Commit 62ca36dedea657f53d0ec64bc52f65ab269adfdc

Authored by YunaiV
2 parents 72dc28a6 ac1ced74

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

Showing 670 changed files with 57714 additions and 441 deletions

Too many changes.

To preserve performance only 100 of 670 files are displayed.

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

189 KB

yudao-admin-server/pom.xml
... ... @@ -117,7 +117,15 @@
117 117 <artifactId>yudao-spring-boot-starter-excel</artifactId>
118 118 </dependency>
119 119  
  120 + <dependency>
  121 + <groupId>cn.iocoder.boot</groupId>
  122 + <artifactId>yudao-spring-boot-starter-tenant</artifactId>
  123 + </dependency>
120 124  
  125 + <dependency>
  126 + <groupId>cn.iocoder.boot</groupId>
  127 + <artifactId>yudao-spring-boot-starter-data-permission</artifactId>
  128 + </dependency>
121 129  
122 130 <dependency>
123 131 <groupId>org.apache.velocity</groupId>
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/config/AsyncConfiguration.java deleted
1   -package cn.iocoder.yudao.adminserver.framework.async.config;
2   -
3   -import org.springframework.context.annotation.Configuration;
4   -import org.springframework.scheduling.annotation.EnableAsync;
5   -
6   -@Configuration
7   -@EnableAsync
8   -public class AsyncConfiguration {
9   -}
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/security/SecurityConfiguration.java
... ... @@ -22,9 +22,11 @@ public class SecurityConfiguration {
22 22 @Bean
23 23 public Customizer<ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry> authorizeRequestsCustomizer() {
24 24 return registry -> {
25   - // 通用的接口,可匿名访问 TODO 芋艿:需要抽象出去
  25 + // 验证码的接口
26 26 registry.antMatchers(api("/system/captcha/**")).anonymous();
27   - // Spring Boot Admin Server 的安全配置 TODO 芋艿:需要抽象出去
  27 + // 获得租户编号的接口
  28 + registry.antMatchers(api("/system/tenant/get-id-by-name")).anonymous();
  29 + // Spring Boot Admin Server 的安全配置
28 30 registry.antMatchers(adminSeverContextPath).anonymous()
29 31 .antMatchers(adminSeverContextPath + "/**").anonymous();
30 32 // 短信回调 API
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/message/config/InfConfigRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.infra.mq.message.config;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
5 5  
6 6 /**
7 7 * 配置数据刷新 Message
8 8 */
9 9 @Data
10   -public class InfConfigRefreshMessage implements ChannelMessage {
  10 +public class InfConfigRefreshMessage extends AbstractChannelMessage {
11 11  
12 12 @Override
13 13 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/infra/mq/producer/config/InfConfigProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.infra.mq.producer.config;
2 2  
3 3 import cn.iocoder.yudao.adminserver.modules.infra.mq.message.config.InfConfigRefreshMessage;
4   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -14,14 +13,14 @@ import javax.annotation.Resource;
14 13 public class InfConfigProducer {
15 14  
16 15 @Resource
17   - private StringRedisTemplate stringRedisTemplate;
  16 + private RedisMQTemplate redisMQTemplate;
18 17  
19 18 /**
20 19 * 发送 {@link InfConfigRefreshMessage} 消息
21 20 */
22 21 public void sendConfigRefreshMessage() {
23 22 InfConfigRefreshMessage message = new InfConfigRefreshMessage();
24   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  23 + redisMQTemplate.send(message);
25 24 }
26 25  
27 26 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/auth/SysAuthController.http
1 1 ### 请求 /login 接口 => 成功
2 2 POST {{baseUrl}}/login
3 3 Content-Type: application/json
  4 +tenant-id: 1
4 5  
5 6 {
6 7 "username": "admin",
7 8 "password": "admin123",
8   - "uuid": "9b2ffbc1-7425-4155-9894-9d5c08541d62",
  9 + "uuid": "3acd87a09a4f48fb9118333780e94883",
9 10 "code": "1024"
10 11 }
11 12  
12 13 ### 请求 /get-permission-info 接口 => 成功
13 14 GET {{baseUrl}}/get-permission-info
14 15 Authorization: Bearer {{token}}
  16 +tenant-id: 1
15 17  
16 18 ### 请求 /list-menus 接口 => 成功
17 19 GET {{baseUrl}}/list-menus
18 20 Authorization: Bearer {{token}}
  21 +#Authorization: Bearer a6aa7714a2e44c95aaa8a2c5adc2a67a
  22 +tenant-id: 1
19 23  
20 24 ### 请求 /druid/xxx 接口 => 失败 TODO 临时测试
21 25 GET http://127.0.0.1:8080/druid/123
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/SysTenantController.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.*;
  4 +import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
  5 +import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
  6 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  7 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
  10 +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  11 +import io.swagger.annotations.Api;
  12 +import io.swagger.annotations.ApiImplicitParam;
  13 +import io.swagger.annotations.ApiOperation;
  14 +import org.springframework.security.access.prepost.PreAuthorize;
  15 +import org.springframework.web.bind.annotation.*;
  16 +
  17 +import javax.annotation.Resource;
  18 +import javax.servlet.http.HttpServletResponse;
  19 +import javax.validation.Valid;
  20 +import java.io.IOException;
  21 +import java.util.Collection;
  22 +import java.util.List;
  23 +
  24 +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  25 +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
  26 +
  27 +@Api(tags = "租户")
  28 +@RestController
  29 +@RequestMapping("/system/tenant")
  30 +public class SysTenantController {
  31 +
  32 + @Resource
  33 + private SysTenantService tenantService;
  34 +
  35 + @GetMapping("/get-id-by-name")
  36 + @ApiOperation(value = "使用租户名,获得租户编号", notes = "登录界面,根据用户的租户名,获得租户编号")
  37 + @ApiImplicitParam(name = "name", value = "租户名", required = true, example = "芋道源码", dataTypeClass = Long.class)
  38 + public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
  39 + SysTenantDO tenantDO = tenantService.getTenantByName(name);
  40 + return success(tenantDO != null ? tenantDO.getId() : null);
  41 + }
  42 +
  43 + @PostMapping("/create")
  44 + @ApiOperation("创建租户")
  45 + @PreAuthorize("@ss.hasPermission('system:tenant:create')")
  46 + public CommonResult<Long> createTenant(@Valid @RequestBody SysTenantCreateReqVO createReqVO) {
  47 + return success(tenantService.createTenant(createReqVO));
  48 + }
  49 +
  50 + @PutMapping("/update")
  51 + @ApiOperation("更新租户")
  52 + @PreAuthorize("@ss.hasPermission('system:tenant:update')")
  53 + public CommonResult<Boolean> updateTenant(@Valid @RequestBody SysTenantUpdateReqVO updateReqVO) {
  54 + tenantService.updateTenant(updateReqVO);
  55 + return success(true);
  56 + }
  57 +
  58 + @DeleteMapping("/delete")
  59 + @ApiOperation("删除租户")
  60 + @ApiImplicitParam(name = "id", value = "编号", required = true)
  61 + @PreAuthorize("@ss.hasPermission('system:tenant:delete')")
  62 + public CommonResult<Boolean> deleteTenant(@RequestParam("id") Long id) {
  63 + tenantService.deleteTenant(id);
  64 + return success(true);
  65 + }
  66 +
  67 + @GetMapping("/get")
  68 + @ApiOperation("获得租户")
  69 + @ApiImplicitParam(name = "id", value = "编号", required = true, example = "1024", dataTypeClass = Long.class)
  70 + @PreAuthorize("@ss.hasPermission('system:tenant:query')")
  71 + public CommonResult<SysTenantRespVO> getTenant(@RequestParam("id") Long id) {
  72 + SysTenantDO tenant = tenantService.getTenant(id);
  73 + return success(SysTenantConvert.INSTANCE.convert(tenant));
  74 + }
  75 +
  76 + @GetMapping("/list")
  77 + @ApiOperation("获得租户列表")
  78 + @ApiImplicitParam(name = "ids", value = "编号列表", required = true, example = "1024,2048", dataTypeClass = List.class)
  79 + @PreAuthorize("@ss.hasPermission('system:tenant:query')")
  80 + public CommonResult<List<SysTenantRespVO>> getTenantList(@RequestParam("ids") Collection<Long> ids) {
  81 + List<SysTenantDO> list = tenantService.getTenantList(ids);
  82 + return success(SysTenantConvert.INSTANCE.convertList(list));
  83 + }
  84 +
  85 + @GetMapping("/page")
  86 + @ApiOperation("获得租户分页")
  87 + @PreAuthorize("@ss.hasPermission('system:tenant:query')")
  88 + public CommonResult<PageResult<SysTenantRespVO>> getTenantPage(@Valid SysTenantPageReqVO pageVO) {
  89 + PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(pageVO);
  90 + return success(SysTenantConvert.INSTANCE.convertPage(pageResult));
  91 + }
  92 +
  93 + @GetMapping("/export-excel")
  94 + @ApiOperation("导出租户 Excel")
  95 + @PreAuthorize("@ss.hasPermission('system:tenant:export')")
  96 + @OperateLog(type = EXPORT)
  97 + public void exportTenantExcel(@Valid SysTenantExportReqVO exportReqVO,
  98 + HttpServletResponse response) throws IOException {
  99 + List<SysTenantDO> list = tenantService.getTenantList(exportReqVO);
  100 + // 导出 Excel
  101 + List<SysTenantExcelVO> datas = SysTenantConvert.INSTANCE.convertList02(list);
  102 + ExcelUtils.write(response, "租户.xls", "数据", SysTenantExcelVO.class, datas);
  103 + }
  104 +
  105 +
  106 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantBaseVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +/**
  9 +* 租户 Base VO,提供给添加、修改、详细的子 VO 使用
  10 +* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
  11 +*/
  12 +@Data
  13 +public class SysTenantBaseVO {
  14 +
  15 + @ApiModelProperty(value = "租户名", required = true, example = "芋道")
  16 + @NotNull(message = "租户名不能为空")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "联系人", required = true, example = "芋艿")
  20 + @NotNull(message = "联系人不能为空")
  21 + private String contactName;
  22 +
  23 + @ApiModelProperty(value = "联系手机", example = "15601691300")
  24 + private String contactMobile;
  25 +
  26 + @ApiModelProperty(value = "租户状态(0正常 1停用)", required = true, example = "1")
  27 + @NotNull(message = "租户状态(0正常 1停用)不能为空")
  28 + private Integer status;
  29 +
  30 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantCreateReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@ApiModel("租户创建 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SysTenantCreateReqVO extends SysTenantBaseVO {
  13 +
  14 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExcelVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +
  7 +import com.alibaba.excel.annotation.ExcelProperty;
  8 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  9 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  10 +
  11 +
  12 +/**
  13 + * 租户 Excel VO
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +@Data
  18 +public class SysTenantExcelVO {
  19 +
  20 + @ExcelProperty("租户编号")
  21 + private Long id;
  22 +
  23 + @ExcelProperty("租户名")
  24 + private String name;
  25 +
  26 + @ExcelProperty("联系人")
  27 + private String contactName;
  28 +
  29 + @ExcelProperty("联系手机")
  30 + private String contactMobile;
  31 +
  32 + @ExcelProperty(value = "租户状态(0正常 1停用)", converter = DictConvert.class)
  33 + @DictFormat("sys_common_status") // TODO 代码优化:建议设置到对应的 XXXDictTypeConstants 枚举类中
  34 + private Integer status;
  35 +
  36 + @ExcelProperty("创建时间")
  37 + private Date createTime;
  38 +
  39 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantExportReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import io.swagger.annotations.ApiModel;
  4 +import io.swagger.annotations.ApiModelProperty;
  5 +import lombok.Data;
  6 +import org.springframework.format.annotation.DateTimeFormat;
  7 +
  8 +import java.util.Date;
  9 +
  10 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  11 +
  12 +@ApiModel(value = "租户 Excel 导出 Request VO", description = "参数和 SysTenantPageReqVO 是一致的")
  13 +@Data
  14 +public class SysTenantExportReqVO {
  15 +
  16 + @ApiModelProperty(value = "租户名", example = "芋道")
  17 + private String name;
  18 +
  19 + @ApiModelProperty(value = "联系人", example = "芋艿")
  20 + private String contactName;
  21 +
  22 + @ApiModelProperty(value = "联系手机", example = "15601691300")
  23 + private String contactMobile;
  24 +
  25 + @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
  26 + private Integer status;
  27 +
  28 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  29 + @ApiModelProperty(value = "开始创建时间")
  30 + private Date beginCreateTime;
  31 +
  32 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  33 + @ApiModelProperty(value = "结束创建时间")
  34 + private Date endCreateTime;
  35 +
  36 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantPageReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import cn.iocoder.yudao.framework.common.pojo.PageParam;
  4 +import io.swagger.annotations.ApiModel;
  5 +import io.swagger.annotations.ApiModelProperty;
  6 +import lombok.Data;
  7 +import lombok.EqualsAndHashCode;
  8 +import lombok.ToString;
  9 +import org.springframework.format.annotation.DateTimeFormat;
  10 +
  11 +import java.util.Date;
  12 +
  13 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
  14 +
  15 +@ApiModel("租户分页 Request VO")
  16 +@Data
  17 +@EqualsAndHashCode(callSuper = true)
  18 +@ToString(callSuper = true)
  19 +public class SysTenantPageReqVO extends PageParam {
  20 +
  21 + @ApiModelProperty(value = "租户名", example = "芋道")
  22 + private String name;
  23 +
  24 + @ApiModelProperty(value = "联系人", example = "芋艿")
  25 + private String contactName;
  26 +
  27 + @ApiModelProperty(value = "联系手机", example = "15601691300")
  28 + private String contactMobile;
  29 +
  30 + @ApiModelProperty(value = "租户状态(0正常 1停用)", example = "1")
  31 + private Integer status;
  32 +
  33 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  34 + @ApiModelProperty(value = "开始创建时间")
  35 + private Date beginCreateTime;
  36 +
  37 + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
  38 + @ApiModelProperty(value = "结束创建时间")
  39 + private Date endCreateTime;
  40 +
  41 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantRespVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +
  7 +@ApiModel("租户 Response VO")
  8 +@Data
  9 +@EqualsAndHashCode(callSuper = true)
  10 +@ToString(callSuper = true)
  11 +public class SysTenantRespVO extends SysTenantBaseVO {
  12 +
  13 + @ApiModelProperty(value = "租户编号", required = true, example = "1024")
  14 + private Long id;
  15 +
  16 + @ApiModelProperty(value = "创建时间", required = true)
  17 + private Date createTime;
  18 +
  19 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/tenant/vo/SysTenantUpdateReqVO.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo;
  2 +
  3 +import lombok.*;
  4 +import java.util.*;
  5 +import io.swagger.annotations.*;
  6 +import javax.validation.constraints.*;
  7 +
  8 +@ApiModel("租户更新 Request VO")
  9 +@Data
  10 +@EqualsAndHashCode(callSuper = true)
  11 +@ToString(callSuper = true)
  12 +public class SysTenantUpdateReqVO extends SysTenantBaseVO {
  13 +
  14 + @ApiModelProperty(value = "租户编号", required = true, example = "1024")
  15 + @NotNull(message = "租户编号不能为空")
  16 + private Long id;
  17 +
  18 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/controller/user/SysUserController.http
1 1 ### 请求 /system/user/page 接口 => 没有权限
2 2 GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
3   -Authorization: Bearer test104 # 使用测试账号
  3 +Authorization: Bearer test1 # 使用测试账号
  4 +tenant-id: 1
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/convert/tenant/SysTenantConvert.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.convert.tenant;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExcelVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantRespVO;
  6 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +import org.mapstruct.Mapper;
  10 +import org.mapstruct.factory.Mappers;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 租户 Convert
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +@Mapper
  20 +public interface SysTenantConvert {
  21 +
  22 + SysTenantConvert INSTANCE = Mappers.getMapper(SysTenantConvert.class);
  23 +
  24 + SysTenantDO convert(SysTenantCreateReqVO bean);
  25 +
  26 + SysTenantDO convert(SysTenantUpdateReqVO bean);
  27 +
  28 + SysTenantRespVO convert(SysTenantDO bean);
  29 +
  30 + List<SysTenantRespVO> convertList(List<SysTenantDO> list);
  31 +
  32 + PageResult<SysTenantRespVO> convertPage(PageResult<SysTenantDO> page);
  33 +
  34 + List<SysTenantExcelVO> convertList02(List<SysTenantDO> list);
  35 +
  36 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysDeptDO.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 5 import com.baomidou.mybatisplus.annotation.TableId;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
7 7 import lombok.Data;
... ... @@ -15,7 +15,7 @@ import lombok.EqualsAndHashCode;
15 15 @TableName("sys_dept")
16 16 @Data
17 17 @EqualsAndHashCode(callSuper = true)
18   -public class SysDeptDO extends BaseDO {
  18 +public class SysDeptDO extends TenantBaseDO {
19 19  
20 20 /**
21 21 * 部门ID
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/dept/SysPostDO.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 5 import com.baomidou.mybatisplus.annotation.TableId;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
7 7 import lombok.Data;
... ... @@ -15,14 +15,13 @@ import lombok.EqualsAndHashCode;
15 15 @TableName("sys_post")
16 16 @Data
17 17 @EqualsAndHashCode(callSuper = true)
18   -public class SysPostDO extends BaseDO {
  18 +public class SysPostDO extends TenantBaseDO {
19 19  
20 20 /**
21 21 * 岗位序号
22 22 */
23 23 @TableId
24 24 private Long id;
25   -
26 25 /**
27 26 * 岗位名称
28 27 */
... ...
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;
3 3 import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
4 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5 5 import cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum;
6   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  6 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
7 7 import com.baomidou.mybatisplus.annotation.TableField;
8 8 import com.baomidou.mybatisplus.annotation.TableId;
9 9 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -22,7 +22,7 @@ import java.util.Map;
22 22 @TableName(value = "sys_operate_log", autoResultMap = true)
23 23 @Data
24 24 @EqualsAndHashCode(callSuper = true)
25   -public class SysOperateLogDO extends BaseDO {
  25 +public class SysOperateLogDO extends TenantBaseDO {
26 26  
27 27 /**
28 28 * {@link #javaMethodArgs} 的最大长度
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/dataobject/notice/SysNoticeDO.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.notice;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 3 import cn.iocoder.yudao.adminserver.modules.system.enums.notice.SysNoticeTypeEnum;
  4 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  5 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
6 6 import com.baomidou.mybatisplus.annotation.TableField;
7 7 import com.baomidou.mybatisplus.annotation.TableName;
8 8 import lombok.Data;
... ... @@ -16,7 +16,7 @@ import lombok.EqualsAndHashCode;
16 16 @TableName("sys_notice")
17 17 @Data
18 18 @EqualsAndHashCode(callSuper = true)
19   -public class SysNoticeDO extends BaseDO {
  19 +public class SysNoticeDO extends TenantBaseDO {
20 20  
21 21 /**
22 22 * 公告ID
... ...
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&lt;SysDeptDO&gt; {
24 24 }
25 25  
26 26 default Integer selectCountByParentId(Long parentId) {
27   - return selectCount(new QueryWrapper<SysDeptDO>().eq("parent_id", parentId));
  27 + return selectCount("parent_id", parentId);
28 28 }
29 29  
30 30 default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
... ...
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&lt;SysMenuDO&gt; {
19 19 }
20 20  
21 21 default Integer selectCountByParentId(Long parentId) {
22   - return selectCount(new QueryWrapper<SysMenuDO>().eq("parent_id", parentId));
  22 + return selectCount("parent_id", parentId);
23 23 }
24 24  
25 25 default List<SysMenuDO> selectList(SysMenuListReqVO reqVO) {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/dal/mysql/tenant/SysTenantMapper.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
  5 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  6 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  7 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  8 +import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  9 +import org.apache.ibatis.annotations.Mapper;
  10 +
  11 +import java.util.List;
  12 +
  13 +/**
  14 + * 租户 Mapper
  15 + *
  16 + * @author 芋道源码
  17 + */
  18 +@Mapper
  19 +public interface SysTenantMapper extends BaseMapperX<SysTenantDO> {
  20 +
  21 + default PageResult<SysTenantDO> selectPage(SysTenantPageReqVO reqVO) {
  22 + return selectPage(reqVO, new QueryWrapperX<SysTenantDO>()
  23 + .likeIfPresent("name", reqVO.getName())
  24 + .likeIfPresent("contact_name", reqVO.getContactName())
  25 + .likeIfPresent("contact_mobile", reqVO.getContactMobile())
  26 + .eqIfPresent("status", reqVO.getStatus())
  27 + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  28 + .orderByDesc("id"));
  29 + }
  30 +
  31 + default List<SysTenantDO> selectList(SysTenantExportReqVO reqVO) {
  32 + return selectList(new QueryWrapperX<SysTenantDO>()
  33 + .likeIfPresent("name", reqVO.getName())
  34 + .likeIfPresent("contact_name", reqVO.getContactName())
  35 + .likeIfPresent("contact_mobile", reqVO.getContactMobile())
  36 + .eqIfPresent("status", reqVO.getStatus())
  37 + .betweenIfPresent("create_time", reqVO.getBeginCreateTime(), reqVO.getEndCreateTime())
  38 + .orderByDesc("id"));
  39 + }
  40 +
  41 + default SysTenantDO selectByName(String name) {
  42 + return selectOne("name", name);
  43 + }
  44 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/enums/SysErrorCodeConstants.java
... ... @@ -85,10 +85,12 @@ public interface SysErrorCodeConstants {
85 85 ErrorCode SMS_TEMPLATE_NOT_EXISTS = new ErrorCode(1002011000, "短信模板不存在");
86 86 ErrorCode SMS_TEMPLATE_CODE_DUPLICATE = new ErrorCode(1002011001, "已经存在编码为【{}】的短信模板");
87 87  
  88 + // ========== 租户模块 1002012000 ==========
  89 + ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002012000, "租户不存在");
  90 +
88 91 // ========== 错误码模块 1002013000 ==========
89 92 ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002013000, "错误码不存在");
90 93 ErrorCode ERROR_CODE_DUPLICATE = new ErrorCode(1002013001, "已经存在编码为【{}】的错误码");
91 94  
92 95  
93   -
94 96 }
... ...
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;
12 12 @Data
13 13 public class CaptchaProperties {
14 14  
  15 + private static final Boolean ENABLE_DEFAULT = true;
  16 +
  17 + /**
  18 + * 是否开启
  19 + * 注意,这里仅仅是后端 Server 是否校验,暂时不控制前端的逻辑
  20 + */
  21 + private Boolean enable = ENABLE_DEFAULT;
15 22 /**
16 23 * 验证码的过期时间
17 24 */
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/config/SysDataPermissionConfiguration.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission.config;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
  4 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.user.SysUserDO;
  5 +import cn.iocoder.yudao.framework.datapermission.core.dept.rule.DeptDataPermissionRuleCustomizer;
  6 +import org.springframework.context.annotation.Bean;
  7 +import org.springframework.context.annotation.Configuration;
  8 +
  9 +/**
  10 + * system 模块的数据权限 Configuration
  11 + *
  12 + * @author 芋道源码
  13 + */
  14 +@Configuration
  15 +public class SysDataPermissionConfiguration {
  16 +
  17 + @Bean
  18 + public DeptDataPermissionRuleCustomizer sysDeptDataPermissionRuleCustomizer() {
  19 + return rule -> {
  20 + rule.addDeptColumn(SysUserDO.class);
  21 + rule.addDeptColumn(SysDeptDO.class, "id");
  22 + };
  23 + }
  24 +
  25 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/framework/async/package-info.java renamed to yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/framework/datapermission/package-info.java
1 1 /**
2   - * 异步执行,基于 Spring @Async 实现
  2 + * system 模块的数据权限配置
3 3 */
4   -package cn.iocoder.yudao.adminserver.framework.async;
  4 +package cn.iocoder.yudao.adminserver.modules.system.framework.datapermission;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
4 4 import cn.iocoder.yudao.adminserver.modules.system.service.auth.SysUserSessionService;
  5 +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
5 6 import lombok.extern.slf4j.Slf4j;
6 7 import org.springframework.stereotype.Component;
7 8  
... ... @@ -13,6 +14,7 @@ import javax.annotation.Resource;
13 14 * @author 願
14 15 */
15 16 @Component
  17 +@TenantJob
16 18 @Slf4j
17 19 public class SysUserSessionTimeoutJob implements JobHandler {
18 20  
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dept/SysDeptRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dept;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 部门数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysDeptRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysDeptRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/dict/SysDictDataRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.dict;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 字典数据数据刷新 Message
8 9 */
9 10 @Data
10   -public class SysDictDataRefreshMessage implements ChannelMessage {
  11 +@EqualsAndHashCode(callSuper = true)
  12 +public class SysDictDataRefreshMessage extends AbstractChannelMessage {
11 13  
12 14 @Override
13 15 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/mail/SysMailSendMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.mail;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.stream.StreamMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 import javax.validation.constraints.NotNull;
7 8 import java.util.Map;
... ... @@ -12,7 +13,8 @@ import java.util.Map;
12 13 * @author 芋道源码
13 14 */
14 15 @Data
15   -public class SysMailSendMessage implements StreamMessage {
  16 +@EqualsAndHashCode(callSuper = true)
  17 +public class SysMailSendMessage extends AbstractStreamMessage {
16 18  
17 19 /**
18 20 * 邮箱地址
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysMenuRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 菜单数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysMenuRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysMenuRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleMenuRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 角色与菜单数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysRoleMenuRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysRoleMenuRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/permission/SysRoleRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 角色数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysRoleRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysRoleRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsChannelRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 短信渠道的数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysSmsChannelRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysSmsChannelRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/message/sms/SysSmsTemplateRefreshMessage.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.message.sms;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.pubsub.ChannelMessage;
  3 +import cn.iocoder.yudao.framework.mq.core.pubsub.AbstractChannelMessage;
4 4 import lombok.Data;
  5 +import lombok.EqualsAndHashCode;
5 6  
6 7 /**
7 8 * 短信模板的数据刷新 Message
  9 + *
  10 + * @author 芋道源码
8 11 */
9 12 @Data
10   -public class SysSmsTemplateRefreshMessage implements ChannelMessage {
  13 +@EqualsAndHashCode(callSuper = true)
  14 +public class SysSmsTemplateRefreshMessage extends AbstractChannelMessage {
11 15  
12 16 @Override
13 17 public String getChannel() {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dept/SysDeptProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dept;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
4 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dept.SysDeptRefreshMessage;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -14,14 +13,14 @@ import javax.annotation.Resource;
14 13 public class SysDeptProducer {
15 14  
16 15 @Resource
17   - private StringRedisTemplate stringRedisTemplate;
  16 + private RedisMQTemplate redisMQTemplate;
18 17  
19 18 /**
20 19 * 发送 {@link SysDeptRefreshMessage} 消息
21 20 */
22 21 public void sendDeptRefreshMessage() {
23 22 SysDeptRefreshMessage message = new SysDeptRefreshMessage();
24   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  23 + redisMQTemplate.send(message);
25 24 }
26 25  
27 26 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/dict/SysDictDataProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.dict;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
4 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.dict.SysDictDataRefreshMessage;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -14,14 +13,14 @@ import javax.annotation.Resource;
14 13 public class SysDictDataProducer {
15 14  
16 15 @Resource
17   - private StringRedisTemplate stringRedisTemplate;
  16 + private RedisMQTemplate redisMQTemplate;
18 17  
19 18 /**
20 19 * 发送 {@link SysDictDataRefreshMessage} 消息
21 20 */
22 21 public void sendDictDataRefreshMessage() {
23 22 SysDictDataRefreshMessage message = new SysDictDataRefreshMessage();
24   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  23 + redisMQTemplate.send(message);
25 24 }
26 25  
27 26 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysMenuProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
4 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysMenuRefreshMessage;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -14,14 +13,14 @@ import javax.annotation.Resource;
14 13 public class SysMenuProducer {
15 14  
16 15 @Resource
17   - private StringRedisTemplate stringRedisTemplate;
  16 + private RedisMQTemplate redisMQTemplate;
18 17  
19 18 /**
20 19 * 发送 {@link SysMenuRefreshMessage} 消息
21 20 */
22 21 public void sendMenuRefreshMessage() {
23 22 SysMenuRefreshMessage message = new SysMenuRefreshMessage();
24   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  23 + redisMQTemplate.send(message);
25 24 }
26 25  
27 26 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysPermissionProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
4 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleMenuRefreshMessage;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -14,14 +13,14 @@ import javax.annotation.Resource;
14 13 public class SysPermissionProducer {
15 14  
16 15 @Resource
17   - private StringRedisTemplate stringRedisTemplate;
  16 + private RedisMQTemplate redisMQTemplate;
18 17  
19 18 /**
20 19 * 发送 {@link SysRoleMenuRefreshMessage} 消息
21 20 */
22 21 public void sendRoleMenuRefreshMessage() {
23 22 SysRoleMenuRefreshMessage message = new SysRoleMenuRefreshMessage();
24   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  23 + redisMQTemplate.send(message);
25 24 }
26 25  
27 26 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/permission/SysRoleProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission;
2 2  
3   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
4 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.permission.SysRoleRefreshMessage;
5   -import org.springframework.data.redis.core.StringRedisTemplate;
  4 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 5 import org.springframework.stereotype.Component;
7 6  
8 7 import javax.annotation.Resource;
... ... @@ -16,14 +15,14 @@ import javax.annotation.Resource;
16 15 public class SysRoleProducer {
17 16  
18 17 @Resource
19   - private StringRedisTemplate stringRedisTemplate;
  18 + private RedisMQTemplate redisMQTemplate;
20 19  
21 20 /**
22 21 * 发送 {@link SysRoleRefreshMessage} 消息
23 22 */
24 23 public void sendRoleRefreshMessage() {
25 24 SysRoleRefreshMessage message = new SysRoleRefreshMessage();
26   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  25 + redisMQTemplate.send(message);
27 26 }
28 27  
29 28 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/mq/producer/sms/SysSmsProducer.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.mq.producer.sms;
2 2  
3   -import cn.iocoder.yudao.framework.common.core.KeyValue;
4   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
5 3 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsChannelRefreshMessage;
6 4 import cn.iocoder.yudao.adminserver.modules.system.mq.message.sms.SysSmsTemplateRefreshMessage;
  5 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
7 6 import lombok.extern.slf4j.Slf4j;
8   -import org.springframework.data.redis.core.StringRedisTemplate;
9 7 import org.springframework.stereotype.Component;
10 8  
11 9 import javax.annotation.Resource;
12   -import java.util.List;
13 10  
14 11 /**
15 12 * Sms 短信相关消息的 Producer
... ... @@ -22,14 +19,14 @@ import java.util.List;
22 19 public class SysSmsProducer {
23 20  
24 21 @Resource
25   - private StringRedisTemplate stringRedisTemplate;
  22 + private RedisMQTemplate redisMQTemplate;
26 23  
27 24 /**
28 25 * 发送 {@link SysSmsChannelRefreshMessage} 消息
29 26 */
30 27 public void sendSmsChannelRefreshMessage() {
31 28 SysSmsChannelRefreshMessage message = new SysSmsChannelRefreshMessage();
32   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  29 + redisMQTemplate.send(message);
33 30 }
34 31  
35 32 /**
... ... @@ -37,7 +34,7 @@ public class SysSmsProducer {
37 34 */
38 35 public void sendSmsTemplateRefreshMessage() {
39 36 SysSmsTemplateRefreshMessage message = new SysSmsTemplateRefreshMessage();
40   - RedisMessageUtils.sendChannelMessage(stringRedisTemplate, message);
  37 + redisMQTemplate.send(message);
41 38 }
42 39  
43 40 }
... ...
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 {
92 92 throw new UsernameNotFoundException(username);
93 93 }
94 94 // 创建 LoginUser 对象
95   - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
96   - loginUser.setPostIds(user.getPostIds());
97   - return loginUser;
  95 + return this.buildLoginUser(user);
98 96 }
99 97  
100 98 @Override
... ... @@ -107,9 +105,7 @@ public class SysAuthServiceImpl implements SysAuthService {
107 105 this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_MOCK, SysLoginResultEnum.SUCCESS);
108 106  
109 107 // 创建 LoginUser 对象
110   - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
111   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
112   - return loginUser;
  108 + return this.buildLoginUser(user);
113 109 }
114 110  
115 111 @Override
... ... @@ -117,10 +113,9 @@ public class SysAuthServiceImpl implements SysAuthService {
117 113 // 判断验证码是否正确
118 114 this.verifyCaptcha(reqVO.getUsername(), reqVO.getUuid(), reqVO.getCode());
119 115  
120   - // 使用账号密码,进行登录。
  116 + // 使用账号密码,进行登录
121 117 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
122   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
123   - loginUser.setGroups(this.getUserPosts(loginUser.getPostIds()));
  118 +
124 119 // 缓存登陆用户到 Redis 中,返回 sessionId 编号
125 120 return userSessionCoreService.createUserSession(loginUser, userIp, userAgent);
126 121 }
... ... @@ -133,9 +128,13 @@ public class SysAuthServiceImpl implements SysAuthService {
133 128 }
134 129  
135 130 private void verifyCaptcha(String username, String captchaUUID, String captchaCode) {
  131 + // 如果验证码关闭,则不进行校验
  132 + if (!captchaService.isCaptchaEnable()) {
  133 + return;
  134 + }
  135 + // 验证码不存在
136 136 final SysLoginLogTypeEnum logTypeEnum = SysLoginLogTypeEnum.LOGIN_USERNAME;
137 137 String code = captchaService.getCaptchaCode(captchaUUID);
138   - // 验证码不存在
139 138 if (code == null) {
140 139 // 创建登录失败日志(验证码不存在)
141 140 this.createLoginLog(username, logTypeEnum, SysLoginResultEnum.CAPTCHA_NOT_FOUND);
... ... @@ -230,8 +229,7 @@ public class SysAuthServiceImpl implements SysAuthService {
230 229 this.createLoginLog(user.getUsername(), SysLoginLogTypeEnum.LOGIN_SOCIAL, SysLoginResultEnum.SUCCESS);
231 230  
232 231 // 创建 LoginUser 对象
233   - LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
234   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
  232 + LoginUser loginUser = this.buildLoginUser(user);
235 233  
236 234 // 绑定社交用户(更新)
237 235 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
... ... @@ -248,7 +246,6 @@ public class SysAuthServiceImpl implements SysAuthService {
248 246  
249 247 // 使用账号密码,进行登录。
250 248 LoginUser loginUser = this.login0(reqVO.getUsername(), reqVO.getPassword());
251   - loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId())); // 获取用户角色列表
252 249  
253 250 // 绑定社交用户(新增)
254 251 socialService.bindSocialUser(loginUser.getId(), reqVO.getType(), authUser, userTypeEnum);
... ... @@ -301,15 +298,14 @@ public class SysAuthServiceImpl implements SysAuthService {
301 298 return null;
302 299 }
303 300 // 刷新 LoginUser 缓存
304   - this.refreshLoginUserCache(token, loginUser);
305   - return loginUser;
  301 + return this.refreshLoginUserCache(token, loginUser);
306 302 }
307 303  
308   - private void refreshLoginUserCache(String token, LoginUser loginUser) {
  304 + private LoginUser refreshLoginUserCache(String token, LoginUser loginUser) {
309 305 // 每 1/3 的 Session 超时时间,刷新 LoginUser 缓存
310 306 if (System.currentTimeMillis() - loginUser.getUpdateTime().getTime() <
311 307 userSessionCoreService.getSessionTimeoutMillis() / 3) {
312   - return;
  308 + return loginUser;
313 309 }
314 310  
315 311 // 重新加载 SysUserDO 信息
... ... @@ -319,9 +315,18 @@ public class SysAuthServiceImpl implements SysAuthService {
319 315 }
320 316  
321 317 // 刷新 LoginUser 缓存
  318 + LoginUser newLoginUser= this.buildLoginUser(user);
  319 + userSessionCoreService.refreshUserSession(token, newLoginUser);
  320 + return newLoginUser;
  321 + }
  322 +
  323 + private LoginUser buildLoginUser(SysUserDO user) {
  324 + LoginUser loginUser = SysAuthConvert.INSTANCE.convert(user);
  325 + // 补全字段
322 326 loginUser.setDeptId(user.getDeptId());
323 327 loginUser.setRoleIds(this.getUserRoleIds(loginUser.getId()));
324   - userSessionCoreService.refreshUserSession(token, loginUser);
  328 + loginUser.setGroups(this.getUserPosts(user.getPostIds()));
  329 + return loginUser;
325 330 }
326 331  
327 332 }
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/SysCaptchaService.java
... ... @@ -15,6 +15,13 @@ public interface SysCaptchaService {
15 15 SysCaptchaImageRespVO getCaptchaImage();
16 16  
17 17 /**
  18 + * 是否开启图片验证码
  19 + *
  20 + * @return 是否
  21 + */
  22 + Boolean isCaptchaEnable();
  23 +
  24 + /**
18 25 * 获得 uuid 对应的验证码
19 26 *
20 27 * @param uuid 验证码编号
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/common/impl/SysCaptchaServiceImpl.java
... ... @@ -36,6 +36,11 @@ public class SysCaptchaServiceImpl implements SysCaptchaService {
36 36 }
37 37  
38 38 @Override
  39 + public Boolean isCaptchaEnable() {
  40 + return captchaProperties.getEnable();
  41 + }
  42 +
  43 + @Override
39 44 public String getCaptchaCode(String uuid) {
40 45 return captchaRedisDAO.get(uuid);
41 46 }
... ...
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 {
169 169  
170 170 @Override
171 171 public List<SysDeptDO> getDeptsByParentIdFromCache(Long parentId, boolean recursive) {
172   - List<SysDeptDO> result = new ArrayList<>();
  172 + if (parentId == null) {
  173 + return Collections.emptyList();
  174 + }
  175 + List<SysDeptDO> result = new ArrayList<>(); // TODO 芋艿:待优化,新增缓存,避免每次遍历的计算
173 176 // 递归,简单粗暴
174   - this.listDeptsByParentIdFromCache(result, parentId,
  177 + this.getDeptsByParentIdFromCache(result, parentId,
175 178 recursive ? Integer.MAX_VALUE : 1, // 如果递归获取,则无限;否则,只递归 1 次
176 179 parentDeptCache);
177 180 return result;
... ... @@ -185,8 +188,8 @@ public class SysDeptServiceImpl implements SysDeptService {
185 188 * @param recursiveCount 递归次数
186 189 * @param parentDeptMap 父部门 Map,使用缓存,避免变化
187 190 */
188   - private void listDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
189   - Multimap<Long, SysDeptDO> parentDeptMap) {
  191 + private void getDeptsByParentIdFromCache(List<SysDeptDO> result, Long parentId, int recursiveCount,
  192 + Multimap<Long, SysDeptDO> parentDeptMap) {
190 193 // 递归次数为 0,结束!
191 194 if (recursiveCount == 0) {
192 195 return;
... ... @@ -198,7 +201,7 @@ public class SysDeptServiceImpl implements SysDeptService {
198 201 }
199 202 result.addAll(depts);
200 203 // 继续递归
201   - depts.forEach(dept -> listDeptsByParentIdFromCache(result, dept.getId(),
  204 + depts.forEach(dept -> getDeptsByParentIdFromCache(result, dept.getId(),
202 205 recursiveCount - 1, parentDeptMap));
203 206 }
204 207  
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionService.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
2 2  
  3 +import cn.iocoder.yudao.framework.datapermission.core.dept.service.DeptDataPermissionFrameworkService;
3 4 import cn.iocoder.yudao.framework.security.core.service.SecurityPermissionFrameworkService;
4 5 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
5 6 import org.springframework.lang.Nullable;
... ... @@ -15,7 +16,7 @@ import java.util.Set;
15 16 *
16 17 * @author 芋道源码
17 18 */
18   -public interface SysPermissionService extends SecurityPermissionFrameworkService {
  19 +public interface SysPermissionService extends SecurityPermissionFrameworkService, DeptDataPermissionFrameworkService {
19 20  
20 21 /**
21 22 * 初始化权限的本地缓存
... ...
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;
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.collection.CollectionUtil;
5 5 import cn.hutool.core.util.ArrayUtil;
6   -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
7   -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
8   -import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
  6 +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
9 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysMenuDO;
10 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
11 9 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
12 10 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
  11 +import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
  12 +import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
13 13 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
  14 +import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
14 15 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysMenuService;
15 16 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
16 17 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
17 18 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
18 19 import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
  20 +import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
  21 +import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
  22 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  23 +import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
  24 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
19 25 import com.google.common.collect.ImmutableMultimap;
20 26 import com.google.common.collect.Multimap;
21 27 import com.google.common.collect.Sets;
... ... @@ -40,6 +46,11 @@ import java.util.*;
40 46 public class SysPermissionServiceImpl implements SysPermissionService {
41 47  
42 48 /**
  49 + * LoginUser 的 Context 缓存 Key
  50 + */
  51 + public static final String CONTEXT_KEY = SysPermissionServiceImpl.class.getSimpleName();
  52 +
  53 + /**
43 54 * 定时执行 {@link #schedulePeriodicRefresh()} 的周期
44 55 * 因为已经通过 Redis Pub/Sub 机制,所以频率不需要高
45 56 */
... ... @@ -75,6 +86,8 @@ public class SysPermissionServiceImpl implements SysPermissionService {
75 86 private SysRoleService roleService;
76 87 @Resource
77 88 private SysMenuService menuService;
  89 + @Resource
  90 + private SysDeptService deptService;
78 91  
79 92 @Resource
80 93 private SysPermissionProducer permissionProducer;
... ... @@ -329,4 +342,58 @@ public class SysPermissionServiceImpl implements SysPermissionService {
329 342 return CollUtil.containsAny(userRoles, Sets.newHashSet(roles));
330 343 }
331 344  
  345 + @Override
  346 + public DeptDataPermissionRespDTO getDeptDataPermission(LoginUser loginUser) {
  347 + // 判断是否 context 已经缓存
  348 + DeptDataPermissionRespDTO result = loginUser.getContext(CONTEXT_KEY, DeptDataPermissionRespDTO.class);
  349 + if (result != null) {
  350 + return result;
  351 + }
  352 +
  353 + // 创建 DeptDataPermissionRespDTO 对象
  354 + result = new DeptDataPermissionRespDTO();
  355 + List<SysRoleDO> roles = roleService.getRolesFromCache(loginUser.getRoleIds());
  356 + for (SysRoleDO role : roles) {
  357 + // 为空时,跳过
  358 + if (role.getDataScope() == null) {
  359 + continue;
  360 + }
  361 + // 情况一,ALL
  362 + if (Objects.equals(role.getDataScope(), DataScopeEnum.ALL.getScope())) {
  363 + result.setAll(true);
  364 + continue;
  365 + }
  366 + // 情况二,DEPT_CUSTOM
  367 + if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_CUSTOM.getScope())) {
  368 + CollUtil.addAll(result.getDeptIds(), role.getDataScopeDeptIds());
  369 + // 自定义可见部门时,保证可以看到自己所在的部门。否则,一些场景下可能会有问题。
  370 + // 例如说,登录时,基于 t_user 的 username 查询会可能被 dept_id 过滤掉
  371 + CollUtil.addAll(result.getDeptIds(), loginUser.getDeptId());
  372 + continue;
  373 + }
  374 + // 情况三,DEPT_ONLY
  375 + if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_ONLY.getScope())) {
  376 + CollectionUtils.addIfNotNull(result.getDeptIds(), loginUser.getDeptId());
  377 + continue;
  378 + }
  379 + // 情况四,DEPT_DEPT_AND_CHILD
  380 + if (Objects.equals(role.getDataScope(), DataScopeEnum.DEPT_AND_CHILD.getScope())) {
  381 + List<SysDeptDO> depts = deptService.getDeptsByParentIdFromCache(loginUser.getDeptId(), true);
  382 + CollUtil.addAll(result.getDeptIds(), CollectionUtils.convertList(depts, SysDeptDO::getId));
  383 + continue;
  384 + }
  385 + // 情况五,SELF
  386 + if (Objects.equals(role.getDataScope(), DataScopeEnum.SELF.getScope())) {
  387 + result.setSelf(true);
  388 + continue;
  389 + }
  390 + // 未知情况,error log 即可
  391 + log.error("[getDeptDataPermission][LoginUser({}) role({}) 无法处理]", loginUser.getId(), JsonUtils.toJsonString(result));
  392 + }
  393 +
  394 + // 添加到缓存,并返回
  395 + loginUser.setContext(CONTEXT_KEY, result);
  396 + return result;
  397 + }
  398 +
332 399 }
... ...
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
18 18 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysRoleProducer;
19 19 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
20 20 import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysRoleService;
  21 +import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
21 22 import com.google.common.annotations.VisibleForTesting;
22 23 import com.google.common.collect.ImmutableMap;
23 24 import lombok.extern.slf4j.Slf4j;
... ... @@ -127,6 +128,7 @@ public class SysRoleServiceImpl implements SysRoleService {
127 128 SysRoleDO role = SysRoleConvert.INSTANCE.convert(reqVO);
128 129 role.setType(SysRoleTypeEnum.CUSTOM.getType());
129 130 role.setStatus(CommonStatusEnum.ENABLE.getStatus());
  131 + role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限
130 132 roleMapper.insert(role);
131 133 // 发送刷新消息
132 134 roleProducer.sendRoleRefreshMessage();
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantService.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
  7 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  8 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  9 +
  10 +import javax.validation.Valid;
  11 +import java.util.Collection;
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 租户 Service 接口
  16 + *
  17 + * @author 芋道源码
  18 + */
  19 +public interface SysTenantService {
  20 +
  21 + /**
  22 + * 创建租户
  23 + *
  24 + * @param createReqVO 创建信息
  25 + * @return 编号
  26 + */
  27 + Long createTenant(@Valid SysTenantCreateReqVO createReqVO);
  28 +
  29 + /**
  30 + * 更新租户
  31 + *
  32 + * @param updateReqVO 更新信息
  33 + */
  34 + void updateTenant(@Valid SysTenantUpdateReqVO updateReqVO);
  35 +
  36 + /**
  37 + * 删除租户
  38 + *
  39 + * @param id 编号
  40 + */
  41 + void deleteTenant(Long id);
  42 +
  43 + /**
  44 + * 获得租户
  45 + *
  46 + * @param id 编号
  47 + * @return 租户
  48 + */
  49 + SysTenantDO getTenant(Long id);
  50 +
  51 + /**
  52 + * 获得租户列表
  53 + *
  54 + * @param ids 编号
  55 + * @return 租户列表
  56 + */
  57 + List<SysTenantDO> getTenantList(Collection<Long> ids);
  58 +
  59 + /**
  60 + * 获得租户分页
  61 + *
  62 + * @param pageReqVO 分页查询
  63 + * @return 租户分页
  64 + */
  65 + PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO);
  66 +
  67 + /**
  68 + * 获得租户列表, 用于 Excel 导出
  69 + *
  70 + * @param exportReqVO 查询条件
  71 + * @return 租户列表
  72 + */
  73 + List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO);
  74 +
  75 + /**
  76 + * 获得名字对应的租户
  77 + *
  78 + * @param name 组户名
  79 + * @return 租户
  80 + */
  81 + SysTenantDO getTenantByName(String name);
  82 +
  83 +}
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/impl/SysTenantServiceImpl.java 0 → 100755
  1 +package cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl;
  2 +
  3 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
  7 +import cn.iocoder.yudao.adminserver.modules.system.convert.tenant.SysTenantConvert;
  8 +import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
  9 +import cn.iocoder.yudao.adminserver.modules.system.service.tenant.SysTenantService;
  10 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  11 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  12 +import org.springframework.stereotype.Service;
  13 +import org.springframework.validation.annotation.Validated;
  14 +
  15 +import javax.annotation.Resource;
  16 +import java.util.Collection;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
  21 +
  22 +/**
  23 + * 租户 Service 实现类
  24 + *
  25 + * @author 芋道源码
  26 + */
  27 +@Service
  28 +@Validated
  29 +public class SysTenantServiceImpl implements SysTenantService {
  30 +
  31 + @Resource
  32 + private SysTenantMapper tenantMapper;
  33 +
  34 + @Override
  35 + public Long createTenant(SysTenantCreateReqVO createReqVO) {
  36 + // 插入
  37 + SysTenantDO tenant = SysTenantConvert.INSTANCE.convert(createReqVO);
  38 + tenantMapper.insert(tenant);
  39 + // 返回
  40 + return tenant.getId();
  41 + }
  42 +
  43 + @Override
  44 + public void updateTenant(SysTenantUpdateReqVO updateReqVO) {
  45 + // 校验存在
  46 + this.validateTenantExists(updateReqVO.getId());
  47 + // 更新
  48 + SysTenantDO updateObj = SysTenantConvert.INSTANCE.convert(updateReqVO);
  49 + tenantMapper.updateById(updateObj);
  50 + }
  51 +
  52 + @Override
  53 + public void deleteTenant(Long id) {
  54 + // 校验存在
  55 + this.validateTenantExists(id);
  56 + // 删除
  57 + tenantMapper.deleteById(id);
  58 + }
  59 +
  60 + private void validateTenantExists(Long id) {
  61 + if (tenantMapper.selectById(id) == null) {
  62 + throw exception(TENANT_NOT_EXISTS);
  63 + }
  64 + }
  65 +
  66 + @Override
  67 + public SysTenantDO getTenant(Long id) {
  68 + return tenantMapper.selectById(id);
  69 + }
  70 +
  71 + @Override
  72 + public List<SysTenantDO> getTenantList(Collection<Long> ids) {
  73 + return tenantMapper.selectBatchIds(ids);
  74 + }
  75 +
  76 + @Override
  77 + public PageResult<SysTenantDO> getTenantPage(SysTenantPageReqVO pageReqVO) {
  78 + return tenantMapper.selectPage(pageReqVO);
  79 + }
  80 +
  81 + @Override
  82 + public List<SysTenantDO> getTenantList(SysTenantExportReqVO exportReqVO) {
  83 + return tenantMapper.selectList(exportReqVO);
  84 + }
  85 +
  86 + @Override
  87 + public SysTenantDO getTenantByName(String name) {
  88 + return tenantMapper.selectByName(name);
  89 + }
  90 +
  91 +}
... ...
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;
10 10 import cn.iocoder.yudao.framework.common.pojo.PageParam;
11 11 import cn.iocoder.yudao.framework.common.pojo.PageResult;
12 12 import cn.iocoder.yudao.adminserver.modules.system.framework.codegen.config.CodegenProperties;
  13 +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
13 14 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
14 15 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
15 16 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
... ... @@ -119,6 +120,8 @@ public class ToolCodegenEngine {
119 120 private void initGlobalBindingMap() {
120 121 // 全局配置
121 122 globalBindingMap.put("basePackage", codegenProperties.getBasePackage());
  123 + globalBindingMap.put("baseFrameworkPackage", StrUtil.subBefore(codegenProperties.getBasePackage(),
  124 + '.', true) + '.' + "framework");
122 125 // 全局 Java Bean
123 126 globalBindingMap.put("CommonResultClassName", CommonResult.class.getName());
124 127 globalBindingMap.put("PageResultClassName", PageResult.class.getName());
... ... @@ -134,6 +137,7 @@ public class ToolCodegenEngine {
134 137 globalBindingMap.put("ServiceExceptionUtilClassName", ServiceExceptionUtil.class.getName());
135 138 globalBindingMap.put("DateUtilsClassName", DateUtils.class.getName());
136 139 globalBindingMap.put("ExcelUtilsClassName", ExcelUtils.class.getName());
  140 + globalBindingMap.put("ObjectUtilsClassName", ObjectUtils.class.getName());
137 141 globalBindingMap.put("DictConvertClassName", DictConvert.class.getName());
138 142 globalBindingMap.put("OperateLogClassName", OperateLog.class.getName());
139 143 globalBindingMap.put("OperateTypeEnumClassName", OperateTypeEnum.class.getName());
... ... @@ -191,7 +195,7 @@ public class ToolCodegenEngine {
191 195 }
192 196  
193 197 private static String javaFilePath(String path) {
194   - return "java/${basePackage}/${table.moduleName}/" + path + ".java";
  198 + return "java/${basePackage}/modules/${table.moduleName}/" + path + ".java";
195 199 }
196 200  
197 201 private static String vueTemplatePath(String path) {
... ...
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/tool/service/codegen/impl/ToolCodegenSQLParser.java
... ... @@ -64,10 +64,17 @@ public class ToolCodegenSQLParser {
64 64 private static ToolSchemaTableDO parseTable(SQLCreateTableStatement statement) {
65 65 return ToolSchemaTableDO.builder()
66 66 .tableName(statement.getTableSource().getTableName(true))
67   - .tableComment(((SQLCharExpr) statement.getComment()).getText())
  67 + .tableComment(getCommentText(statement))
68 68 .build();
69 69 }
70 70  
  71 + private static String getCommentText(SQLCreateTableStatement statement) {
  72 + if (statement == null || statement.getComment() == null) {
  73 + return "";
  74 + }
  75 + return ((SQLCharExpr) statement.getComment()).getText();
  76 + }
  77 +
71 78 private static List<ToolSchemaColumnDO> parseColumns(SQLCreateTableStatement statement) {
72 79 List<ToolSchemaColumnDO> columns = new ArrayList<>();
73 80 statement.getTableElementList().forEach(element -> parseColumn(columns, element));
... ...
yudao-admin-server/src/main/resources/application-dev.yaml
... ... @@ -66,6 +66,7 @@ spring:
66 66 # Quartz 配置项,对应 QuartzProperties 配置类
67 67 spring:
68 68 quartz:
  69 + auto-startup: true # 测试环境,需要开启 Job
69 70 scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
70 71 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
71 72 wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
... ...
yudao-admin-server/src/main/resources/application-local.yaml
... ... @@ -80,6 +80,7 @@ spring:
80 80 # Quartz 配置项,对应 QuartzProperties 配置类
81 81 spring:
82 82 quartz:
  83 + auto-startup: false # 本地开发环境,尽量不要开启 Job
83 84 scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
84 85 job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
85 86 wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
... ... @@ -166,6 +167,8 @@ logging:
166 167  
167 168 # 芋道配置项,设置当前项目所有自定义的配置
168 169 yudao:
  170 + captcha:
  171 + enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试
169 172 security:
170 173 token-header: Authorization
171 174 token-secret: abcdefghijklmnopqrstuvwxyz
... ...
yudao-admin-server/src/main/resources/application.yaml
... ... @@ -22,7 +22,7 @@ spring:
22 22  
23 23 # MyBatis Plus 的配置项
24 24 mybatis-plus:
25   -# 在 mybatis-config/mybatis-config.xml 中设置
  25 +# 在 mybatis-config/mybatis-config.xml 中设置 TODO jason:看看有没其它解决方案
26 26 # configuration:
27 27 # map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
28 28 # log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 打印日志
... ... @@ -73,5 +73,7 @@ yudao:
73 73 constants-class-list:
74 74 - cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants
75 75 - cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants
  76 + tenant: # 多租户相关配置项
  77 + tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置
76 78  
77 79 debug: false
... ...
yudao-admin-server/src/main/resources/codegen/java/test/serviceTest.vm
... ... @@ -10,7 +10,6 @@ import ${basePackage}.modules.${table.moduleName}.service.${table.businessName}.
10 10 import ${basePackage}.modules.${table.moduleName}.controller.${table.businessName}.vo.*;
11 11 import ${basePackage}.modules.${table.moduleName}.dal.dataobject.${table.businessName}.${table.className}DO;
12 12 import ${basePackage}.modules.${table.moduleName}.dal.mysql.${table.businessName}.${table.className}Mapper;
13   -import ${basePackage}.util.object.ObjectUtils;
14 13 import ${PageResultClassName};
15 14  
16 15 import javax.annotation.Resource;
... ... @@ -19,9 +18,10 @@ import java.util.*;
19 18  
20 19 import static cn.hutool.core.util.RandomUtil.*;
21 20 import static ${basePackage}.modules.${table.moduleName}.enums.${simpleModuleName_upperFirst}ErrorCodeConstants.*;
22   -import static ${basePackage}.util.AssertUtils.*;
23   -import static ${basePackage}.util.RandomUtils.*;
24   -import static ${basePackage}.util.date.DateUtils.*;
  21 +import static ${baseFrameworkPackage}.test.core.util.AssertUtils.*;
  22 +import static ${baseFrameworkPackage}.test.core.util.RandomUtils.*;
  23 +import static ${ObjectUtilsClassName}.*;
  24 +import static ${DateUtilsClassName}.*;
25 25 import static org.junit.jupiter.api.Assertions.*;
26 26 import static org.mockito.Mockito.*;
27 27  
... ... @@ -41,7 +41,7 @@ import static org.mockito.Mockito.*;
41 41 #if (${column.listOperation})
42 42 #set ($JavaField = $column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})##首字母大写
43 43 // 测试 ${column.javaField} 不匹配
44   - ${classNameVar}Mapper.insert(ObjectUtils.clone(db${simpleClassName}, o -> o.set$JavaField(null)));
  44 + ${classNameVar}Mapper.insert(cloneIgnoreId(db${simpleClassName}, o -> o.set$JavaField(null)));
45 45 #end
46 46 #end
47 47 // 准备参数
... ...
yudao-admin-server/src/main/resources/mybatis-config/mybatis-config.xml
... ... @@ -6,6 +6,7 @@
6 6 <settings>
7 7 <setting name="lazyLoadingEnabled" value="false" />
8 8 <setting name="mapUnderscoreToCamelCase" value="true"/>
  9 + <setting name="logImpl" value="org.apache.ibatis.logging.stdout.StdOutImpl"/> <!-- 如果不想打 SQL 日志,可以注释掉 -->
9 10 </settings>
10 11 <typeAliases>
11 12 <typeAlias type="org.activiti.engine.impl.persistence.ByteArrayRefTypeHandler" alias="ByteArrayRefTypeHandler"/>
... ...
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 {
172 172 });
173 173 configMapper.insert(dbConfig);
174 174 // 测试 name 不匹配
175   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setName("土豆")));
  175 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
176 176 // 测试 key 不匹配
177   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setKey("tudou")));
  177 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
178 178 // 测试 type 不匹配
179   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
  179 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
180 180 // 测试 createTime 不匹配
181   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
  181 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
182 182 // 准备参数
183 183 InfConfigPageReqVO reqVO = new InfConfigPageReqVO();
184 184 reqVO.setName("艿");
... ... @@ -206,13 +206,13 @@ public class InfConfigServiceTest extends BaseDbUnitTest {
206 206 });
207 207 configMapper.insert(dbConfig);
208 208 // 测试 name 不匹配
209   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setName("土豆")));
  209 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setName("土豆")));
210 210 // 测试 key 不匹配
211   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setKey("tudou")));
  211 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setKey("tudou")));
212 212 // 测试 type 不匹配
213   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
  213 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setType(InfConfigTypeEnum.CUSTOM.getType())));
214 214 // 测试 createTime 不匹配
215   - configMapper.insert(ObjectUtils.clone(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
  215 + configMapper.insert(ObjectUtils.cloneIgnoreId(dbConfig, o -> o.setCreateTime(buildTime(2021, 1, 1))));
216 216 // 准备参数
217 217 InfConfigExportReqVO reqVO = new InfConfigExportReqVO();
218 218 reqVO.setName("艿");
... ...
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 {
41 41 });
42 42 fileMapper.insert(dbFile);
43 43 // 测试 id 不匹配
44   - fileMapper.insert(ObjectUtils.clone(dbFile, o -> o.setId("tudou")));
  44 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> o.setId("tudou")));
45 45 // 测试 type 不匹配
46   - fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
  46 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
47 47 o.setId("yudao02");
48 48 o.setType("png");
49 49 }));
50 50 // 测试 createTime 不匹配
51   - fileMapper.insert(ObjectUtils.clone(dbFile, o -> {
  51 + fileMapper.insert(ObjectUtils.cloneIgnoreId(dbFile, o -> {
52 52 o.setId("yudao03");
53 53 o.setCreateTime(buildTime(2020, 1, 15));
54 54 }));
... ...
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 {
84 84 o.setExecuteIndex(1);
85 85 o.setStatus(randomEle(InfJobLogStatusEnum.values()).getStatus()); // 保证 status 的范围
86 86 });
87   - InfJobLogDO cloneJobLog = ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString()));
  87 + InfJobLogDO cloneJobLog = ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString()));
88 88 jobLogMapper.insert(dbJobLog);
89 89 // 测试 handlerName 不匹配
90 90 jobLogMapper.insert(cloneJobLog);
... ... @@ -111,15 +111,15 @@ public class InfJobLogServiceTest extends BaseDbUnitTest {
111 111 });
112 112 jobLogMapper.insert(dbJobLog);
113 113 // 测试 jobId 不匹配
114   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
  114 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setJobId(randomLongId())));
115 115 // 测试 handlerName 不匹配
116   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
  116 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
117 117 // 测试 beginTime 不匹配
118   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
  118 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
119 119 // 测试 endTime 不匹配
120   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
  120 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
121 121 // 测试 status 不匹配
122   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
  122 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
123 123 // 准备参数
124 124 InfJobLogPageReqVO reqVo = new InfJobLogPageReqVO();
125 125 reqVo.setJobId(dbJobLog.getJobId());
... ... @@ -147,15 +147,15 @@ public class InfJobLogServiceTest extends BaseDbUnitTest {
147 147 });
148 148 jobLogMapper.insert(dbJobLog);
149 149 // 测试 jobId 不匹配
150   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setJobId(randomLongId())));
  150 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setJobId(randomLongId())));
151 151 // 测试 handlerName 不匹配
152   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setHandlerName(randomString())));
  152 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setHandlerName(randomString())));
153 153 // 测试 beginTime 不匹配
154   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
  154 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setBeginTime(buildTime(2021, 1, 7))));
155 155 // 测试 endTime 不匹配
156   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
  156 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setEndTime(buildTime(2021, 1, 9))));
157 157 // 测试 status 不匹配
158   - jobLogMapper.insert(ObjectUtils.clone(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
  158 + jobLogMapper.insert(ObjectUtils.cloneIgnoreId(dbJobLog, o -> o.setStatus(InfJobLogStatusEnum.FAILURE.getStatus())));
159 159 // 准备参数
160 160 InfJobLogExportReqVO reqVo = new InfJobLogExportReqVO();
161 161 reqVo.setJobId(dbJobLog.getJobId());
... ...
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 {
230 230 InfJobDO dbJob = randomPojo(InfJobDO.class, o -> {
231 231 o.setStatus(randomEle(InfJobStatusEnum.values()).getStatus()); // 保证 status 的范围
232 232 });
233   - InfJobDO cloneJob = ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString()));
  233 + InfJobDO cloneJob = ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString()));
234 234 jobMapper.insert(dbJob);
235 235 // 测试 handlerName 不匹配
236 236 jobMapper.insert(cloneJob);
... ... @@ -255,11 +255,11 @@ public class InfJobServiceTest extends BaseDbUnitTest {
255 255 });
256 256 jobMapper.insert(dbJob);
257 257 // 测试 name 不匹配
258   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
  258 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆")));
259 259 // 测试 status 不匹配
260   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
  260 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
261 261 // 测试 handlerName 不匹配
262   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
  262 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())));
263 263 // 准备参数
264 264 InfJobPageReqVO reqVo = new InfJobPageReqVO();
265 265 reqVo.setName("定时");
... ... @@ -283,11 +283,11 @@ public class InfJobServiceTest extends BaseDbUnitTest {
283 283 });
284 284 jobMapper.insert(dbJob);
285 285 // 测试 name 不匹配
286   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setName("土豆")));
  286 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setName("土豆")));
287 287 // 测试 status 不匹配
288   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
  288 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setStatus(InfJobStatusEnum.NORMAL.getStatus())));
289 289 // 测试 handlerName 不匹配
290   - jobMapper.insert(ObjectUtils.clone(dbJob, o -> o.setHandlerName(randomString())));
  290 + jobMapper.insert(ObjectUtils.cloneIgnoreId(dbJob, o -> o.setHandlerName(randomString())));
291 291 // 准备参数
292 292 InfJobExportReqVO reqVo = new InfJobExportReqVO();
293 293 reqVo.setName("定时");
... ...
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 {
59 59  
60 60 // 下面几个都是不匹配的数据
61 61 // userId 不同的
62   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
  62 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
63 63 // userType
64   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
  64 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
65 65 // applicationName 不同的
66   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
  66 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
67 67 // requestUrl 不同的
68   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
  68 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
69 69 // 构造一个早期时间 2021-02-06 00:00:00
70   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
  70 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
71 71 // duration 不同的
72   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
  72 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
73 73 // resultCode 不同的
74   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
  74 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
75 75  
76 76 // 构造调用参数
77 77 InfApiAccessLogPageReqVO reqVO = new InfApiAccessLogPageReqVO();
... ... @@ -117,19 +117,19 @@ public class InfApiAccessLogServiceImplTest extends BaseDbUnitTest {
117 117  
118 118 // 下面几个都是不匹配的数据
119 119 // userId 不同的
120   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
  120 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserId(3344L)));
121 121 // userType
122   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
  122 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
123 123 // applicationName 不同的
124   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
  124 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setApplicationName("test")));
125 125 // requestUrl 不同的
126   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
  126 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setRequestUrl("bar")));
127 127 // 构造一个早期时间 2021-02-06 00:00:00
128   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
  128 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setBeginTime(buildTime(2021, 2, 6))));
129 129 // duration 不同的
130   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
  130 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setDuration(100)));
131 131 // resultCode 不同的
132   - infApiAccessLogMapper.insert(ObjectUtils.clone(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
  132 + infApiAccessLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiAccessLogDO, logDO -> logDO.setResultCode(2)));
133 133  
134 134 // 构造调用参数
135 135 InfApiAccessLogExportReqVO reqVO = new InfApiAccessLogExportReqVO();
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/infra/service/logger/InfApiErrorLogServiceImplTest.java
1 1 package cn.iocoder.yudao.adminserver.modules.infra.service.logger;
2 2  
3 3 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
4   -import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
5   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
6   -import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 4 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogExportReqVO;
8 5 import cn.iocoder.yudao.adminserver.modules.infra.controller.logger.vo.apierrorlog.InfApiErrorLogPageReqVO;
9 6 import cn.iocoder.yudao.adminserver.modules.infra.dal.mysql.logger.InfApiErrorLogMapper;
10 7 import cn.iocoder.yudao.adminserver.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
11 8 import cn.iocoder.yudao.adminserver.modules.infra.service.logger.impl.InfApiErrorLogServiceImpl;
12   -import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
  9 +import cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger.InfApiErrorLogDO;
  10 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  11 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
13 12 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
  13 +import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
14 14 import org.junit.jupiter.api.Test;
15 15 import org.springframework.context.annotation.Import;
16 16  
... ... @@ -20,11 +20,10 @@ import java.util.List;
20 20  
21 21 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_NOT_FOUND;
22 22 import static cn.iocoder.yudao.adminserver.modules.infra.enums.InfErrorCodeConstants.API_ERROR_LOG_PROCESSED;
  23 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
23 24 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
24 25 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
25   -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
26 26 import static org.junit.jupiter.api.Assertions.assertEquals;
27   -import static org.junit.jupiter.api.Assertions.assertNotNull;
28 27  
29 28 /**
30 29 * {@link InfApiErrorLogServiceImpl} 单元测试
... ... @@ -60,17 +59,17 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
60 59  
61 60 // 下面几个都是不匹配的数据
62 61 // userId 不同的
63   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
  62 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
64 63 // userType
65   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
  64 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
66 65 // applicationName 不同的
67   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
  66 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
68 67 // requestUrl 不同的
69   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
  68 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
70 69 // 构造一个早期时间 2021-02-06 00:00:00
71   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
  70 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
72 71 // progressStatus 不同的
73   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
  72 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
74 73  
75 74 // 构造调用参数
76 75 InfApiErrorLogPageReqVO reqVO = new InfApiErrorLogPageReqVO();
... ... @@ -113,17 +112,17 @@ public class InfApiErrorLogServiceImplTest extends BaseDbUnitTest {
113 112  
114 113 // 下面几个都是不匹配的数据
115 114 // userId 不同的
116   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
  115 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserId(3344L)));
117 116 // userType
118   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
  117 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setUserType(UserTypeEnum.MEMBER.getValue())));
119 118 // applicationName 不同的
120   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
  119 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setApplicationName("test")));
121 120 // requestUrl 不同的
122   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
  121 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setRequestUrl("bar")));
123 122 // 构造一个早期时间 2021-02-06 00:00:00
124   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
  123 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setExceptionTime(buildTime(2021, 2, 6))));
125 124 // progressStatus 不同的
126   - infApiErrorLogMapper.insert(ObjectUtils.clone(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
  125 + infApiErrorLogMapper.insert(ObjectUtils.cloneIgnoreId(infApiErrorLogDO, logDO -> logDO.setProcessStatus(InfApiErrorLogProcessStatusEnum.DONE.getStatus())));
127 126  
128 127 // 构造调用参数
129 128 InfApiErrorLogExportReqVO reqVO = new InfApiErrorLogExportReqVO();
... ...
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
17 17 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
18 18 import cn.iocoder.yudao.framework.security.core.LoginUser;
19 19 import cn.iocoder.yudao.framework.test.core.util.AssertUtils;
  20 +import org.junit.jupiter.api.BeforeEach;
20 21 import org.junit.jupiter.api.Test;
21 22 import org.springframework.boot.test.mock.mockito.MockBean;
22 23 import org.springframework.context.annotation.Import;
... ... @@ -71,6 +72,11 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
71 72 @MockBean
72 73 private SysPostService postService;
73 74  
  75 + @BeforeEach
  76 + public void setUp() {
  77 + when(captchaService.isCaptchaEnable()).thenReturn(true);
  78 + }
  79 +
74 80 @Test
75 81 public void testLoadUserByUsername_success() {
76 82 // 准备参数
... ... @@ -83,7 +89,6 @@ public class SysAuthServiceImplTest extends BaseDbUnitTest {
83 89 LoginUser loginUser = (LoginUser) authService.loadUserByUsername(username);
84 90 // 校验
85 91 AssertUtils.assertPojoEquals(user, loginUser, "updateTime");
86   - assertNull(loginUser.getRoleIds()); // 此时不会加载角色,所以是空的
87 92 }
88 93  
89 94 @Test
... ...
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 {
73 73 });
74 74 userSessionMapper.insert(dbSession);
75 75 // 测试 username 不匹配
76   - userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
  76 + userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
77 77 o.setId(randomString());
78 78 o.setUserId(123456L);
79 79 }));
80 80 // 测试 userIp 不匹配
81   - userSessionMapper.insert(ObjectUtils.clone(dbSession, o -> {
  81 + userSessionMapper.insert(ObjectUtils.cloneIgnoreId(dbSession, o -> {
82 82 o.setId(randomString());
83 83 o.setUserIp("testUserIp");
84 84 }));
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysDeptServiceTest.java
... ... @@ -83,9 +83,9 @@ class SysDeptServiceTest extends BaseDbUnitTest {
83 83 });
84 84 deptMapper.insert(dept);
85 85 // 测试 name 不匹配
86   - deptMapper.insert(ObjectUtils.clone(dept, o -> o.setName("发")));
  86 + deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setName("发")));
87 87 // 测试 status 不匹配
88   - deptMapper.insert(ObjectUtils.clone(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  88 + deptMapper.insert(ObjectUtils.cloneIgnoreId(dept, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
89 89 // 准备参数
90 90 SysDeptListReqVO reqVO = new SysDeptListReqVO();
91 91 reqVO.setName("开");
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/dept/SysPostServiceTest.java
... ... @@ -49,9 +49,9 @@ class SysPostServiceTest extends BaseDbUnitTest {
49 49 });
50 50 postMapper.insert(postDO);
51 51 // 测试 name 不匹配
52   - postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
  52 + postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setName("程序员")));
53 53 // 测试 status 不匹配
54   - postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  54 + postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
55 55  
56 56 // 准备参数
57 57 SysPostPageReqVO reqVO = new SysPostPageReqVO();
... ... @@ -76,9 +76,9 @@ class SysPostServiceTest extends BaseDbUnitTest {
76 76 });
77 77 postMapper.insert(postDO);
78 78 // 测试 name 不匹配
79   - postMapper.insert(ObjectUtils.clone(postDO, o -> o.setName("程序员")));
  79 + postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setName("程序员")));
80 80 // 测试 status 不匹配
81   - postMapper.insert(ObjectUtils.clone(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  81 + postMapper.insert(ObjectUtils.cloneIgnoreId(postDO, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
82 82 // 准备参数
83 83 SysPostExportReqVO reqVO = new SysPostExportReqVO();
84 84 reqVO.setName("码");
... ...
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
14 14 import cn.iocoder.yudao.adminserver.modules.system.service.dict.impl.SysDictDataServiceImpl;
15 15 import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils;
16 16 import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
17   -import com.google.common.collect.ImmutableTable;
18 17 import org.junit.jupiter.api.Test;
19 18 import org.springframework.boot.test.mock.mockito.MockBean;
20 19 import org.springframework.context.annotation.Import;
21 20  
22 21 import javax.annotation.Resource;
23   -import java.util.Date;
24 22 import java.util.List;
25 23 import java.util.function.Consumer;
26 24  
27   -import static cn.hutool.core.bean.BeanUtil.getFieldValue;
28 25 import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.*;
29 26 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
30 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
... ... @@ -61,11 +58,11 @@ public class SysDictDataServiceTest extends BaseDbUnitTest {
61 58 });
62 59 dictDataMapper.insert(dbDictData);
63 60 // 测试 label 不匹配
64   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setLabel("艿")));
  61 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setLabel("艿")));
65 62 // 测试 dictType 不匹配
66   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setDictType("nai")));
  63 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setDictType("nai")));
67 64 // 测试 status 不匹配
68   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  65 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
69 66 // 准备参数
70 67 SysDictDataPageReqVO reqVO = new SysDictDataPageReqVO();
71 68 reqVO.setLabel("芋");
... ... @@ -90,11 +87,11 @@ public class SysDictDataServiceTest extends BaseDbUnitTest {
90 87 });
91 88 dictDataMapper.insert(dbDictData);
92 89 // 测试 label 不匹配
93   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setLabel("艿")));
  90 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setLabel("艿")));
94 91 // 测试 dictType 不匹配
95   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setDictType("nai")));
  92 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setDictType("nai")));
96 93 // 测试 status 不匹配
97   - dictDataMapper.insert(ObjectUtils.clone(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  94 + dictDataMapper.insert(ObjectUtils.cloneIgnoreId(dbDictData, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
98 95 // 准备参数
99 96 SysDictDataExportReqVO reqVO = new SysDictDataExportReqVO();
100 97 reqVO.setLabel("芋");
... ...
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 {
57 57 });
58 58 dictTypeMapper.insert(dbDictType);
59 59 // 测试 name 不匹配
60   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setName("tudou")));
  60 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setName("tudou")));
61 61 // 测试 type 不匹配
62   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setType("土豆")));
  62 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setType("土豆")));
63 63 // 测试 status 不匹配
64   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  64 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
65 65 // 测试 createTime 不匹配
66   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
  66 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
67 67 // 准备参数
68 68 SysDictTypePageReqVO reqVO = new SysDictTypePageReqVO();
69 69 reqVO.setName("nai");
... ... @@ -91,13 +91,13 @@ public class SysDictTypeServiceTest extends BaseDbUnitTest {
91 91 });
92 92 dictTypeMapper.insert(dbDictType);
93 93 // 测试 name 不匹配
94   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setName("tudou")));
  94 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setName("tudou")));
95 95 // 测试 type 不匹配
96   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setType("土豆")));
  96 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setType("土豆")));
97 97 // 测试 status 不匹配
98   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  98 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
99 99 // 测试 createTime 不匹配
100   - dictTypeMapper.insert(ObjectUtils.clone(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
  100 + dictTypeMapper.insert(ObjectUtils.cloneIgnoreId(dbDictType, o -> o.setCreateTime(buildTime(2021, 1, 1))));
101 101 // 准备参数
102 102 SysDictTypeExportReqVO reqVO = new SysDictTypeExportReqVO();
103 103 reqVO.setName("nai");
... ...
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 {
131 131 });
132 132 errorCodeMapper.insert(dbErrorCode);
133 133 // 测试 type 不匹配
134   - errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType())));
  134 + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setType(SysErrorCodeTypeEnum.MANUAL_OPERATION.getType())));
135 135 // 测试 applicationName 不匹配
136   - errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setApplicationName("yunai")));
  136 + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setApplicationName("yunai")));
137 137 // 测试 code 不匹配
138   - errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setCode(2)));
  138 + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCode(2)));
139 139 // 测试 message 不匹配
140   - errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setMessage("nai")));
  140 + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setMessage("nai")));
141 141 // 测试 createTime 不匹配
142   - errorCodeMapper.insert(ObjectUtils.clone(dbErrorCode, o -> o.setCreateTime(buildTime(2020, 12, 12))));
  142 + errorCodeMapper.insert(ObjectUtils.cloneIgnoreId(dbErrorCode, o -> o.setCreateTime(buildTime(2020, 12, 12))));
143 143 return dbErrorCode;
144 144 }
145 145  
... ...
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 {
51 51  
52 52 // 下面几个都是不匹配的数据
53 53 // 登录失败的
54   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
  54 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
55 55 // 不同ip段的
56   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
  56 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
57 57 // 不同username
58   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
  58 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai")));
59 59 // 构造一个早期时间 2021-02-06 00:00:00
60   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
  60 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
61 61  
62 62  
63 63 // 构造调用参数
... ... @@ -96,13 +96,13 @@ public class SysLoginLogServiceImplTest extends BaseDbUnitTest {
96 96  
97 97 // 下面几个都是不匹配的数据
98 98 // 登录失败的
99   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
  99 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setResult(SysLoginResultEnum.CAPTCHA_CODE_ERROR.getResult())));
100 100 // 不同ip段的
101   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
  101 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUserIp("192.168.128.18")));
102 102 // 不同username
103   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setUsername("yunai")));
  103 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setUsername("yunai")));
104 104 // 构造一个早期时间 2021-02-06 00:00:00
105   - loginLogMapper.insert(ObjectUtils.clone(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
  105 + loginLogMapper.insert(ObjectUtils.cloneIgnoreId(loginLogDO, logDO -> logDO.setCreateTime(buildTime(2021, 2, 6))));
106 106  
107 107  
108 108 // 构造调用参数
... ...
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 {
87 87  
88 88 // 下面几个是不匹配的数据
89 89 // 随机 userId
90   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
  90 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
91 91 // module 不同
92   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
  92 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setModule("user")));
93 93 // type 不同
94   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
  94 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
95 95 // createTime 不同
96   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
  96 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
97 97 // resultCode 不同
98   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
  98 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
99 99  
100 100 // 构造调用参数
101 101 SysOperateLogPageReqVO reqVO = new SysOperateLogPageReqVO();
... ... @@ -138,15 +138,15 @@ public class SysOperateLogServiceImplTest extends BaseDbUnitTest {
138 138  
139 139 // 下面几个是不匹配的数据
140 140 // 随机 userId
141   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
  141 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setUserId(userId + 1)));
142 142 // module 不同
143   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setModule("user")));
  143 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setModule("user")));
144 144 // type 不同
145   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
  145 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setType(OperateTypeEnum.IMPORT.getType())));
146 146 // createTime 不同
147   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
  147 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setStartTime(buildTime(2021, 2, 6))));
148 148 // resultCode 不同
149   - operateLogMapper.insert(ObjectUtils.clone(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
  149 + operateLogMapper.insert(ObjectUtils.cloneIgnoreId(sysOperateLogDO, logDO -> logDO.setResultCode(GlobalErrorCodeConstants.BAD_REQUEST.getCode())));
150 150  
151 151 // 构造调用参数
152 152 SysOperateLogExportReqVO reqVO = new SysOperateLogExportReqVO();
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/notice/SysNoticeServiceImplTest.java
... ... @@ -46,9 +46,9 @@ class SysNoticeServiceImplTest extends BaseDbUnitTest {
46 46 sysNoticeMapper.insert(dbNotice);
47 47  
48 48 // 测试 title 不匹配
49   - sysNoticeMapper.insert(ObjectUtils.clone(dbNotice, o -> o.setTitle("尼古拉斯凯奇也来啦!")));
  49 + sysNoticeMapper.insert(ObjectUtils.cloneIgnoreId(dbNotice, o -> o.setTitle("尼古拉斯凯奇也来啦!")));
50 50 // 测试 status 不匹配
51   - sysNoticeMapper.insert(ObjectUtils.clone(dbNotice, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  51 + sysNoticeMapper.insert(ObjectUtils.cloneIgnoreId(dbNotice, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
52 52  
53 53  
54 54 // 查询
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/permission/SysPermissionServiceTest.java
1 1 package cn.iocoder.yudao.adminserver.modules.system.service.permission;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
  5 +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.dept.SysDeptDO;
  6 +import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleDO;
4 7 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysRoleMenuDO;
5 8 import cn.iocoder.yudao.adminserver.modules.system.dal.dataobject.permission.SysUserRoleDO;
6 9 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysRoleMenuMapper;
7 10 import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.permission.SysUserRoleMapper;
8 11 import cn.iocoder.yudao.adminserver.modules.system.mq.producer.permission.SysPermissionProducer;
  12 +import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
9 13 import cn.iocoder.yudao.adminserver.modules.system.service.permission.impl.SysPermissionServiceImpl;
  14 +import cn.iocoder.yudao.framework.datapermission.core.dept.service.dto.DeptDataPermissionRespDTO;
  15 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  16 +import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum;
10 17 import org.junit.jupiter.api.Test;
11 18 import org.springframework.boot.test.mock.mockito.MockBean;
12 19 import org.springframework.context.annotation.Import;
... ... @@ -17,8 +24,12 @@ import java.util.List;
17 24 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
18 25 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
19 26 import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
20   -import static org.junit.jupiter.api.Assertions.assertEquals;
  27 +import static java.util.Collections.singletonList;
  28 +import static org.junit.jupiter.api.Assertions.*;
  29 +import static org.mockito.ArgumentMatchers.eq;
  30 +import static org.mockito.ArgumentMatchers.same;
21 31 import static org.mockito.Mockito.verify;
  32 +import static org.mockito.Mockito.when;
22 33  
23 34 @Import(SysPermissionServiceImpl.class)
24 35 public class SysPermissionServiceTest extends BaseDbUnitTest {
... ... @@ -35,6 +46,8 @@ public class SysPermissionServiceTest extends BaseDbUnitTest {
35 46 private SysRoleService roleService;
36 47 @MockBean
37 48 private SysMenuService menuService;
  49 + @MockBean
  50 + private SysDeptService deptService;
38 51  
39 52 @MockBean
40 53 private SysPermissionProducer permissionProducer;
... ... @@ -106,4 +119,111 @@ public class SysPermissionServiceTest extends BaseDbUnitTest {
106 119 assertPojoEquals(dbUserRoles.get(0), userRoleDO02);
107 120 }
108 121  
  122 + @Test // 测试从 context 获取的场景
  123 + public void testGetDeptDataPermission_fromContext() {
  124 + // 准备参数
  125 + LoginUser loginUser = randomPojo(LoginUser.class);
  126 + // mock 方法
  127 + DeptDataPermissionRespDTO respDTO = new DeptDataPermissionRespDTO();
  128 + loginUser.setContext(SysPermissionServiceImpl.CONTEXT_KEY, respDTO);
  129 +
  130 + // 调用
  131 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  132 + // 断言
  133 + assertSame(respDTO, result);
  134 + }
  135 +
  136 + @Test
  137 + public void testGetDeptDataPermission_All() {
  138 + // 准备参数
  139 + LoginUser loginUser = randomPojo(LoginUser.class);
  140 + // mock 方法
  141 + SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.ALL.getScope()));
  142 + when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
  143 +
  144 + // 调用
  145 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  146 + // 断言
  147 + assertTrue(result.getAll());
  148 + assertFalse(result.getSelf());
  149 + assertTrue(CollUtil.isEmpty(result.getDeptIds()));
  150 + assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
  151 + }
  152 +
  153 + @Test
  154 + public void testGetDeptDataPermission_DeptCustom() {
  155 + // 准备参数
  156 + LoginUser loginUser = randomPojo(LoginUser.class);
  157 + // mock 方法
  158 + SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_CUSTOM.getScope()));
  159 + when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
  160 +
  161 + // 调用
  162 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  163 + // 断言
  164 + assertFalse(result.getAll());
  165 + assertFalse(result.getSelf());
  166 + assertEquals(roleDO.getDataScopeDeptIds().size() + 1, result.getDeptIds().size());
  167 + assertTrue(CollUtil.containsAll(result.getDeptIds(), roleDO.getDataScopeDeptIds()));
  168 + assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
  169 + assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
  170 + }
  171 +
  172 + @Test
  173 + public void testGetDeptDataPermission_DeptOnly() {
  174 + // 准备参数
  175 + LoginUser loginUser = randomPojo(LoginUser.class);
  176 + // mock 方法
  177 + SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_ONLY.getScope()));
  178 + when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
  179 +
  180 + // 调用
  181 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  182 + // 断言
  183 + assertFalse(result.getAll());
  184 + assertFalse(result.getSelf());
  185 + assertEquals(1, result.getDeptIds().size());
  186 + assertTrue(CollUtil.contains(result.getDeptIds(), loginUser.getDeptId()));
  187 + assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
  188 + }
  189 +
  190 + @Test
  191 + public void testGetDeptDataPermission_DeptAndChild() {
  192 + // 准备参数
  193 + LoginUser loginUser = randomPojo(LoginUser.class);
  194 + // mock 方法(角色)
  195 + SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.DEPT_AND_CHILD.getScope()));
  196 + when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
  197 + // mock 方法(部门)
  198 + SysDeptDO deptDO = randomPojo(SysDeptDO.class);
  199 + when(deptService.getDeptsByParentIdFromCache(eq(loginUser.getDeptId()), eq(true)))
  200 + .thenReturn(singletonList(deptDO));
  201 +
  202 + // 调用
  203 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  204 + // 断言
  205 + assertFalse(result.getAll());
  206 + assertFalse(result.getSelf());
  207 + assertEquals(1, result.getDeptIds().size());
  208 + assertTrue(CollUtil.contains(result.getDeptIds(), deptDO.getId()));
  209 + assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
  210 + }
  211 +
  212 + @Test
  213 + public void testGetDeptDataPermission_Self() {
  214 + // 准备参数
  215 + LoginUser loginUser = randomPojo(LoginUser.class);
  216 + // mock 方法
  217 + SysRoleDO roleDO = randomPojo(SysRoleDO.class, o -> o.setDataScope(DataScopeEnum.SELF.getScope()));
  218 + when(roleService.getRolesFromCache(same(loginUser.getRoleIds()))).thenReturn(singletonList(roleDO));
  219 +
  220 + // 调用
  221 + DeptDataPermissionRespDTO result = permissionService.getDeptDataPermission(loginUser);
  222 + // 断言
  223 + assertFalse(result.getAll());
  224 + assertTrue(result.getSelf());
  225 + assertTrue(CollUtil.isEmpty(result.getDeptIds()));
  226 + assertSame(result, loginUser.getContext(SysPermissionServiceImpl.CONTEXT_KEY, DeptDataPermissionRespDTO.class));
  227 + }
  228 +
109 229 }
... ...
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 {
133 133  
134 134 //调用
135 135 Set<Long> deptIdSet = Arrays.asList(1L, 2L, 3L, 4L, 5L).stream().collect(Collectors.toSet());
136   - sysRoleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScore(), deptIdSet);
  136 + sysRoleService.updateRoleDataScope(roleId, DataScopeEnum.DEPT_CUSTOM.getScope(), deptIdSet);
137 137  
138 138 //断言
139 139 SysRoleDO newRoleDO = roleMapper.selectById(roleId);
140   - assertEquals(DataScopeEnum.DEPT_CUSTOM.getScore(), newRoleDO.getDataScope());
  140 + assertEquals(DataScopeEnum.DEPT_CUSTOM.getScope(), newRoleDO.getDataScope());
141 141  
142 142 Set<Long> newDeptIdSet = newRoleDO.getDataScopeDeptIds();
143 143 assertTrue(deptIdSet.size() == newDeptIdSet.size());
... ... @@ -242,7 +242,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest {
242 242 o.setCode("code");
243 243 o.setType(SysRoleTypeEnum.CUSTOM.getType());
244 244 o.setStatus(1);
245   - o.setDataScope(DataScopeEnum.ALL.getScore());
  245 + o.setDataScope(DataScopeEnum.ALL.getScope());
246 246 });
247 247 roleMapper.insert(roleDO);
248 248  
... ... @@ -293,7 +293,7 @@ public class SysRoleServiceTest extends BaseDbUnitTest {
293 293 o.setName(name);
294 294 o.setType(typeEnum.getType());
295 295 o.setStatus(status);
296   - o.setDataScope(scopeEnum.getScore());
  296 + o.setDataScope(scopeEnum.getScope());
297 297 o.setCode(code);
298 298 });
299 299 return roleDO;
... ...
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 {
169 169 });
170 170 smsChannelMapper.insert(dbSmsChannel);
171 171 // 测试 signature 不匹配
172   - smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setSignature("源码")));
  172 + smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setSignature("源码")));
173 173 // 测试 status 不匹配
174   - smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  174 + smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
175 175 // 测试 createTime 不匹配
176   - smsChannelMapper.insert(ObjectUtils.clone(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
  176 + smsChannelMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsChannel, o -> o.setCreateTime(buildTime(2020, 11, 11))));
177 177 // 准备参数
178 178 SysSmsChannelPageReqVO reqVO = new SysSmsChannelPageReqVO();
179 179 reqVO.setSignature("芋道");
... ...
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 {
57 57 });
58 58 smsLogMapper.insert(dbSmsLog);
59 59 // 测试 channelId 不匹配
60   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L)));
  60 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L)));
61 61 // 测试 templateId 不匹配
62   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L)));
  62 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L)));
63 63 // 测试 mobile 不匹配
64   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999")));
  64 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999")));
65 65 // 测试 sendStatus 不匹配
66   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
  66 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
67 67 // 测试 sendTime 不匹配
68   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
  68 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
69 69 // 测试 receiveStatus 不匹配
70   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
  70 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
71 71 // 测试 receiveTime 不匹配
72   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
  72 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
73 73 // 准备参数
74 74 SysSmsLogPageReqVO reqVO = new SysSmsLogPageReqVO();
75 75 reqVO.setChannelId(1L);
... ... @@ -104,19 +104,19 @@ public class SysSmsLogServiceTest extends BaseDbUnitTest {
104 104 });
105 105 smsLogMapper.insert(dbSmsLog);
106 106 // 测试 channelId 不匹配
107   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setChannelId(2L)));
  107 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setChannelId(2L)));
108 108 // 测试 templateId 不匹配
109   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setTemplateId(20L)));
  109 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setTemplateId(20L)));
110 110 // 测试 mobile 不匹配
111   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setMobile("18818260999")));
  111 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setMobile("18818260999")));
112 112 // 测试 sendStatus 不匹配
113   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
  113 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendStatus(SysSmsSendStatusEnum.IGNORE.getStatus())));
114 114 // 测试 sendTime 不匹配
115   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
  115 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setSendTime(buildTime(2020, 12, 12))));
116 116 // 测试 receiveStatus 不匹配
117   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
  117 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveStatus(SysSmsReceiveStatusEnum.SUCCESS.getStatus())));
118 118 // 测试 receiveTime 不匹配
119   - smsLogMapper.insert(ObjectUtils.clone(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
  119 + smsLogMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsLog, o -> o.setReceiveTime(buildTime(2021, 12, 12))));
120 120 // 准备参数
121 121 SysSmsLogExportReqVO reqVO = new SysSmsLogExportReqVO();
122 122 reqVO.setChannelId(1L);
... ...
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 {
190 190 });
191 191 smsTemplateMapper.insert(dbSmsTemplate);
192 192 // 测试 type 不匹配
193   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
  193 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
194 194 // 测试 status 不匹配
195   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  195 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
196 196 // 测试 code 不匹配
197   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCode("yuanma")));
  197 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
198 198 // 测试 content 不匹配
199   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setContent("源码")));
  199 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
200 200 // 测试 apiTemplateId 不匹配
201   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
  201 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
202 202 // 测试 channelId 不匹配
203   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setChannelId(2L)));
  203 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
204 204 // 测试 createTime 不匹配
205   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
  205 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
206 206 // 准备参数
207 207 SysSmsTemplatePageReqVO reqVO = new SysSmsTemplatePageReqVO();
208 208 reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());
... ... @@ -236,19 +236,19 @@ public class SysSmsTemplateServiceTest extends BaseDbUnitTest {
236 236 });
237 237 smsTemplateMapper.insert(dbSmsTemplate);
238 238 // 测试 type 不匹配
239   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
  239 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setType(SysSmsTemplateTypeEnum.VERIFICATION_CODE.getType())));
240 240 // 测试 status 不匹配
241   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  241 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
242 242 // 测试 code 不匹配
243   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCode("yuanma")));
  243 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCode("yuanma")));
244 244 // 测试 content 不匹配
245   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setContent("源码")));
  245 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setContent("源码")));
246 246 // 测试 apiTemplateId 不匹配
247   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
  247 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setApiTemplateId("nai")));
248 248 // 测试 channelId 不匹配
249   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setChannelId(2L)));
  249 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setChannelId(2L)));
250 250 // 测试 createTime 不匹配
251   - smsTemplateMapper.insert(ObjectUtils.clone(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
  251 + smsTemplateMapper.insert(ObjectUtils.cloneIgnoreId(dbSmsTemplate, o -> o.setCreateTime(buildTime(2021, 12, 12))));
252 252 // 准备参数
253 253 SysSmsTemplateExportReqVO reqVO = new SysSmsTemplateExportReqVO();
254 254 reqVO.setType(SysSmsTemplateTypeEnum.PROMOTION.getType());
... ...
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/system/service/tenant/SysTenantServiceTest.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.system.service.tenant;
  2 +
  3 +import cn.iocoder.yudao.adminserver.BaseDbUnitTest;
  4 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantCreateReqVO;
  5 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantExportReqVO;
  6 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantPageReqVO;
  7 +import cn.iocoder.yudao.adminserver.modules.system.controller.tenant.vo.SysTenantUpdateReqVO;
  8 +import cn.iocoder.yudao.adminserver.modules.system.dal.mysql.tenant.SysTenantMapper;
  9 +import cn.iocoder.yudao.adminserver.modules.system.service.tenant.impl.SysTenantServiceImpl;
  10 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  11 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  12 +import cn.iocoder.yudao.framework.common.pojo.PageResult;
  13 +import org.junit.jupiter.api.Test;
  14 +import org.springframework.context.annotation.Import;
  15 +
  16 +import javax.annotation.Resource;
  17 +import java.util.List;
  18 +
  19 +import static cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants.TENANT_NOT_EXISTS;
  20 +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
  21 +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
  22 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
  23 +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
  24 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
  25 +import static org.junit.jupiter.api.Assertions.*;
  26 +
  27 +/**
  28 + * {@link SysTenantServiceImpl} 的单元测试类
  29 + *
  30 + * @author 芋道源码
  31 + */
  32 +@Import(SysTenantServiceImpl.class)
  33 +public class SysTenantServiceTest extends BaseDbUnitTest {
  34 +
  35 + @Resource
  36 + private SysTenantServiceImpl tenantService;
  37 +
  38 + @Resource
  39 + private SysTenantMapper tenantMapper;
  40 +
  41 + @Test
  42 + public void testCreateTenant_success() {
  43 + // 准备参数
  44 + SysTenantCreateReqVO reqVO = randomPojo(SysTenantCreateReqVO.class, o -> o.setStatus(randomCommonStatus()));
  45 +
  46 + // 调用
  47 + Long tenantId = tenantService.createTenant(reqVO);
  48 + // 断言
  49 + assertNotNull(tenantId);
  50 + // 校验记录的属性是否正确
  51 + SysTenantDO tenant = tenantMapper.selectById(tenantId);
  52 + assertPojoEquals(reqVO, tenant);
  53 + }
  54 +
  55 + @Test
  56 + public void testUpdateTenant_success() {
  57 + // mock 数据
  58 + SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> o.setStatus(randomCommonStatus()));
  59 + tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
  60 + // 准备参数
  61 + SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class, o -> {
  62 + o.setId(dbTenant.getId()); // 设置更新的 ID
  63 + o.setStatus(randomCommonStatus());
  64 + });
  65 +
  66 + // 调用
  67 + tenantService.updateTenant(reqVO);
  68 + // 校验是否更新正确
  69 + SysTenantDO tenant = tenantMapper.selectById(reqVO.getId()); // 获取最新的
  70 + assertPojoEquals(reqVO, tenant);
  71 + }
  72 +
  73 + @Test
  74 + public void testUpdateTenant_notExists() {
  75 + // 准备参数
  76 + SysTenantUpdateReqVO reqVO = randomPojo(SysTenantUpdateReqVO.class);
  77 +
  78 + // 调用, 并断言异常
  79 + assertServiceException(() -> tenantService.updateTenant(reqVO), TENANT_NOT_EXISTS);
  80 + }
  81 +
  82 + @Test
  83 + public void testDeleteTenant_success() {
  84 + // mock 数据
  85 + SysTenantDO dbTenant = randomPojo(SysTenantDO.class,
  86 + o -> o.setStatus(randomCommonStatus()));
  87 + tenantMapper.insert(dbTenant);// @Sql: 先插入出一条存在的数据
  88 + // 准备参数
  89 + Long id = dbTenant.getId();
  90 +
  91 + // 调用
  92 + tenantService.deleteTenant(id);
  93 + // 校验数据不存在了
  94 + assertNull(tenantMapper.selectById(id));
  95 + }
  96 +
  97 + @Test
  98 + public void testDeleteTenant_notExists() {
  99 + // 准备参数
  100 + Long id = randomLongId();
  101 +
  102 + // 调用, 并断言异常
  103 + assertServiceException(() -> tenantService.deleteTenant(id), TENANT_NOT_EXISTS);
  104 + }
  105 +
  106 + @Test
  107 + public void testGetTenantPage() {
  108 + // mock 数据
  109 + SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到
  110 + o.setName("芋道源码");
  111 + o.setContactName("芋艿");
  112 + o.setContactMobile("15601691300");
  113 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  114 + o.setCreateTime(buildTime(2020, 12, 12));
  115 + });
  116 + tenantMapper.insert(dbTenant);
  117 + // 测试 name 不匹配
  118 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString())));
  119 + // 测试 contactName 不匹配
  120 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString())));
  121 + // 测试 contactMobile 不匹配
  122 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString())));
  123 + // 测试 status 不匹配
  124 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  125 + // 测试 createTime 不匹配
  126 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12))));
  127 + // 准备参数
  128 + SysTenantPageReqVO reqVO = new SysTenantPageReqVO();
  129 + reqVO.setName("芋道");
  130 + reqVO.setContactName("艿");
  131 + reqVO.setContactMobile("1560");
  132 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  133 + reqVO.setBeginCreateTime(buildTime(2020, 12, 1));
  134 + reqVO.setEndCreateTime(buildTime(2020, 12, 24));
  135 +
  136 + // 调用
  137 + PageResult<SysTenantDO> pageResult = tenantService.getTenantPage(reqVO);
  138 + // 断言
  139 + assertEquals(1, pageResult.getTotal());
  140 + assertEquals(1, pageResult.getList().size());
  141 + assertPojoEquals(dbTenant, pageResult.getList().get(0));
  142 + }
  143 +
  144 + @Test
  145 + public void testGetTenantList() {
  146 + // mock 数据
  147 + SysTenantDO dbTenant = randomPojo(SysTenantDO.class, o -> { // 等会查询到
  148 + o.setName("芋道源码");
  149 + o.setContactName("芋艿");
  150 + o.setContactMobile("15601691300");
  151 + o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  152 + o.setCreateTime(buildTime(2020, 12, 12));
  153 + });
  154 + tenantMapper.insert(dbTenant);
  155 + // 测试 name 不匹配
  156 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setName(randomString())));
  157 + // 测试 contactName 不匹配
  158 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactName(randomString())));
  159 + // 测试 contactMobile 不匹配
  160 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setContactMobile(randomString())));
  161 + // 测试 status 不匹配
  162 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  163 + // 测试 createTime 不匹配
  164 + tenantMapper.insert(cloneIgnoreId(dbTenant, o -> o.setCreateTime(buildTime(2021, 12, 12))));
  165 + // 准备参数
  166 + SysTenantExportReqVO reqVO = new SysTenantExportReqVO();
  167 + reqVO.setName("芋道");
  168 + reqVO.setContactName("艿");
  169 + reqVO.setContactMobile("1560");
  170 + reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
  171 + reqVO.setBeginCreateTime(buildTime(2020, 12, 1));
  172 + reqVO.setEndCreateTime(buildTime(2020, 12, 24));
  173 +
  174 + // 调用
  175 + List<SysTenantDO> list = tenantService.getTenantList(reqVO);
  176 + // 断言
  177 + assertEquals(1, list.size());
  178 + assertPojoEquals(dbTenant, list.get(0));
  179 + }
  180 +
  181 +}
... ...
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 {
309 309 });
310 310 userMapper.insert(dbUser);
311 311 // 测试 username 不匹配
312   - userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setUsername("yuanma")));
  312 + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setUsername("yuanma")));
313 313 // 测试 mobile 不匹配
314   - userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setMobile("18818260888")));
  314 + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setMobile("18818260888")));
315 315 // 测试 status 不匹配
316   - userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
  316 + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
317 317 // 测试 createTime 不匹配
318   - userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11))));
  318 + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setCreateTime(buildTime(2020, 11, 11))));
319 319 // 测试 dept 不匹配
320   - userMapper.insert(ObjectUtils.clone(dbUser, o -> o.setDeptId(0L)));
  320 + userMapper.insert(ObjectUtils.cloneIgnoreId(dbUser, o -> o.setDeptId(0L)));
321 321 return dbUser;
322 322 }
323 323  
... ...
yudao-admin-server/src/test/resources/sql/clean.sql
... ... @@ -24,3 +24,4 @@ DELETE FROM &quot;sys_sms_template&quot;;
24 24 DELETE FROM "sys_sms_log";
25 25 DELETE FROM "sys_error_code";
26 26 DELETE FROM "sys_social_user";
  27 +DELETE FROM "sys_tenant";
... ...
yudao-admin-server/src/test/resources/sql/create_tables.sql
1 1 -- inf 开头的 DB
2 2  
3 3 CREATE TABLE IF NOT EXISTS "inf_config" (
4   - "id" int NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  4 + "id" bigint(20) NOT NULL GENERATED BY DEFAULT AS IDENTITY,
5 5 "group" varchar(50) NOT NULL,
6 6 "type" tinyint NOT NULL,
7 7 "name" varchar(100) NOT NULL DEFAULT '',
... ... @@ -26,6 +26,7 @@ CREATE TABLE IF NOT EXISTS &quot;inf_file&quot; (
26 26 "updater" varchar(64) DEFAULT '',
27 27 "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
28 28 "deleted" bit NOT NULL DEFAULT FALSE,
  29 + "tenant_id" bigint not null default '0',
29 30 PRIMARY KEY ("id")
30 31 ) COMMENT '文件表';
31 32  
... ... @@ -82,6 +83,7 @@ CREATE TABLE IF NOT EXISTS &quot;sys_dept&quot; (
82 83 "updater" varchar(64) DEFAULT '',
83 84 "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
84 85 "deleted" bit NOT NULL DEFAULT FALSE,
  86 + "tenant_id" bigint not null default '0',
85 87 PRIMARY KEY ("id")
86 88 ) COMMENT '部门表';
87 89  
... ... @@ -189,6 +191,7 @@ CREATE TABLE IF NOT EXISTS `sys_user_session` (
189 191 `updater` varchar(64) DEFAULT '' ,
190 192 "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
191 193 "deleted" bit NOT NULL DEFAULT FALSE,
  194 + "tenant_id" bigint not null default '0',
192 195 PRIMARY KEY (`id`)
193 196 ) COMMENT '用户在线 Session';
194 197  
... ... @@ -204,6 +207,7 @@ CREATE TABLE IF NOT EXISTS &quot;sys_post&quot; (
204 207 "updater" varchar(64) DEFAULT '',
205 208 "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
206 209 "deleted" bit NOT NULL DEFAULT FALSE,
  210 + "tenant_id" bigint not null default '0',
207 211 PRIMARY KEY ("id")
208 212 ) COMMENT '岗位信息表';
209 213  
... ... @@ -218,7 +222,8 @@ CREATE TABLE IF NOT EXISTS &quot;sys_notice&quot; (
218 222 "updater" varchar(64) DEFAULT '' COMMENT '更新者',
219 223 "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
220 224 "deleted" bit NOT NULL DEFAULT 0 COMMENT '是否删除',
221   - PRIMARY KEY("id")
  225 + "tenant_id" bigint not null default '0',
  226 + PRIMARY KEY("id")
222 227 ) COMMENT '通知公告表';
223 228  
224 229 CREATE TABLE IF NOT EXISTS `sys_login_log` (
... ... @@ -264,6 +269,7 @@ CREATE TABLE IF NOT EXISTS `sys_operate_log` (
264 269 `updater` varchar(64) DEFAULT '',
265 270 `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
266 271 `deleted` bit(1) NOT NULL DEFAULT '0',
  272 + "tenant_id" bigint not null default '0',
267 273 PRIMARY KEY (`id`)
268 274 ) COMMENT ='操作日志记录';
269 275  
... ... @@ -287,6 +293,7 @@ CREATE TABLE IF NOT EXISTS &quot;sys_user&quot; (
287 293 "updater" varchar(64) default '',
288 294 "update_time" timestamp not null default current_timestamp,
289 295 "deleted" bit not null default false,
  296 + "tenant_id" bigint not null default '0',
290 297 primary key ("id")
291 298 ) comment '用户信息表';
292 299  
... ... @@ -311,11 +318,12 @@ CREATE TABLE IF NOT EXISTS &quot;inf_api_access_log&quot; (
311 318 "updater" varchar(64) default '',
312 319 "update_time" timestamp not null default current_timestamp,
313 320 "deleted" bit not null default false,
  321 + "tenant_id" bigint not null default '0',
314 322 primary key ("id")
315 323 ) COMMENT 'API 访问日志表';
316 324  
317 325 CREATE TABLE IF NOT EXISTS "inf_api_error_log" (
318   - "id" integer not null GENERATED BY DEFAULT AS IDENTITY,
  326 + "id" bigint not null GENERATED BY DEFAULT AS IDENTITY,
319 327 "trace_id" varchar(64) not null,
320 328 "user_id" bigint not null default '0',
321 329 "user_type" tinyint not null default '0',
... ... @@ -342,6 +350,7 @@ CREATE TABLE IF NOT EXISTS &quot;inf_api_error_log&quot; (
342 350 "updater" varchar(64) default '',
343 351 "update_time" timestamp not null default current_timestamp,
344 352 "deleted" bit not null default false,
  353 + "tenant_id" bigint not null default '0',
345 354 primary key ("id")
346 355 ) COMMENT '系统异常日志';
347 356  
... ... @@ -449,3 +458,17 @@ CREATE TABLE IF NOT EXISTS &quot;sys_social_user&quot; (
449 458 "deleted" bit NOT NULL DEFAULT FALSE,
450 459 PRIMARY KEY ("id")
451 460 ) COMMENT '社交用户';
  461 +
  462 +CREATE TABLE IF NOT EXISTS "sys_tenant" (
  463 + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY,
  464 + "name" varchar(63) NOT NULL,
  465 + "contact_name" varchar(255) NOT NULL,
  466 + "contact_mobile" varchar(255),
  467 + "status" tinyint NOT NULL,
  468 + "creator" varchar(64) DEFAULT '',
  469 + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  470 + "updater" varchar(64) DEFAULT '',
  471 + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  472 + "deleted" bit NOT NULL DEFAULT FALSE,
  473 + PRIMARY KEY ("id")
  474 +) COMMENT '租户';
... ...
yudao-admin-ui/src/api/system/tenant.js 0 → 100755
  1 +import request from '@/utils/request'
  2 +
  3 +// 创建租户
  4 +export function createTenant(data) {
  5 + return request({
  6 + url: '/system/tenant/create',
  7 + method: 'post',
  8 + data: data
  9 + })
  10 +}
  11 +
  12 +// 更新租户
  13 +export function updateTenant(data) {
  14 + return request({
  15 + url: '/system/tenant/update',
  16 + method: 'put',
  17 + data: data
  18 + })
  19 +}
  20 +
  21 +// 删除租户
  22 +export function deleteTenant(id) {
  23 + return request({
  24 + url: '/system/tenant/delete?id=' + id,
  25 + method: 'delete'
  26 + })
  27 +}
  28 +
  29 +// 获得租户
  30 +export function getTenant(id) {
  31 + return request({
  32 + url: '/system/tenant/get?id=' + id,
  33 + method: 'get'
  34 + })
  35 +}
  36 +
  37 +// 获得租户分页
  38 +export function getTenantPage(query) {
  39 + return request({
  40 + url: '/system/tenant/page',
  41 + method: 'get',
  42 + params: query
  43 + })
  44 +}
  45 +
  46 +// 导出租户 Excel
  47 +export function exportTenantExcel(query) {
  48 + return request({
  49 + url: '/system/tenant/export-excel',
  50 + method: 'get',
  51 + params: query,
  52 + responseType: 'blob'
  53 + })
  54 +}
... ...
yudao-admin-ui/src/utils/request.js
... ... @@ -3,6 +3,7 @@ import { Notification, MessageBox, Message } from &#39;element-ui&#39;
3 3 import store from '@/store'
4 4 import { getToken } from '@/utils/auth'
5 5 import errorCode from '@/utils/errorCode'
  6 +import Cookies from "js-cookie";
6 7  
7 8 axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
8 9 // 创建axios实例
... ... @@ -19,6 +20,11 @@ service.interceptors.request.use(config =&gt; {
19 20 if (getToken() && !isToken) {
20 21 config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定义token 请根据实际情况自行修改
21 22 }
  23 + // 设置租户
  24 + const tenantId = Cookies.get('tenantId');
  25 + if (tenantId) {
  26 + config.headers['tenant-id'] = tenantId;
  27 + }
22 28 // get请求映射params参数
23 29 if (config.method === 'get' && config.params) {
24 30 let url = config.url + '?';
... ...
yudao-admin-ui/src/views/login.vue
... ... @@ -2,6 +2,11 @@
2 2 <div class="login">
3 3 <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form">
4 4 <h3 class="title">芋道后台管理系统</h3>
  5 + <el-form-item prop="tenantName">
  6 + <el-input v-model="loginForm.tenantName" type="text" auto-complete="off" placeholder='租户'>
  7 + <svg-icon slot="prefix" icon-class="tree" class="el-input__icon input-icon" />
  8 + </el-input>
  9 + </el-form-item>
5 10 <el-form-item prop="username">
6 11 <el-input v-model="loginForm.username" type="text" auto-complete="off" placeholder="账号">
7 12 <svg-icon slot="prefix" icon-class="user" class="el-input__icon input-icon" />
... ... @@ -46,6 +51,7 @@
46 51  
47 52 <script>
48 53 import { getCodeImg,socialAuthRedirect } from "@/api/login";
  54 +import { getTenantIdByName } from "@/api/system/tenant";
49 55 import Cookies from "js-cookie";
50 56 import { encrypt, decrypt } from '@/utils/jsencrypt'
51 57 import {InfApiErrorLogProcessStatusEnum, SysUserSocialTypeEnum} from "@/utils/constants";
... ... @@ -60,9 +66,29 @@ export default {
60 66 password: "admin123",
61 67 rememberMe: false,
62 68 code: "",
63   - uuid: ""
  69 + uuid: "",
  70 + tenantName: "芋道源码",
64 71 },
65 72 loginRules: {
  73 + tenantName: [
  74 + { required: true, trigger: "blur", message: "租户不能为空" },
  75 + {
  76 + validator: (rule, value, callback) => {
  77 + // debugger
  78 + getTenantIdByName(value).then(res => {
  79 + const tenantId = res.data;
  80 + if (tenantId >= 0) {
  81 + // 设置租户
  82 + Cookies.set("tenantId", tenantId);
  83 + callback();
  84 + } else {
  85 + callback('租户不存在');
  86 + }
  87 + });
  88 + },
  89 + trigger: 'blur'
  90 + }
  91 + ],
66 92 username: [
67 93 { required: true, trigger: "blur", message: "用户名不能为空" }
68 94 ],
... ... @@ -103,25 +129,31 @@ export default {
103 129 const username = Cookies.get("username");
104 130 const password = Cookies.get("password");
105 131 const rememberMe = Cookies.get('rememberMe')
  132 + const tenantName = Cookies.get('tenantName');
106 133 this.loginForm = {
107 134 username: username === undefined ? this.loginForm.username : username,
108 135 password: password === undefined ? this.loginForm.password : decrypt(password),
109   - rememberMe: rememberMe === undefined ? false : Boolean(rememberMe)
  136 + rememberMe: rememberMe === undefined ? false : Boolean(rememberMe),
  137 + tenantName: tenantName === undefined ? this.loginForm.tenantName : tenantName,
110 138 };
111 139 },
112 140 handleLogin() {
113 141 this.$refs.loginForm.validate(valid => {
114 142 if (valid) {
115 143 this.loading = true;
  144 + // 设置 Cookie
116 145 if (this.loginForm.rememberMe) {
117 146 Cookies.set("username", this.loginForm.username, { expires: 30 });
118 147 Cookies.set("password", encrypt(this.loginForm.password), { expires: 30 });
119 148 Cookies.set('rememberMe', this.loginForm.rememberMe, { expires: 30 });
  149 + Cookies.set('tenantName', this.loginForm.tenantName, { expires: 30 });
120 150 } else {
121 151 Cookies.remove("username");
122 152 Cookies.remove("password");
123 153 Cookies.remove('rememberMe');
  154 + Cookies.remove('tenantName');
124 155 }
  156 + // 发起登陆
125 157 this.$store.dispatch("Login", this.loginForm).then(() => {
126 158 this.$router.push({ path: this.redirect || "/" }).catch(()=>{});
127 159 }).catch(() => {
... ... @@ -167,7 +199,7 @@ export default {
167 199 .login-form {
168 200 border-radius: 6px;
169 201 background: #ffffff;
170   - width: 400px;
  202 + width: 500px;
171 203 padding: 25px 25px 5px 25px;
172 204 .el-input {
173 205 height: 38px;
... ...
yudao-admin-ui/src/views/system/tenant/index.vue 0 → 100755
  1 +<template>
  2 + <div class="app-container">
  3 +
  4 + <!-- 搜索工作栏 -->
  5 + <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
  6 + <el-form-item label="租户名" prop="name">
  7 + <el-input v-model="queryParams.name" placeholder="请输入租户名" clearable size="small" @keyup.enter.native="handleQuery"/>
  8 + </el-form-item>
  9 + <el-form-item label="联系人" prop="contactName">
  10 + <el-input v-model="queryParams.contactName" placeholder="请输入联系人" clearable size="small" @keyup.enter.native="handleQuery"/>
  11 + </el-form-item>
  12 + <el-form-item label="联系手机" prop="contactMobile">
  13 + <el-input v-model="queryParams.contactMobile" placeholder="请输入联系手机" clearable size="small" @keyup.enter.native="handleQuery"/>
  14 + </el-form-item>
  15 + <el-form-item label="租户状态" prop="status">
  16 + <el-select v-model="queryParams.status" placeholder="请选择租户状态" clearable size="small">
  17 + <el-option v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
  18 + :key="dict.value" :label="dict.label" :value="dict.value"/>
  19 + </el-select>
  20 + </el-form-item>
  21 + <el-form-item label="创建时间">
  22 + <el-date-picker v-model="dateRangeCreateTime" size="small" style="width: 240px" value-format="yyyy-MM-dd"
  23 + type="daterange" range-separator="-" start-placeholder="开始日期" end-placeholder="结束日期" />
  24 + </el-form-item>
  25 + <el-form-item>
  26 + <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
  27 + <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
  28 + </el-form-item>
  29 + </el-form>
  30 +
  31 + <!-- 操作工具栏 -->
  32 + <el-row :gutter="10" class="mb8">
  33 + <el-col :span="1.5">
  34 + <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd"
  35 + v-hasPermi="['system:tenant:create']">新增</el-button>
  36 + </el-col>
  37 + <el-col :span="1.5">
  38 + <el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExport"
  39 + v-hasPermi="['system:tenant:export']">导出</el-button>
  40 + </el-col>
  41 + <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
  42 + </el-row>
  43 +
  44 + <!-- 列表 -->
  45 + <el-table v-loading="loading" :data="list">
  46 + <el-table-column label="租户编号" align="center" prop="id" />
  47 + <el-table-column label="租户名" align="center" prop="name" />
  48 + <el-table-column label="联系人" align="center" prop="contactName" />
  49 + <el-table-column label="联系手机" align="center" prop="contactMobile" />
  50 + <el-table-column label="租户状态" align="center" prop="status">
  51 + <template slot-scope="scope">
  52 + <span>{{ getDictDataLabel(DICT_TYPE.SYS_COMMON_STATUS, scope.row.status) }}</span>
  53 + </template>
  54 + </el-table-column>
  55 + <el-table-column label="创建时间" align="center" prop="createTime" width="180">
  56 + <template slot-scope="scope">
  57 + <span>{{ parseTime(scope.row.createTime) }}</span>
  58 + </template>
  59 + </el-table-column>
  60 + <el-table-column label="操作" align="center" class-name="small-padding fixed-width">
  61 + <template slot-scope="scope">
  62 + <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)"
  63 + v-hasPermi="['system:tenant:update']">修改</el-button>
  64 + <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)"
  65 + v-hasPermi="['system:tenant:delete']">删除</el-button>
  66 + </template>
  67 + </el-table-column>
  68 + </el-table>
  69 + <!-- 分页组件 -->
  70 + <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
  71 + @pagination="getList"/>
  72 +
  73 + <!-- 对话框(添加 / 修改) -->
  74 + <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
  75 + <el-form ref="form" :model="form" :rules="rules" label-width="80px">
  76 + <el-form-item label="租户名" prop="name">
  77 + <el-input v-model="form.name" placeholder="请输入租户名" />
  78 + </el-form-item>
  79 + <el-form-item label="联系人" prop="contactName">
  80 + <el-input v-model="form.contactName" placeholder="请输入联系人" />
  81 + </el-form-item>
  82 + <el-form-item label="联系手机" prop="contactMobile">
  83 + <el-input v-model="form.contactMobile" placeholder="请输入联系手机" />
  84 + </el-form-item>
  85 + <el-form-item label="租户状态" prop="status">
  86 + <el-radio-group v-model="form.status">
  87 + <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)"
  88 + :key="dict.value" :label="parseInt(dict.value)">{{dict.label}}</el-radio>
  89 + </el-radio-group>
  90 + </el-form-item>
  91 + </el-form>
  92 + <div slot="footer" class="dialog-footer">
  93 + <el-button type="primary" @click="submitForm">确 定</el-button>
  94 + <el-button @click="cancel">取 消</el-button>
  95 + </div>
  96 + </el-dialog>
  97 + </div>
  98 +</template>
  99 +
  100 +<script>
  101 +import { createTenant, updateTenant, deleteTenant, getTenant, getTenantPage, exportTenantExcel } from "@/api/system/tenant";
  102 +import { SysCommonStatusEnum } from '@/utils/constants'
  103 +
  104 +export default {
  105 + name: "Tenant",
  106 + components: {
  107 + },
  108 + data() {
  109 + return {
  110 + // 遮罩层
  111 + loading: true,
  112 + // 显示搜索条件
  113 + showSearch: true,
  114 + // 总条数
  115 + total: 0,
  116 + // 租户列表
  117 + list: [],
  118 + // 弹出层标题
  119 + title: "",
  120 + // 是否显示弹出层
  121 + open: false,
  122 + dateRangeCreateTime: [],
  123 + // 查询参数
  124 + queryParams: {
  125 + pageNo: 1,
  126 + pageSize: 10,
  127 + name: null,
  128 + contactName: null,
  129 + contactMobile: null,
  130 + status: undefined,
  131 + },
  132 + // 表单参数
  133 + form: {},
  134 + // 表单校验
  135 + rules: {
  136 + name: [{ required: true, message: "租户名不能为空", trigger: "blur" }],
  137 + contactName: [{ required: true, message: "联系人不能为空", trigger: "blur" }],
  138 + status: [{ required: true, message: "租户状态(0正常 1停用)不能为空", trigger: "blur" }],
  139 + }
  140 + };
  141 + },
  142 + created() {
  143 + this.getList();
  144 + },
  145 + methods: {
  146 + /** 查询列表 */
  147 + getList() {
  148 + this.loading = true;
  149 + // 处理查询参数
  150 + let params = {...this.queryParams};
  151 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  152 + // 执行查询
  153 + getTenantPage(params).then(response => {
  154 + this.list = response.data.list;
  155 + this.total = response.data.total;
  156 + this.loading = false;
  157 + });
  158 + },
  159 + /** 取消按钮 */
  160 + cancel() {
  161 + this.open = false;
  162 + this.reset();
  163 + },
  164 + /** 表单重置 */
  165 + reset() {
  166 + this.form = {
  167 + id: undefined,
  168 + name: undefined,
  169 + contactName: undefined,
  170 + contactMobile: undefined,
  171 + status: SysCommonStatusEnum.ENABLE,
  172 + };
  173 + this.resetForm("form");
  174 + },
  175 + /** 搜索按钮操作 */
  176 + handleQuery() {
  177 + this.queryParams.pageNo = 1;
  178 + this.getList();
  179 + },
  180 + /** 重置按钮操作 */
  181 + resetQuery() {
  182 + this.dateRangeCreateTime = [];
  183 + this.resetForm("queryForm");
  184 + this.handleQuery();
  185 + },
  186 + /** 新增按钮操作 */
  187 + handleAdd() {
  188 + this.reset();
  189 + this.open = true;
  190 + this.title = "添加租户";
  191 + },
  192 + /** 修改按钮操作 */
  193 + handleUpdate(row) {
  194 + this.reset();
  195 + const id = row.id;
  196 + getTenant(id).then(response => {
  197 + this.form = response.data;
  198 + this.open = true;
  199 + this.title = "修改租户";
  200 + });
  201 + },
  202 + /** 提交按钮 */
  203 + submitForm() {
  204 + this.$refs["form"].validate(valid => {
  205 + if (!valid) {
  206 + return;
  207 + }
  208 + // 修改的提交
  209 + if (this.form.id != null) {
  210 + updateTenant(this.form).then(response => {
  211 + this.msgSuccess("修改成功");
  212 + this.open = false;
  213 + this.getList();
  214 + });
  215 + return;
  216 + }
  217 + // 添加的提交
  218 + createTenant(this.form).then(response => {
  219 + this.msgSuccess("新增成功");
  220 + this.open = false;
  221 + this.getList();
  222 + });
  223 + });
  224 + },
  225 + /** 删除按钮操作 */
  226 + handleDelete(row) {
  227 + const id = row.id;
  228 + this.$confirm('是否确认删除租户编号为"' + id + '"的数据项?', "警告", {
  229 + confirmButtonText: "确定",
  230 + cancelButtonText: "取消",
  231 + type: "warning"
  232 + }).then(function() {
  233 + return deleteTenant(id);
  234 + }).then(() => {
  235 + this.getList();
  236 + this.msgSuccess("删除成功");
  237 + })
  238 + },
  239 + /** 导出按钮操作 */
  240 + handleExport() {
  241 + // 处理查询参数
  242 + let params = {...this.queryParams};
  243 + params.pageNo = undefined;
  244 + params.pageSize = undefined;
  245 + this.addBeginAndEndTime(params, this.dateRangeCreateTime, 'createTime');
  246 + // 执行导出
  247 + this.$confirm('是否确认导出所有租户数据项?', "警告", {
  248 + confirmButtonText: "确定",
  249 + cancelButtonText: "取消",
  250 + type: "warning"
  251 + }).then(function() {
  252 + return exportTenantExcel(params);
  253 + }).then(response => {
  254 + this.downloadExcel(response, '租户.xls');
  255 + })
  256 + }
  257 + }
  258 +};
  259 +</script>
... ...
yudao-core-service/pom.xml
... ... @@ -92,6 +92,11 @@
92 92  
93 93 <!-- 工具类相关 -->
94 94 <dependency>
  95 + <groupId>cn.iocoder.boot</groupId>
  96 + <artifactId>yudao-spring-boot-starter-tenant</artifactId>
  97 + </dependency>
  98 +
  99 + <dependency>
95 100 <groupId>com.google.guava</groupId>
96 101 <artifactId>guava</artifactId>
97 102 </dependency>
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/file/InfFileDO.java
1 1 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.file;
2 2  
3 3 import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
4 5 import com.baomidou.mybatisplus.annotation.IdType;
5 6 import com.baomidou.mybatisplus.annotation.TableField;
6 7 import com.baomidou.mybatisplus.annotation.TableId;
... ... @@ -21,7 +22,7 @@ import java.io.InputStream;
21 22 @Builder
22 23 @NoArgsConstructor
23 24 @AllArgsConstructor
24   -public class InfFileDO extends BaseDO {
  25 +public class InfFileDO extends TenantBaseDO {
25 26  
26 27 /**
27 28 * 文件路径
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4 4 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
5   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
6 6 import com.baomidou.mybatisplus.annotation.TableId;
7 7 import com.baomidou.mybatisplus.annotation.TableName;
8 8 import lombok.*;
... ... @@ -21,7 +21,7 @@ import java.util.Date;
21 21 @Builder
22 22 @NoArgsConstructor
23 23 @AllArgsConstructor
24   -public class InfApiAccessLogDO extends BaseDO {
  24 +public class InfApiAccessLogDO extends TenantBaseDO {
25 25  
26 26 /**
27 27 * 编号
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/infra/dal/dataobject/logger/InfApiErrorLogDO.java
1 1 package cn.iocoder.yudao.coreservice.modules.infra.dal.dataobject.logger;
2 2  
3   -import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 3 import cn.iocoder.yudao.coreservice.modules.infra.enums.logger.InfApiErrorLogProcessStatusEnum;
  4 +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
  5 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
6 6 import com.baomidou.mybatisplus.annotation.TableId;
7 7 import com.baomidou.mybatisplus.annotation.TableName;
8 8 import lombok.*;
... ... @@ -21,7 +21,7 @@ import java.util.Date;
21 21 @Builder
22 22 @NoArgsConstructor
23 23 @AllArgsConstructor
24   -public class InfApiErrorLogDO extends BaseDO {
  24 +public class InfApiErrorLogDO extends TenantBaseDO {
25 25  
26 26 /**
27 27 * 编号
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/member/dal/dataobject/user/MbrUserDO.java
1 1 package cn.iocoder.yudao.coreservice.modules.member.dal.dataobject.user;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  4 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
5 5 import com.baomidou.mybatisplus.annotation.TableId;
6 6 import com.baomidou.mybatisplus.annotation.TableName;
7 7 import lombok.*;
... ... @@ -22,7 +22,7 @@ import java.util.Date;
22 22 @Builder
23 23 @NoArgsConstructor
24 24 @AllArgsConstructor
25   -public class MbrUserDO extends BaseDO {
  25 +public class MbrUserDO extends TenantBaseDO {
26 26  
27 27 /**
28 28 * 用户ID
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/auth/SysUserSessionDO.java
1 1 package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.auth;
2 2  
3 3 import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
4   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
5 4 import cn.iocoder.yudao.framework.security.core.LoginUser;
  5 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
6 6 import com.baomidou.mybatisplus.annotation.IdType;
7 7 import com.baomidou.mybatisplus.annotation.TableId;
8 8 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -25,7 +25,7 @@ import java.util.Date;
25 25 @Data
26 26 @Builder
27 27 @EqualsAndHashCode(callSuper = true)
28   -public class SysUserSessionDO extends BaseDO {
  28 +public class SysUserSessionDO extends TenantBaseDO {
29 29  
30 30 /**
31 31 * 会话编号, 即 sessionId
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/dataobject/tenant/SysTenantDO.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant;
  2 +
  3 +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
  4 +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
  5 +import com.baomidou.mybatisplus.annotation.TableName;
  6 +import lombok.*;
  7 +
  8 +/**
  9 + * 租户 DO
  10 + *
  11 + * @author 芋道源码
  12 + */
  13 +@TableName(value = "sys_tenant", autoResultMap = true)
  14 +@Data
  15 +@EqualsAndHashCode(callSuper = true)
  16 +@ToString(callSuper = true)
  17 +@Builder
  18 +@AllArgsConstructor
  19 +@NoArgsConstructor
  20 +public class SysTenantDO extends BaseDO {
  21 +
  22 + /**
  23 + * 租户编号,自增
  24 + */
  25 + private Long id;
  26 + /**
  27 + * 租户名,唯一
  28 + */
  29 + private String name;
  30 + /**
  31 + * 联系人
  32 + */
  33 + private String contactName;
  34 + /**
  35 + * 联系手机
  36 + */
  37 + private String contactMobile;
  38 + /**
  39 + * 帐号状态
  40 + *
  41 + * 枚举 {@link CommonStatusEnum}
  42 + */
  43 + private Integer status;
  44 +
  45 +}
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.system.enums.common.SysSexEnum;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5   -import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
6 5 import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler;
  6 +import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
7 7 import com.baomidou.mybatisplus.annotation.TableField;
8 8 import com.baomidou.mybatisplus.annotation.TableId;
9 9 import com.baomidou.mybatisplus.annotation.TableName;
... ... @@ -24,7 +24,7 @@ import java.util.Set;
24 24 @Builder
25 25 @NoArgsConstructor
26 26 @AllArgsConstructor
27   -public class SysUserDO extends BaseDO {
  27 +public class SysUserDO extends TenantBaseDO {
28 28  
29 29 /**
30 30 * 用户ID
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/dal/mysql/tenant/SysTenantCoreMapper.java 0 → 100644
  1 +package cn.iocoder.yudao.coreservice.modules.system.dal.mysql.tenant;
  2 +
  3 +import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.tenant.SysTenantDO;
  4 +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import org.apache.ibatis.annotations.Mapper;
  6 +
  7 +@Mapper
  8 +public interface SysTenantCoreMapper extends BaseMapperX<SysTenantDO> {
  9 +}
... ...
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/system/mq/message/sms/SysSmsSendMessage.java
1 1 package cn.iocoder.yudao.coreservice.modules.system.mq.message.sms;
2 2  
3 3 import cn.iocoder.yudao.framework.common.core.KeyValue;
4   -import cn.iocoder.yudao.framework.mq.core.stream.StreamMessage;
  4 +import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessage;
5 5 import lombok.Data;
  6 +import lombok.EqualsAndHashCode;
6 7  
7 8 import javax.validation.constraints.NotNull;
8 9 import java.util.List;
... ... @@ -13,7 +14,8 @@ import java.util.List;
13 14 * @author 芋道源码
14 15 */
15 16 @Data
16   -public class SysSmsSendMessage implements StreamMessage {
  17 +@EqualsAndHashCode(callSuper = true)
  18 +public class SysSmsSendMessage extends AbstractStreamMessage {
17 19  
18 20 /**
19 21 * 短信日志编号
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.coreservice.modules.system.mq.message.sms.SysSmsSendMessage;
4 4 import cn.iocoder.yudao.framework.common.core.KeyValue;
5   -import cn.iocoder.yudao.framework.mq.core.util.RedisMessageUtils;
  5 +import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate;
6 6 import lombok.extern.slf4j.Slf4j;
7   -import org.springframework.data.redis.core.StringRedisTemplate;
8 7 import org.springframework.stereotype.Component;
9 8  
10 9 import javax.annotation.Resource;
... ... @@ -21,7 +20,7 @@ import java.util.List;
21 20 public class SysSmsCoreProducer {
22 21  
23 22 @Resource
24   - private StringRedisTemplate stringRedisTemplate;
  23 + private RedisMQTemplate redisMQTemplate;
25 24  
26 25 /**
27 26 * 发送 {@link SysSmsSendMessage} 消息
... ... @@ -36,7 +35,7 @@ public class SysSmsCoreProducer {
36 35 Long channelId, String apiTemplateId, List<KeyValue<String, Object>> templateParams) {
37 36 SysSmsSendMessage message = new SysSmsSendMessage().setLogId(logId).setMobile(mobile);
38 37 message.setChannelId(channelId).setApiTemplateId(apiTemplateId).setTemplateParams(templateParams);
39   - RedisMessageUtils.sendStreamMessage(stringRedisTemplate, message);
  38 + redisMQTemplate.send(message);
40 39 }
41 40  
42 41 }
... ...