Commit 2598c033a95d4b61d5f5ab3da5f1414f25c510d6
1 parent
6b6d676a
【新增】【优化】新建租户时,自动创建对应的管理员账号、角色等基础信息
Showing
34 changed files
with
425 additions
and
64 deletions
yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java
| @@ -147,4 +147,7 @@ public class CollectionUtils { | @@ -147,4 +147,7 @@ public class CollectionUtils { | ||
| 147 | coll.add(item); | 147 | coll.add(item); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | + public static <T> Collection<T> singleton(T deptId) { | ||
| 151 | + return deptId == null ? Collections.emptyList() : Collections.singleton(deptId); | ||
| 152 | + } | ||
| 150 | } | 153 | } |
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/config/YudaoTenantSecurityAutoConfiguration.java
| @@ -2,7 +2,9 @@ package cn.iocoder.yudao.framework.tenant.config; | @@ -2,7 +2,9 @@ package cn.iocoder.yudao.framework.tenant.config; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; | 3 | import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; |
| 4 | import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; | 4 | import cn.iocoder.yudao.framework.tenant.core.security.TenantSecurityWebFilter; |
| 5 | +import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; | ||
| 5 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 6 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| 7 | +import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | ||
| 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; | 8 | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; | 9 | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| 8 | import org.springframework.boot.web.servlet.FilterRegistrationBean; | 10 | import org.springframework.boot.web.servlet.FilterRegistrationBean; |
| @@ -22,9 +24,12 @@ public class YudaoTenantSecurityAutoConfiguration { | @@ -22,9 +24,12 @@ public class YudaoTenantSecurityAutoConfiguration { | ||
| 22 | 24 | ||
| 23 | @Bean | 25 | @Bean |
| 24 | public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties, | 26 | public FilterRegistrationBean<TenantSecurityWebFilter> tenantSecurityWebFilter(TenantProperties tenantProperties, |
| 25 | - WebProperties webProperties) { | 27 | + WebProperties webProperties, |
| 28 | + GlobalExceptionHandler globalExceptionHandler, | ||
| 29 | + TenantFrameworkService tenantFrameworkService) { | ||
| 26 | FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>(); | 30 | FilterRegistrationBean<TenantSecurityWebFilter> registrationBean = new FilterRegistrationBean<>(); |
| 27 | - registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties)); | 31 | + registrationBean.setFilter(new TenantSecurityWebFilter(tenantProperties, webProperties, |
| 32 | + globalExceptionHandler, tenantFrameworkService)); | ||
| 28 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER); | 33 | registrationBean.setOrder(WebFilterOrderEnum.TENANT_SECURITY_FILTER); |
| 29 | return registrationBean; | 34 | return registrationBean; |
| 30 | } | 35 | } |
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/context/TenantContextHolder.java
| @@ -12,11 +12,6 @@ public class TenantContextHolder { | @@ -12,11 +12,6 @@ public class TenantContextHolder { | ||
| 12 | private static final ThreadLocal<Long> TENANT_ID = new TransmittableThreadLocal<>(); | 12 | private static final ThreadLocal<Long> TENANT_ID = new TransmittableThreadLocal<>(); |
| 13 | 13 | ||
| 14 | /** | 14 | /** |
| 15 | - * 租户编号 - 空 | ||
| 16 | - */ | ||
| 17 | - private static final Long TENANT_ID_NULL = 0L; | ||
| 18 | - | ||
| 19 | - /** | ||
| 20 | * 获得租户编号。 | 15 | * 获得租户编号。 |
| 21 | * | 16 | * |
| 22 | * @return 租户编号 | 17 | * @return 租户编号 |
| @@ -38,15 +33,6 @@ public class TenantContextHolder { | @@ -38,15 +33,6 @@ public class TenantContextHolder { | ||
| 38 | return tenantId; | 33 | return tenantId; |
| 39 | } | 34 | } |
| 40 | 35 | ||
| 41 | - /** | ||
| 42 | - * 在一些前端场景下,可能无法请求带上租户。例如说,<img /> 方式获取图片等 | ||
| 43 | - * 此时,暂时的解决方案,是在该接口的 Controller 方法上,调用该方法 | ||
| 44 | - * TODO 芋艿:思考有没更合适的方案,目标是去掉该方法 | ||
| 45 | - */ | ||
| 46 | - public static void setNullTenantId() { | ||
| 47 | - TENANT_ID.set(TENANT_ID_NULL); | ||
| 48 | - } | ||
| 49 | - | ||
| 50 | public static void setTenantId(Long tenantId) { | 36 | public static void setTenantId(Long tenantId) { |
| 51 | TENANT_ID.set(tenantId); | 37 | TENANT_ID.set(tenantId); |
| 52 | } | 38 | } |
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/security/TenantSecurityWebFilter.java
| @@ -8,8 +8,10 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; | @@ -8,8 +8,10 @@ import cn.iocoder.yudao.framework.security.core.LoginUser; | ||
| 8 | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; | 8 | import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; |
| 9 | import cn.iocoder.yudao.framework.tenant.config.TenantProperties; | 9 | import cn.iocoder.yudao.framework.tenant.config.TenantProperties; |
| 10 | import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; | 10 | import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; |
| 11 | +import cn.iocoder.yudao.framework.tenant.core.service.TenantFrameworkService; | ||
| 11 | import cn.iocoder.yudao.framework.web.config.WebProperties; | 12 | import cn.iocoder.yudao.framework.web.config.WebProperties; |
| 12 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; | 13 | import cn.iocoder.yudao.framework.web.core.filter.ApiRequestFilter; |
| 14 | +import cn.iocoder.yudao.framework.web.core.handler.GlobalExceptionHandler; | ||
| 13 | import lombok.extern.slf4j.Slf4j; | 15 | import lombok.extern.slf4j.Slf4j; |
| 14 | import org.springframework.util.AntPathMatcher; | 16 | import org.springframework.util.AntPathMatcher; |
| 15 | 17 | ||
| @@ -24,6 +26,7 @@ import java.util.Objects; | @@ -24,6 +26,7 @@ import java.util.Objects; | ||
| 24 | * 多租户 Security Web 过滤器 | 26 | * 多租户 Security Web 过滤器 |
| 25 | * 1. 如果是登陆的用户,校验是否有权限访问该租户,避免越权问题。 | 27 | * 1. 如果是登陆的用户,校验是否有权限访问该租户,避免越权问题。 |
| 26 | * 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。 | 28 | * 2. 如果请求未带租户的编号,检查是否是忽略的 URL,否则也不允许访问。 |
| 29 | + * 3. 校验租户是合法,例如说被禁用、到期 | ||
| 27 | * | 30 | * |
| 28 | * 校验用户访问的租户,是否是其所在的租户, | 31 | * 校验用户访问的租户,是否是其所在的租户, |
| 29 | * | 32 | * |
| @@ -33,13 +36,21 @@ import java.util.Objects; | @@ -33,13 +36,21 @@ import java.util.Objects; | ||
| 33 | public class TenantSecurityWebFilter extends ApiRequestFilter { | 36 | public class TenantSecurityWebFilter extends ApiRequestFilter { |
| 34 | 37 | ||
| 35 | private final TenantProperties tenantProperties; | 38 | private final TenantProperties tenantProperties; |
| 39 | + | ||
| 36 | private final AntPathMatcher pathMatcher; | 40 | private final AntPathMatcher pathMatcher; |
| 37 | 41 | ||
| 42 | + private final GlobalExceptionHandler globalExceptionHandler; | ||
| 43 | + private final TenantFrameworkService tenantFrameworkService; | ||
| 44 | + | ||
| 38 | public TenantSecurityWebFilter(TenantProperties tenantProperties, | 45 | public TenantSecurityWebFilter(TenantProperties tenantProperties, |
| 39 | - WebProperties webProperties) { | 46 | + WebProperties webProperties, |
| 47 | + GlobalExceptionHandler globalExceptionHandler, | ||
| 48 | + TenantFrameworkService tenantFrameworkService) { | ||
| 40 | super(webProperties); | 49 | super(webProperties); |
| 41 | this.tenantProperties = tenantProperties; | 50 | this.tenantProperties = tenantProperties; |
| 42 | this.pathMatcher = new AntPathMatcher(); | 51 | this.pathMatcher = new AntPathMatcher(); |
| 52 | + this.globalExceptionHandler = globalExceptionHandler; | ||
| 53 | + this.tenantFrameworkService = tenantFrameworkService; | ||
| 43 | } | 54 | } |
| 44 | 55 | ||
| 45 | @Override | 56 | @Override |
| @@ -72,6 +83,17 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | @@ -72,6 +83,17 @@ public class TenantSecurityWebFilter extends ApiRequestFilter { | ||
| 72 | return; | 83 | return; |
| 73 | } | 84 | } |
| 74 | 85 | ||
| 86 | + // 3. 校验租户是合法,例如说被禁用、到期 | ||
| 87 | + if (tenantId != null) { | ||
| 88 | + try { | ||
| 89 | + tenantFrameworkService.validTenant(tenantId); | ||
| 90 | + } catch (Throwable ex) { | ||
| 91 | + CommonResult<?> result = globalExceptionHandler.allExceptionHandler(request, ex); | ||
| 92 | + ServletUtils.writeJSON(response, result); | ||
| 93 | + return; | ||
| 94 | + } | ||
| 95 | + } | ||
| 96 | + | ||
| 75 | // 继续过滤 | 97 | // 继续过滤 |
| 76 | chain.doFilter(request, response); | 98 | chain.doFilter(request, response); |
| 77 | } | 99 | } |
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/service/TenantFrameworkService.java
| @@ -16,4 +16,11 @@ public interface TenantFrameworkService { | @@ -16,4 +16,11 @@ public interface TenantFrameworkService { | ||
| 16 | */ | 16 | */ |
| 17 | List<Long> getTenantIds(); | 17 | List<Long> getTenantIds(); |
| 18 | 18 | ||
| 19 | + /** | ||
| 20 | + * 校验租户是否合法 | ||
| 21 | + * | ||
| 22 | + * @param id 租户编号 | ||
| 23 | + */ | ||
| 24 | + void validTenant(Long id); | ||
| 25 | + | ||
| 19 | } | 26 | } |
yudao-framework/yudao-spring-boot-starter-biz-tenant/src/main/java/cn/iocoder/yudao/framework/tenant/core/util/TenantUtils.java
0 → 100644
| 1 | +package cn.iocoder.yudao.framework.tenant.core.util; | ||
| 2 | + | ||
| 3 | +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; | ||
| 4 | + | ||
| 5 | +/** | ||
| 6 | + * 多租户 Util | ||
| 7 | + * | ||
| 8 | + * @author 芋道源码 | ||
| 9 | + */ | ||
| 10 | +public class TenantUtils { | ||
| 11 | + | ||
| 12 | + /** | ||
| 13 | + * 使用指定租户,执行对应的逻辑 | ||
| 14 | + * | ||
| 15 | + * @param tenantId 租户编号 | ||
| 16 | + * @param runnable 逻辑 | ||
| 17 | + */ | ||
| 18 | + public static void execute(Long tenantId, Runnable runnable) { | ||
| 19 | + Long oldTenantId = TenantContextHolder.getTenantId(); | ||
| 20 | + try { | ||
| 21 | + TenantContextHolder.setTenantId(tenantId); | ||
| 22 | + // 执行逻辑 | ||
| 23 | + runnable.run(); | ||
| 24 | + } finally { | ||
| 25 | + TenantContextHolder.setTenantId(oldTenantId); | ||
| 26 | + } | ||
| 27 | + } | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +} |
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
| @@ -104,10 +104,13 @@ public interface ErrorCodeConstants { | @@ -104,10 +104,13 @@ public interface ErrorCodeConstants { | ||
| 104 | 104 | ||
| 105 | // ========== 租户信息 1002014000 ========== | 105 | // ========== 租户信息 1002014000 ========== |
| 106 | ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002014000, "租户不存在"); | 106 | ErrorCode TENANT_NOT_EXISTS = new ErrorCode(1002014000, "租户不存在"); |
| 107 | + ErrorCode TENANT_DISABLE = new ErrorCode(1002014001, "名字为【{}】的租户已被禁用"); | ||
| 108 | + ErrorCode TENANT_EXPIRE = new ErrorCode(1002014002, "名字为【{}】的租户已过期"); | ||
| 107 | 109 | ||
| 108 | // ========== 租户套餐 1002015000 ========== | 110 | // ========== 租户套餐 1002015000 ========== |
| 109 | ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002015000, "租户套餐不存在"); | 111 | ErrorCode TENANT_PACKAGE_NOT_EXISTS = new ErrorCode(1002015000, "租户套餐不存在"); |
| 110 | ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1002015001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除"); | 112 | ErrorCode TENANT_PACKAGE_USED = new ErrorCode(1002015001, "租户正在使用该套餐,请给租户重新设置套餐后再尝试删除"); |
| 113 | + ErrorCode TENANT_PACKAGE_DISABLE = new ErrorCode(1002015002, "名字为【{}】的租户套餐已被禁用"); | ||
| 111 | 114 | ||
| 112 | // ========== 错误码模块 1002016000 ========== | 115 | // ========== 错误码模块 1002016000 ========== |
| 113 | ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002016000, "错误码不存在"); | 116 | ErrorCode ERROR_CODE_NOT_EXISTS = new ErrorCode(1002016000, "错误码不存在"); |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/RoleController.java
| @@ -40,7 +40,7 @@ public class RoleController { | @@ -40,7 +40,7 @@ public class RoleController { | ||
| 40 | @ApiOperation("创建角色") | 40 | @ApiOperation("创建角色") |
| 41 | @PreAuthorize("@ss.hasPermission('system:role:create')") | 41 | @PreAuthorize("@ss.hasPermission('system:role:create')") |
| 42 | public CommonResult<Long> createRole(@Valid @RequestBody RoleCreateReqVO reqVO) { | 42 | public CommonResult<Long> createRole(@Valid @RequestBody RoleCreateReqVO reqVO) { |
| 43 | - return success(roleService.createRole(reqVO)); | 43 | + return success(roleService.createRole(reqVO, null)); |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | @PutMapping("/update") | 46 | @PutMapping("/update") |
| @@ -88,7 +88,7 @@ public class RoleController { | @@ -88,7 +88,7 @@ public class RoleController { | ||
| 88 | public CommonResult<List<RoleSimpleRespVO>> getSimpleRoles() { | 88 | public CommonResult<List<RoleSimpleRespVO>> getSimpleRoles() { |
| 89 | // 获得角色列表,只要开启状态的 | 89 | // 获得角色列表,只要开启状态的 |
| 90 | List<RoleDO> list = roleService.getRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); | 90 | List<RoleDO> list = roleService.getRoles(Collections.singleton(CommonStatusEnum.ENABLE.getStatus())); |
| 91 | - // 排序后,返回个诶前端 | 91 | + // 排序后,返回给前端 |
| 92 | list.sort(Comparator.comparing(RoleDO::getSort)); | 92 | list.sort(Comparator.comparing(RoleDO::getSort)); |
| 93 | return success(RoleConvert.INSTANCE.convertList02(list)); | 93 | return success(RoleConvert.INSTANCE.convertList02(list)); |
| 94 | } | 94 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleBaseVO.java
| @@ -28,9 +28,6 @@ public class RoleBaseVO { | @@ -28,9 +28,6 @@ public class RoleBaseVO { | ||
| 28 | @NotNull(message = "显示顺序不能为空") | 28 | @NotNull(message = "显示顺序不能为空") |
| 29 | private Integer sort; | 29 | private Integer sort; |
| 30 | 30 | ||
| 31 | - @ApiModelProperty(value = "角色类型", required = true, example = "1", notes = "见 RoleTypeEnum 枚举") | ||
| 32 | - private Integer type; | ||
| 33 | - | ||
| 34 | @ApiModelProperty(value = "备注", example = "我是一个角色") | 31 | @ApiModelProperty(value = "备注", example = "我是一个角色") |
| 35 | private String remark; | 32 | private String remark; |
| 36 | 33 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantController.http
0 → 100644
| 1 | +### 创建租户 /admin-api/system/tenant/create | ||
| 2 | +POST {{baseUrl}}/system/tenant/create | ||
| 3 | +Content-Type: application/json | ||
| 4 | +Authorization: Bearer {{token}} | ||
| 5 | +tenant-id: {{adminTenentId}} | ||
| 6 | + | ||
| 7 | +{ | ||
| 8 | + "name": "芋道", | ||
| 9 | + "contactName": "芋艿", | ||
| 10 | + "contactMobile": "15601691300", | ||
| 11 | + "status": 0, | ||
| 12 | + "domain": "https://www.iocoder.cn", | ||
| 13 | + "packageId": 110, | ||
| 14 | + "expireTime": 1699545600000, | ||
| 15 | + "accountCount": 20, | ||
| 16 | + "username": "admin", | ||
| 17 | + "password": "123321" | ||
| 18 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/TenantPackageController.java
| 1 | package cn.iocoder.yudao.module.system.controller.admin.tenant; | 1 | package cn.iocoder.yudao.module.system.controller.admin.tenant; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 5 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 5 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; | ||
| 6 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; | ||
| 7 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO; | ||
| 8 | -import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; | 6 | +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.*; |
| 9 | import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; | 7 | import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 11 | import cn.iocoder.yudao.module.system.service.tenant.TenantPackageService; | 9 | import cn.iocoder.yudao.module.system.service.tenant.TenantPackageService; |
| @@ -82,4 +80,12 @@ public class TenantPackageController { | @@ -82,4 +80,12 @@ public class TenantPackageController { | ||
| 82 | return success(TenantPackageConvert.INSTANCE.convertPage(pageResult)); | 80 | return success(TenantPackageConvert.INSTANCE.convertPage(pageResult)); |
| 83 | } | 81 | } |
| 84 | 82 | ||
| 83 | + @GetMapping("/get-simple-list") | ||
| 84 | + @ApiOperation(value = "获取租户套餐精简信息列表", notes = "只包含被开启的租户套餐,主要用于前端的下拉选项") | ||
| 85 | + public CommonResult<List<TenantPackageSimpleRespVO>> getTenantPackageList() { | ||
| 86 | + // 获得角色列表,只要开启状态的 | ||
| 87 | + List<TenantPackageDO> list = tenantPackageService.getTenantPackageListByStatus(CommonStatusEnum.ENABLE.getStatus()); | ||
| 88 | + return success(TenantPackageConvert.INSTANCE.convertList02(list)); | ||
| 89 | + } | ||
| 90 | + | ||
| 85 | } | 91 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/packages/TenantPackageSimpleRespVO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages; | ||
| 2 | + | ||
| 3 | +import io.swagger.annotations.ApiModel; | ||
| 4 | +import io.swagger.annotations.ApiModelProperty; | ||
| 5 | +import lombok.Data; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotNull; | ||
| 8 | + | ||
| 9 | +@ApiModel("管理后台 - 租户套餐精简 Response VO") | ||
| 10 | +@Data | ||
| 11 | +public class TenantPackageSimpleRespVO { | ||
| 12 | + | ||
| 13 | + @ApiModelProperty(value = "套餐编号", required = true, example = "1024") | ||
| 14 | + @NotNull(message = "套餐编号不能为空") | ||
| 15 | + private Long id; | ||
| 16 | + | ||
| 17 | + @ApiModelProperty(value = "套餐名", required = true, example = "VIP") | ||
| 18 | + @NotNull(message = "套餐名不能为空") | ||
| 19 | + private String name; | ||
| 20 | + | ||
| 21 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantBaseVO.java
| @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; | @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; | ||
| 2 | 2 | ||
| 3 | import lombok.*; | 3 | import lombok.*; |
| 4 | import io.swagger.annotations.*; | 4 | import io.swagger.annotations.*; |
| 5 | +import org.hibernate.validator.constraints.URL; | ||
| 6 | + | ||
| 5 | import javax.validation.constraints.*; | 7 | import javax.validation.constraints.*; |
| 8 | +import java.util.Date; | ||
| 6 | 9 | ||
| 7 | /** | 10 | /** |
| 8 | * 租户 Base VO,提供给添加、修改、详细的子 VO 使用 | 11 | * 租户 Base VO,提供给添加、修改、详细的子 VO 使用 |
| @@ -22,8 +25,24 @@ public class TenantBaseVO { | @@ -22,8 +25,24 @@ public class TenantBaseVO { | ||
| 22 | @ApiModelProperty(value = "联系手机", example = "15601691300") | 25 | @ApiModelProperty(value = "联系手机", example = "15601691300") |
| 23 | private String contactMobile; | 26 | private String contactMobile; |
| 24 | 27 | ||
| 25 | - @ApiModelProperty(value = "租户状态(0正常 1停用)", required = true, example = "1") | ||
| 26 | - @NotNull(message = "租户状态(0正常 1停用)不能为空") | 28 | + @ApiModelProperty(value = "租户状态", required = true, example = "1") |
| 29 | + @NotNull(message = "租户状态") | ||
| 27 | private Integer status; | 30 | private Integer status; |
| 28 | 31 | ||
| 32 | + @ApiModelProperty(value = "绑定域名", example = "https://www.iocoder.cn") | ||
| 33 | + @URL(message = "绑定域名的地址非 URL 格式") | ||
| 34 | + private String domain; | ||
| 35 | + | ||
| 36 | + @ApiModelProperty(value = "租户套餐编号", required = true, example = "1024") | ||
| 37 | + @NotNull(message = "租户套餐编号不能为空") | ||
| 38 | + private Long packageId; | ||
| 39 | + | ||
| 40 | + @ApiModelProperty(value = "过期时间", required = true) | ||
| 41 | + @NotNull(message = "过期时间不能为空") | ||
| 42 | + private Date expireTime; | ||
| 43 | + | ||
| 44 | + @ApiModelProperty(value = "账号数量", required = true, example = "1024") | ||
| 45 | + @NotNull(message = "账号数量不能为空") | ||
| 46 | + private Integer accountCount; | ||
| 47 | + | ||
| 29 | } | 48 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantCreateReqVO.java
| @@ -2,6 +2,12 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; | @@ -2,6 +2,12 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; | ||
| 2 | 2 | ||
| 3 | import lombok.*; | 3 | import lombok.*; |
| 4 | import io.swagger.annotations.*; | 4 | import io.swagger.annotations.*; |
| 5 | +import org.hibernate.validator.constraints.Length; | ||
| 6 | + | ||
| 7 | +import javax.validation.constraints.NotBlank; | ||
| 8 | +import javax.validation.constraints.NotEmpty; | ||
| 9 | +import javax.validation.constraints.Pattern; | ||
| 10 | +import javax.validation.constraints.Size; | ||
| 5 | 11 | ||
| 6 | @ApiModel("管理后台 - 租户创建 Request VO") | 12 | @ApiModel("管理后台 - 租户创建 Request VO") |
| 7 | @Data | 13 | @Data |
| @@ -9,4 +15,15 @@ import io.swagger.annotations.*; | @@ -9,4 +15,15 @@ import io.swagger.annotations.*; | ||
| 9 | @ToString(callSuper = true) | 15 | @ToString(callSuper = true) |
| 10 | public class TenantCreateReqVO extends TenantBaseVO { | 16 | public class TenantCreateReqVO extends TenantBaseVO { |
| 11 | 17 | ||
| 18 | + @ApiModelProperty(value = "用户账号", required = true, example = "yudao") | ||
| 19 | + @NotBlank(message = "用户账号不能为空") | ||
| 20 | + @Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成") | ||
| 21 | + @Size(min = 4, max = 30, message = "用户账号长度为 4-30 个字符") | ||
| 22 | + private String username; | ||
| 23 | + | ||
| 24 | + @ApiModelProperty(value = "密码", required = true, example = "123456") | ||
| 25 | + @NotEmpty(message = "密码不能为空") | ||
| 26 | + @Length(min = 4, max = 16, message = "密码长度为 4-16 位") | ||
| 27 | + private String password; | ||
| 28 | + | ||
| 12 | } | 29 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserBaseVO.java
| 1 | package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; | 1 | package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.validation.Mobile; | ||
| 3 | import io.swagger.annotations.ApiModelProperty; | 4 | import io.swagger.annotations.ApiModelProperty; |
| 4 | import lombok.Data; | 5 | import lombok.Data; |
| 5 | -import org.hibernate.validator.constraints.Length; | ||
| 6 | 6 | ||
| 7 | import javax.validation.constraints.Email; | 7 | import javax.validation.constraints.Email; |
| 8 | import javax.validation.constraints.NotBlank; | 8 | import javax.validation.constraints.NotBlank; |
| @@ -42,7 +42,7 @@ public class UserBaseVO { | @@ -42,7 +42,7 @@ public class UserBaseVO { | ||
| 42 | private String email; | 42 | private String email; |
| 43 | 43 | ||
| 44 | @ApiModelProperty(value = "手机号码", example = "15601691300") | 44 | @ApiModelProperty(value = "手机号码", example = "15601691300") |
| 45 | - @Length(min = 11, max = 11, message = "手机号长度必须 11 位") | 45 | + @Mobile |
| 46 | private String mobile; | 46 | private String mobile; |
| 47 | 47 | ||
| 48 | @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类") | 48 | @ApiModelProperty(value = "用户性别", example = "1", notes = "参见 SexEnum 枚举类") |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/permission/RoleConvert.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.convert.permission; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.convert.permission; | ||
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; | 3 | import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.*; |
| 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 4 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 5 | +import cn.iocoder.yudao.module.system.service.permission.bo.RoleCreateReqBO; | ||
| 5 | import org.mapstruct.Mapper; | 6 | import org.mapstruct.Mapper; |
| 6 | import org.mapstruct.factory.Mappers; | 7 | import org.mapstruct.factory.Mappers; |
| 7 | 8 | ||
| @@ -22,4 +23,6 @@ public interface RoleConvert { | @@ -22,4 +23,6 @@ public interface RoleConvert { | ||
| 22 | 23 | ||
| 23 | List<RoleExcelVO> convertList03(List<RoleDO> list); | 24 | List<RoleExcelVO> convertList03(List<RoleDO> list); |
| 24 | 25 | ||
| 26 | + RoleDO convert(RoleCreateReqBO bean); | ||
| 27 | + | ||
| 25 | } | 28 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantConvert.java
| 1 | package cn.iocoder.yudao.module.system.convert.tenant; | 1 | package cn.iocoder.yudao.module.system.convert.tenant; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 3 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; | 4 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; |
| 4 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExcelVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExcelVO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; | 7 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUpdateReqVO; |
| 8 | +import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserCreateReqVO; | ||
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; |
| 8 | -import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||
| 9 | import org.mapstruct.Mapper; | 10 | import org.mapstruct.Mapper; |
| 10 | import org.mapstruct.factory.Mappers; | 11 | import org.mapstruct.factory.Mappers; |
| 11 | 12 | ||
| @@ -33,4 +34,12 @@ public interface TenantConvert { | @@ -33,4 +34,12 @@ public interface TenantConvert { | ||
| 33 | 34 | ||
| 34 | List<TenantExcelVO> convertList02(List<TenantDO> list); | 35 | List<TenantExcelVO> convertList02(List<TenantDO> list); |
| 35 | 36 | ||
| 37 | + default UserCreateReqVO convert02(TenantCreateReqVO bean) { | ||
| 38 | + UserCreateReqVO reqVO = new UserCreateReqVO(); | ||
| 39 | + reqVO.setUsername(bean.getUsername()); | ||
| 40 | + reqVO.setPassword(bean.getPassword()); | ||
| 41 | + reqVO.setNickname(bean.getContactName()).setMobile(bean.getContactMobile()); | ||
| 42 | + return reqVO; | ||
| 43 | + } | ||
| 44 | + | ||
| 36 | } | 45 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/convert/tenant/TenantPackageConvert.java
| 1 | package cn.iocoder.yudao.module.system.convert.tenant; | 1 | package cn.iocoder.yudao.module.system.convert.tenant; |
| 2 | 2 | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleSimpleRespVO; | ||
| 4 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageRespVO; |
| 7 | +import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageSimpleRespVO; | ||
| 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; | 8 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageUpdateReqVO; |
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 8 | import org.mapstruct.Mapper; | 10 | import org.mapstruct.Mapper; |
| @@ -30,4 +32,6 @@ public interface TenantPackageConvert { | @@ -30,4 +32,6 @@ public interface TenantPackageConvert { | ||
| 30 | 32 | ||
| 31 | PageResult<TenantPackageRespVO> convertPage(PageResult<TenantPackageDO> page); | 33 | PageResult<TenantPackageRespVO> convertPage(PageResult<TenantPackageDO> page); |
| 32 | 34 | ||
| 35 | + List<TenantPackageSimpleRespVO> convertList02(List<TenantPackageDO> list); | ||
| 36 | + | ||
| 33 | } | 37 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/permission/RoleDO.java
| @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; | 4 | import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; |
| 5 | import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; | 5 | import cn.iocoder.yudao.framework.mybatis.core.type.JsonLongSetTypeHandler; |
| 6 | import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; | 6 | import cn.iocoder.yudao.framework.security.core.enums.DataScopeEnum; |
| 7 | +import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; | ||
| 7 | import com.baomidou.mybatisplus.annotation.TableField; | 8 | import com.baomidou.mybatisplus.annotation.TableField; |
| 8 | import com.baomidou.mybatisplus.annotation.TableId; | 9 | import com.baomidou.mybatisplus.annotation.TableId; |
| 9 | import com.baomidou.mybatisplus.annotation.TableName; | 10 | import com.baomidou.mybatisplus.annotation.TableName; |
| @@ -50,7 +51,7 @@ public class RoleDO extends BaseDO { | @@ -50,7 +51,7 @@ public class RoleDO extends BaseDO { | ||
| 50 | /** | 51 | /** |
| 51 | * 角色类型 | 52 | * 角色类型 |
| 52 | * | 53 | * |
| 53 | - * 枚举 | 54 | + * 枚举 {@link RoleTypeEnum} |
| 54 | */ | 55 | */ |
| 55 | private Integer type; | 56 | private Integer type; |
| 56 | /** | 57 | /** |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/tenant/TenantPackageMapper.java
| @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | ||
| 7 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; | 7 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 8 | import org.apache.ibatis.annotations.Mapper; | 8 | import org.apache.ibatis.annotations.Mapper; |
| 9 | 9 | ||
| 10 | +import java.util.List; | ||
| 11 | + | ||
| 10 | /** | 12 | /** |
| 11 | * 租户套餐 Mapper | 13 | * 租户套餐 Mapper |
| 12 | * | 14 | * |
| @@ -24,4 +26,7 @@ public interface TenantPackageMapper extends BaseMapperX<TenantPackageDO> { | @@ -24,4 +26,7 @@ public interface TenantPackageMapper extends BaseMapperX<TenantPackageDO> { | ||
| 24 | .orderByDesc(TenantPackageDO::getId)); | 26 | .orderByDesc(TenantPackageDO::getId)); |
| 25 | } | 27 | } |
| 26 | 28 | ||
| 29 | + default List<TenantPackageDO> selectListByStatus(Integer status) { | ||
| 30 | + return selectList(TenantPackageDO::getStatus, status); | ||
| 31 | + } | ||
| 27 | } | 32 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/PermissionServiceImpl.java
| @@ -224,8 +224,6 @@ public class PermissionServiceImpl implements PermissionService { | @@ -224,8 +224,6 @@ public class PermissionServiceImpl implements PermissionService { | ||
| 224 | UserRoleDO::getRoleId); | 224 | UserRoleDO::getRoleId); |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | - | ||
| 228 | - | ||
| 229 | @Override | 227 | @Override |
| 230 | public void assignUserRole(Long userId, Set<Long> roleIds) { | 228 | public void assignUserRole(Long userId, Set<Long> roleIds) { |
| 231 | // 获得角色拥有角色编号 | 229 | // 获得角色拥有角色编号 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleService.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUp | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleUp | ||
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; | 8 | import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO; |
| 9 | import org.springframework.lang.Nullable; | 9 | import org.springframework.lang.Nullable; |
| 10 | 10 | ||
| 11 | +import javax.validation.Valid; | ||
| 11 | import java.util.Collection; | 12 | import java.util.Collection; |
| 12 | import java.util.List; | 13 | import java.util.List; |
| 13 | import java.util.Set; | 14 | import java.util.Set; |
| @@ -28,16 +29,17 @@ public interface RoleService { | @@ -28,16 +29,17 @@ public interface RoleService { | ||
| 28 | * 创建角色 | 29 | * 创建角色 |
| 29 | * | 30 | * |
| 30 | * @param reqVO 创建角色信息 | 31 | * @param reqVO 创建角色信息 |
| 32 | + * @param type 角色类型 | ||
| 31 | * @return 角色编号 | 33 | * @return 角色编号 |
| 32 | */ | 34 | */ |
| 33 | - Long createRole(RoleCreateReqVO reqVO); | 35 | + Long createRole(@Valid RoleCreateReqVO reqVO, Integer type); |
| 34 | 36 | ||
| 35 | /** | 37 | /** |
| 36 | * 更新角色 | 38 | * 更新角色 |
| 37 | * | 39 | * |
| 38 | * @param reqVO 更新角色信息 | 40 | * @param reqVO 更新角色信息 |
| 39 | */ | 41 | */ |
| 40 | - void updateRole(RoleUpdateReqVO reqVO); | 42 | + void updateRole(@Valid RoleUpdateReqVO reqVO); |
| 41 | 43 | ||
| 42 | /** | 44 | /** |
| 43 | * 删除角色 | 45 | * 删除角色 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceImpl.java
| @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.permission; | @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.service.permission; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.collection.CollectionUtil; | 4 | import cn.hutool.core.collection.CollectionUtil; |
| 5 | +import cn.hutool.core.util.ObjectUtil; | ||
| 5 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 6 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 7 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 8 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| @@ -120,12 +121,12 @@ public class RoleServiceImpl implements RoleService { | @@ -120,12 +121,12 @@ public class RoleServiceImpl implements RoleService { | ||
| 120 | } | 121 | } |
| 121 | 122 | ||
| 122 | @Override | 123 | @Override |
| 123 | - public Long createRole(RoleCreateReqVO reqVO) { | 124 | + public Long createRole(RoleCreateReqVO reqVO, Integer type) { |
| 124 | // 校验角色 | 125 | // 校验角色 |
| 125 | checkDuplicateRole(reqVO.getName(), reqVO.getCode(), null); | 126 | checkDuplicateRole(reqVO.getName(), reqVO.getCode(), null); |
| 126 | // 插入到数据库 | 127 | // 插入到数据库 |
| 127 | RoleDO role = RoleConvert.INSTANCE.convert(reqVO); | 128 | RoleDO role = RoleConvert.INSTANCE.convert(reqVO); |
| 128 | - role.setType(RoleTypeEnum.CUSTOM.getType()); | 129 | + role.setType(ObjectUtil.defaultIfNull(type, RoleTypeEnum.CUSTOM.getType())); |
| 129 | role.setStatus(CommonStatusEnum.ENABLE.getStatus()); | 130 | role.setStatus(CommonStatusEnum.ENABLE.getStatus()); |
| 130 | role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 | 131 | role.setDataScope(DataScopeEnum.ALL.getScope()); // 默认可查看所有数据。原因是,可能一些项目不需要项目权限 |
| 131 | roleMapper.insert(role); | 132 | roleMapper.insert(role); |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/permission/bo/RoleCreateReqBO.java
0 → 100644
| 1 | +package cn.iocoder.yudao.module.system.service.permission.bo; | ||
| 2 | + | ||
| 3 | +import lombok.Data; | ||
| 4 | + | ||
| 5 | +import javax.validation.constraints.NotBlank; | ||
| 6 | +import javax.validation.constraints.NotNull; | ||
| 7 | +import javax.validation.constraints.Size; | ||
| 8 | + | ||
| 9 | +/** | ||
| 10 | + * 角色创建 Request BO | ||
| 11 | + * | ||
| 12 | + * @author 芋道源码 | ||
| 13 | + */ | ||
| 14 | +@Data | ||
| 15 | +public class RoleCreateReqBO { | ||
| 16 | + | ||
| 17 | + /** | ||
| 18 | + * 租户编号 | ||
| 19 | + */ | ||
| 20 | + @NotNull(message = "租户编号不能为空") | ||
| 21 | + private Long tenantId; | ||
| 22 | + | ||
| 23 | + /** | ||
| 24 | + * 角色名称 | ||
| 25 | + */ | ||
| 26 | + @NotBlank(message = "角色名称不能为空") | ||
| 27 | + @Size(max = 30, message = "角色名称长度不能超过30个字符") | ||
| 28 | + private String name; | ||
| 29 | + | ||
| 30 | + /** | ||
| 31 | + * 角色标志 | ||
| 32 | + */ | ||
| 33 | + @NotBlank(message = "角色标志不能为空") | ||
| 34 | + @Size(max = 100, message = "角色标志长度不能超过100个字符") | ||
| 35 | + private String code; | ||
| 36 | + | ||
| 37 | + /** | ||
| 38 | + * 显示顺序 | ||
| 39 | + */ | ||
| 40 | + @NotNull(message = "显示顺序不能为空") | ||
| 41 | + private Integer sort; | ||
| 42 | + | ||
| 43 | + /** | ||
| 44 | + * 角色类型 | ||
| 45 | + */ | ||
| 46 | + @NotNull(message = "角色类型不能为空") | ||
| 47 | + private Integer type; | ||
| 48 | + | ||
| 49 | +} |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageService.java
| @@ -63,4 +63,20 @@ public interface TenantPackageService { | @@ -63,4 +63,20 @@ public interface TenantPackageService { | ||
| 63 | */ | 63 | */ |
| 64 | PageResult<TenantPackageDO> getTenantPackagePage(TenantPackagePageReqVO pageReqVO); | 64 | PageResult<TenantPackageDO> getTenantPackagePage(TenantPackagePageReqVO pageReqVO); |
| 65 | 65 | ||
| 66 | + /** | ||
| 67 | + * 校验租户套餐 | ||
| 68 | + * | ||
| 69 | + * @param id 编号 | ||
| 70 | + * @return 租户套餐 | ||
| 71 | + */ | ||
| 72 | + TenantPackageDO validTenantPackage(Long id); | ||
| 73 | + | ||
| 74 | + /** | ||
| 75 | + * 获得指定状态的租户套餐列表 | ||
| 76 | + * | ||
| 77 | + * @param status 状态 | ||
| 78 | + * @return 租户套餐 | ||
| 79 | + */ | ||
| 80 | + List<TenantPackageDO> getTenantPackageListByStatus(Integer status); | ||
| 81 | + | ||
| 66 | } | 82 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantPackageServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.tenant; | 1 | package cn.iocoder.yudao.module.system.service.tenant; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; | 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackageCreateReqVO; |
| 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; | 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.TenantPackagePageReqVO; |
| @@ -7,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | @@ -7,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.packages.Tenant | ||
| 7 | import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; | 8 | import cn.iocoder.yudao.module.system.convert.tenant.TenantPackageConvert; |
| 8 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantPackageDO; |
| 9 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; | 10 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantPackageMapper; |
| 11 | +import org.springframework.context.annotation.Lazy; | ||
| 10 | import org.springframework.stereotype.Service; | 12 | import org.springframework.stereotype.Service; |
| 11 | import org.springframework.validation.annotation.Validated; | 13 | import org.springframework.validation.annotation.Validated; |
| 12 | 14 | ||
| @@ -15,8 +17,7 @@ import java.util.Collection; | @@ -15,8 +17,7 @@ import java.util.Collection; | ||
| 15 | import java.util.List; | 17 | import java.util.List; |
| 16 | 18 | ||
| 17 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 18 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_PACKAGE_NOT_EXISTS; | ||
| 19 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_PACKAGE_USED; | 20 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; |
| 20 | 21 | ||
| 21 | /** | 22 | /** |
| 22 | * 租户套餐 Service 实现类 | 23 | * 租户套餐 Service 实现类 |
| @@ -31,6 +32,7 @@ public class TenantPackageServiceImpl implements TenantPackageService { | @@ -31,6 +32,7 @@ public class TenantPackageServiceImpl implements TenantPackageService { | ||
| 31 | private TenantPackageMapper tenantPackageMapper; | 32 | private TenantPackageMapper tenantPackageMapper; |
| 32 | 33 | ||
| 33 | @Resource | 34 | @Resource |
| 35 | + @Lazy // 避免循环依赖的报错 | ||
| 34 | private TenantService tenantService; | 36 | private TenantService tenantService; |
| 35 | 37 | ||
| 36 | @Override | 38 | @Override |
| @@ -88,4 +90,21 @@ public class TenantPackageServiceImpl implements TenantPackageService { | @@ -88,4 +90,21 @@ public class TenantPackageServiceImpl implements TenantPackageService { | ||
| 88 | return tenantPackageMapper.selectPage(pageReqVO); | 90 | return tenantPackageMapper.selectPage(pageReqVO); |
| 89 | } | 91 | } |
| 90 | 92 | ||
| 93 | + @Override | ||
| 94 | + public TenantPackageDO validTenantPackage(Long id) { | ||
| 95 | + TenantPackageDO tenantPackage = tenantPackageMapper.selectById(id); | ||
| 96 | + if (tenantPackage == null) { | ||
| 97 | + throw exception(TENANT_PACKAGE_NOT_EXISTS); | ||
| 98 | + } | ||
| 99 | + if (tenantPackage.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { | ||
| 100 | + throw exception(TENANT_PACKAGE_DISABLE, tenantPackage.getName()); | ||
| 101 | + } | ||
| 102 | + return tenantPackage; | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + @Override | ||
| 106 | + public List<TenantPackageDO> getTenantPackageListByStatus(Integer status) { | ||
| 107 | + return tenantPackageMapper.selectListByStatus(status); | ||
| 108 | + } | ||
| 109 | + | ||
| 91 | } | 110 | } |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/tenant/TenantServiceImpl.java
| 1 | package cn.iocoder.yudao.module.system.service.tenant; | 1 | package cn.iocoder.yudao.module.system.service.tenant; |
| 2 | 2 | ||
| 3 | +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||
| 3 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 4 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 4 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; | 5 | import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; |
| 6 | +import cn.iocoder.yudao.framework.common.util.date.DateUtils; | ||
| 7 | +import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; | ||
| 8 | +import cn.iocoder.yudao.module.system.controller.admin.permission.vo.role.RoleCreateReqVO; | ||
| 5 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; | 9 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantCreateReqVO; |
| 6 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; | 10 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantExportReqVO; |
| 7 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; | 11 | import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO; |
| @@ -9,15 +13,22 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUp | @@ -9,15 +13,22 @@ import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantUp | ||
| 9 | import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; | 13 | import cn.iocoder.yudao.module.system.convert.tenant.TenantConvert; |
| 10 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; | 14 | import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO; |
| 11 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; | 15 | import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper; |
| 16 | +import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; | ||
| 17 | +import cn.iocoder.yudao.module.system.enums.permission.RoleTypeEnum; | ||
| 18 | +import cn.iocoder.yudao.module.system.service.permission.PermissionService; | ||
| 19 | +import cn.iocoder.yudao.module.system.service.permission.RoleService; | ||
| 20 | +import cn.iocoder.yudao.module.system.service.user.AdminUserService; | ||
| 12 | import org.springframework.stereotype.Service; | 21 | import org.springframework.stereotype.Service; |
| 22 | +import org.springframework.transaction.annotation.Transactional; | ||
| 13 | import org.springframework.validation.annotation.Validated; | 23 | import org.springframework.validation.annotation.Validated; |
| 14 | 24 | ||
| 15 | import javax.annotation.Resource; | 25 | import javax.annotation.Resource; |
| 16 | import java.util.Collection; | 26 | import java.util.Collection; |
| 27 | +import java.util.Collections; | ||
| 17 | import java.util.List; | 28 | import java.util.List; |
| 18 | 29 | ||
| 19 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | 30 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 20 | -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.TENANT_NOT_EXISTS; | 31 | +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*; |
| 21 | 32 | ||
| 22 | /** | 33 | /** |
| 23 | * 租户 Service 实现类 | 34 | * 租户 Service 实现类 |
| @@ -31,6 +42,15 @@ public class TenantServiceImpl implements TenantService { | @@ -31,6 +42,15 @@ public class TenantServiceImpl implements TenantService { | ||
| 31 | @Resource | 42 | @Resource |
| 32 | private TenantMapper tenantMapper; | 43 | private TenantMapper tenantMapper; |
| 33 | 44 | ||
| 45 | + @Resource | ||
| 46 | + private TenantPackageService tenantPackageService; | ||
| 47 | + @Resource | ||
| 48 | + private AdminUserService userService; | ||
| 49 | + @Resource | ||
| 50 | + private RoleService roleService; | ||
| 51 | + @Resource | ||
| 52 | + private PermissionService permissionService; | ||
| 53 | + | ||
| 34 | @Override | 54 | @Override |
| 35 | public List<Long> getTenantIds() { | 55 | public List<Long> getTenantIds() { |
| 36 | List<TenantDO> tenants = tenantMapper.selectList(); | 56 | List<TenantDO> tenants = tenantMapper.selectList(); |
| @@ -38,18 +58,62 @@ public class TenantServiceImpl implements TenantService { | @@ -38,18 +58,62 @@ public class TenantServiceImpl implements TenantService { | ||
| 38 | } | 58 | } |
| 39 | 59 | ||
| 40 | @Override | 60 | @Override |
| 61 | + public void validTenant(Long id) { | ||
| 62 | + TenantDO tenant = tenantMapper.selectById(id); | ||
| 63 | + if (tenant == null) { | ||
| 64 | + throw exception(TENANT_NOT_EXISTS); | ||
| 65 | + } | ||
| 66 | + if (tenant.getStatus().equals(CommonStatusEnum.DISABLE.getStatus())) { | ||
| 67 | + throw exception(TENANT_DISABLE, tenant.getName()); | ||
| 68 | + } | ||
| 69 | + if (DateUtils.isExpired(tenant.getExpireTime())) { | ||
| 70 | + throw exception(TENANT_EXPIRE, tenant.getName()); | ||
| 71 | + } | ||
| 72 | + } | ||
| 73 | + | ||
| 74 | + @Override | ||
| 75 | + @Transactional(rollbackFor = Exception.class) | ||
| 41 | public Long createTenant(TenantCreateReqVO createReqVO) { | 76 | public Long createTenant(TenantCreateReqVO createReqVO) { |
| 42 | - // 插入 | 77 | + // 校验套餐被禁用 |
| 78 | + tenantPackageService.validTenantPackage(createReqVO.getPackageId()); | ||
| 79 | + | ||
| 80 | + // 创建租户 | ||
| 43 | TenantDO tenant = TenantConvert.INSTANCE.convert(createReqVO); | 81 | TenantDO tenant = TenantConvert.INSTANCE.convert(createReqVO); |
| 44 | tenantMapper.insert(tenant); | 82 | tenantMapper.insert(tenant); |
| 83 | + | ||
| 84 | + TenantUtils.execute(tenant.getId(), () -> { | ||
| 85 | + // 创建角色 | ||
| 86 | + Long roleId = createRole(); | ||
| 87 | + // 创建用户,并分配角色 | ||
| 88 | + Long userId = createUser(roleId, createReqVO); | ||
| 89 | + // 修改租户的管理员 | ||
| 90 | + tenantMapper.updateById(new TenantDO().setId(tenant.getId()).setContactUserId(userId)); | ||
| 91 | + }); | ||
| 45 | // 返回 | 92 | // 返回 |
| 46 | return tenant.getId(); | 93 | return tenant.getId(); |
| 47 | } | 94 | } |
| 48 | 95 | ||
| 96 | + private Long createUser(Long roleId, TenantCreateReqVO createReqVO) { | ||
| 97 | + // 创建用户 | ||
| 98 | + Long userId = userService.createUser(TenantConvert.INSTANCE.convert02(createReqVO)); | ||
| 99 | + // 分配角色 | ||
| 100 | + permissionService.assignUserRole(userId, Collections.singleton(roleId)); | ||
| 101 | + return userId; | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + private Long createRole() { | ||
| 105 | + RoleCreateReqVO reqVO = new RoleCreateReqVO(); | ||
| 106 | + reqVO.setName(RoleCodeEnum.ADMIN.name()).setCode(RoleCodeEnum.ADMIN.getKey()).setSort(0); | ||
| 107 | + return roleService.createRole(reqVO, RoleTypeEnum.SYSTEM.getType()); | ||
| 108 | + } | ||
| 109 | + | ||
| 49 | @Override | 110 | @Override |
| 50 | public void updateTenant(TenantUpdateReqVO updateReqVO) { | 111 | public void updateTenant(TenantUpdateReqVO updateReqVO) { |
| 51 | // 校验存在 | 112 | // 校验存在 |
| 52 | this.validateTenantExists(updateReqVO.getId()); | 113 | this.validateTenantExists(updateReqVO.getId()); |
| 114 | + // 校验套餐被禁用 | ||
| 115 | + tenantPackageService.validTenantPackage(updateReqVO.getPackageId()); | ||
| 116 | + | ||
| 53 | // 更新 | 117 | // 更新 |
| 54 | TenantDO updateObj = TenantConvert.INSTANCE.convert(updateReqVO); | 118 | TenantDO updateObj = TenantConvert.INSTANCE.convert(updateReqVO); |
| 55 | tenantMapper.updateById(updateObj); | 119 | tenantMapper.updateById(updateObj); |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
| @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; | @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*; | ||
| 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; | 8 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 9 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; | 9 | import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; |
| 10 | 10 | ||
| 11 | +import javax.validation.Valid; | ||
| 11 | import java.io.InputStream; | 12 | import java.io.InputStream; |
| 12 | import java.util.*; | 13 | import java.util.*; |
| 13 | 14 | ||
| @@ -24,14 +25,14 @@ public interface AdminUserService { | @@ -24,14 +25,14 @@ public interface AdminUserService { | ||
| 24 | * @param reqVO 用户信息 | 25 | * @param reqVO 用户信息 |
| 25 | * @return 用户编号 | 26 | * @return 用户编号 |
| 26 | */ | 27 | */ |
| 27 | - Long createUser(UserCreateReqVO reqVO); | 28 | + Long createUser(@Valid UserCreateReqVO reqVO); |
| 28 | 29 | ||
| 29 | /** | 30 | /** |
| 30 | * 修改用户 | 31 | * 修改用户 |
| 31 | * | 32 | * |
| 32 | * @param reqVO 用户信息 | 33 | * @param reqVO 用户信息 |
| 33 | */ | 34 | */ |
| 34 | - void updateUser(UserUpdateReqVO reqVO); | 35 | + void updateUser(@Valid UserUpdateReqVO reqVO); |
| 35 | 36 | ||
| 36 | /** | 37 | /** |
| 37 | * 更新用户的最后登陆信息 | 38 | * 更新用户的最后登陆信息 |
| @@ -47,7 +48,7 @@ public interface AdminUserService { | @@ -47,7 +48,7 @@ public interface AdminUserService { | ||
| 47 | * @param id 用户编号 | 48 | * @param id 用户编号 |
| 48 | * @param reqVO 用户个人信息 | 49 | * @param reqVO 用户个人信息 |
| 49 | */ | 50 | */ |
| 50 | - void updateUserProfile(Long id, UserProfileUpdateReqVO reqVO); | 51 | + void updateUserProfile(Long id, @Valid UserProfileUpdateReqVO reqVO); |
| 51 | 52 | ||
| 52 | /** | 53 | /** |
| 53 | * 修改用户个人密码 | 54 | * 修改用户个人密码 |
| @@ -55,7 +56,7 @@ public interface AdminUserService { | @@ -55,7 +56,7 @@ public interface AdminUserService { | ||
| 55 | * @param id 用户编号 | 56 | * @param id 用户编号 |
| 56 | * @param reqVO 更新用户个人密码 | 57 | * @param reqVO 更新用户个人密码 |
| 57 | */ | 58 | */ |
| 58 | - void updateUserPassword(Long id, UserProfileUpdatePasswordReqVO reqVO); | 59 | + void updateUserPassword(Long id, @Valid UserProfileUpdatePasswordReqVO reqVO); |
| 59 | 60 | ||
| 60 | /** | 61 | /** |
| 61 | * 更新用户头像 | 62 | * 更新用户头像 |
yudao-module-system/yudao-module-system-impl/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
| @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.service.user; | @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.system.service.user; | ||
| 2 | 2 | ||
| 3 | import cn.hutool.core.collection.CollUtil; | 3 | import cn.hutool.core.collection.CollUtil; |
| 4 | import cn.hutool.core.io.IoUtil; | 4 | import cn.hutool.core.io.IoUtil; |
| 5 | -import cn.hutool.core.util.IdUtil; | ||
| 6 | import cn.hutool.core.util.StrUtil; | 5 | import cn.hutool.core.util.StrUtil; |
| 7 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | 6 | import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; |
| 8 | import cn.iocoder.yudao.framework.common.exception.ServiceException; | 7 | import cn.iocoder.yudao.framework.common.exception.ServiceException; |
| @@ -258,7 +257,7 @@ public class AdminUserServiceImpl implements AdminUserService { | @@ -258,7 +257,7 @@ public class AdminUserServiceImpl implements AdminUserService { | ||
| 258 | // 校验邮箱唯一 | 257 | // 校验邮箱唯一 |
| 259 | this.checkEmailUnique(id, email); | 258 | this.checkEmailUnique(id, email); |
| 260 | // 校验部门处于开启状态 | 259 | // 校验部门处于开启状态 |
| 261 | - deptService.validDepts(Collections.singleton(deptId)); | 260 | + deptService.validDepts(CollectionUtils.singleton(deptId)); |
| 262 | // 校验岗位处于开启状态 | 261 | // 校验岗位处于开启状态 |
| 263 | postService.validPosts(postIds); | 262 | postService.validPosts(postIds); |
| 264 | } | 263 | } |
yudao-module-system/yudao-module-system-impl/src/test/java/cn/iocoder/yudao/module/system/service/permission/RoleServiceTest.java
| @@ -72,10 +72,9 @@ public class RoleServiceTest extends BaseDbUnitTest { | @@ -72,10 +72,9 @@ public class RoleServiceTest extends BaseDbUnitTest { | ||
| 72 | o.setCode("role_code"); | 72 | o.setCode("role_code"); |
| 73 | o.setName("role_name"); | 73 | o.setName("role_name"); |
| 74 | o.setRemark("remark"); | 74 | o.setRemark("remark"); |
| 75 | - o.setType(RoleTypeEnum.CUSTOM.getType()); | ||
| 76 | o.setSort(1); | 75 | o.setSort(1); |
| 77 | }); | 76 | }); |
| 78 | - Long roleId = sysRoleService.createRole(reqVO); | 77 | + Long roleId = sysRoleService.createRole(reqVO, null); |
| 79 | 78 | ||
| 80 | //断言 | 79 | //断言 |
| 81 | assertNotNull(roleId); | 80 | assertNotNull(roleId); |
| @@ -96,7 +95,6 @@ public class RoleServiceTest extends BaseDbUnitTest { | @@ -96,7 +95,6 @@ public class RoleServiceTest extends BaseDbUnitTest { | ||
| 96 | o.setId(roleId); | 95 | o.setId(roleId); |
| 97 | o.setCode("role_code"); | 96 | o.setCode("role_code"); |
| 98 | o.setName("update_name"); | 97 | o.setName("update_name"); |
| 99 | - o.setType(RoleTypeEnum.SYSTEM.getType()); | ||
| 100 | o.setSort(999); | 98 | o.setSort(999); |
| 101 | }); | 99 | }); |
| 102 | sysRoleService.updateRole(reqVO); | 100 | sysRoleService.updateRole(reqVO); |
yudao-server/src/main/resources/application.yaml
| @@ -80,7 +80,7 @@ yudao: | @@ -80,7 +80,7 @@ yudao: | ||
| 80 | tenant: # 多租户相关配置项 | 80 | tenant: # 多租户相关配置项 |
| 81 | enable: true | 81 | enable: true |
| 82 | ignore-urls: /admin-api/system/captcha/get-image, /admin-api/infra/file/get/* | 82 | ignore-urls: /admin-api/system/captcha/get-image, /admin-api/infra/file/get/* |
| 83 | - ignore-tables: infra_config, infra_file, infra_job, infra_job_log, infra_job_log, system_tenant, system_tenant_package, system_dict_data, system_dict_type, system_error_code, system_menu, system_role, system_role_menu, system_sms_channel, tool_codegen_column, tool_codegen_table, tool_test_demo, tables, columns | 83 | + ignore-tables: infra_config, infra_file, infra_job, infra_job_log, infra_job_log, system_tenant, system_tenant_package, system_dict_data, system_dict_type, system_error_code, system_menu, system_sms_channel, tool_codegen_column, tool_codegen_table, tool_test_demo, tables, columns |
| 84 | sms-code: # 短信验证码相关的配置项 | 84 | sms-code: # 短信验证码相关的配置项 |
| 85 | expire-times: 10m | 85 | expire-times: 10m |
| 86 | send-frequency: 1m | 86 | send-frequency: 1m |
yudao-ui-admin/src/api/system/tenantPackage.js
| @@ -43,12 +43,10 @@ export function getTenantPackagePage(query) { | @@ -43,12 +43,10 @@ export function getTenantPackagePage(query) { | ||
| 43 | }) | 43 | }) |
| 44 | } | 44 | } |
| 45 | 45 | ||
| 46 | -// 导出租户套餐 Excel | ||
| 47 | -export function exportTenantPackageExcel(query) { | 46 | +// 获取租户套餐精简信息列表 |
| 47 | +export function getTenantPackageList() { | ||
| 48 | return request({ | 48 | return request({ |
| 49 | - url: '/system/tenant-package/export-excel', | ||
| 50 | - method: 'get', | ||
| 51 | - params: query, | ||
| 52 | - responseType: 'blob' | 49 | + url: '/system/tenant-package/get-simple-list', |
| 50 | + method: 'get' | ||
| 53 | }) | 51 | }) |
| 54 | } | 52 | } |
yudao-ui-admin/src/views/system/tenant/index.vue
| @@ -18,10 +18,6 @@ | @@ -18,10 +18,6 @@ | ||
| 18 | :key="dict.value" :label="dict.label" :value="dict.value"/> | 18 | :key="dict.value" :label="dict.label" :value="dict.value"/> |
| 19 | </el-select> | 19 | </el-select> |
| 20 | </el-form-item> | 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> | 21 | <el-form-item> |
| 26 | <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button> | 22 | <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> | 23 | <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button> |
| @@ -45,8 +41,24 @@ | @@ -45,8 +41,24 @@ | ||
| 45 | <el-table v-loading="loading" :data="list"> | 41 | <el-table v-loading="loading" :data="list"> |
| 46 | <el-table-column label="租户编号" align="center" prop="id" /> | 42 | <el-table-column label="租户编号" align="center" prop="id" /> |
| 47 | <el-table-column label="租户名" align="center" prop="name" /> | 43 | <el-table-column label="租户名" align="center" prop="name" /> |
| 44 | + <el-table-column label="租户套餐" align="center" prop="packageId"> | ||
| 45 | + <template slot-scope="scope"> | ||
| 46 | + <el-tag> {{getPackageName(scope.row.packageId)}} </el-tag> | ||
| 47 | + </template> | ||
| 48 | + </el-table-column> | ||
| 48 | <el-table-column label="联系人" align="center" prop="contactName" /> | 49 | <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="contactMobile" /> |
| 51 | + <el-table-column label="账号额度" align="center" prop="accountCount"> | ||
| 52 | + <template slot-scope="scope"> | ||
| 53 | + <el-tag> {{scope.row.accountCount}} </el-tag> | ||
| 54 | + </template> | ||
| 55 | + </el-table-column> | ||
| 56 | + <el-table-column label="过期时间" align="center" prop="expireTime" width="180"> | ||
| 57 | + <template slot-scope="scope"> | ||
| 58 | + <span>{{ parseTime(scope.row.expireTime) }}</span> | ||
| 59 | + </template> | ||
| 60 | + </el-table-column> | ||
| 61 | + <el-table-column label="绑定域名" align="center" prop="domain" width="180" /> | ||
| 50 | <el-table-column label="租户状态" align="center" prop="status"> | 62 | <el-table-column label="租户状态" align="center" prop="status"> |
| 51 | <template slot-scope="scope"> | 63 | <template slot-scope="scope"> |
| 52 | <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> | 64 | <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> |
| @@ -76,12 +88,33 @@ | @@ -76,12 +88,33 @@ | ||
| 76 | <el-form-item label="租户名" prop="name"> | 88 | <el-form-item label="租户名" prop="name"> |
| 77 | <el-input v-model="form.name" placeholder="请输入租户名" /> | 89 | <el-input v-model="form.name" placeholder="请输入租户名" /> |
| 78 | </el-form-item> | 90 | </el-form-item> |
| 91 | + <el-form-item label="租户套餐" prop="packageId"> | ||
| 92 | + <el-select v-model="form.packageId" placeholder="请选择租户套餐" clearable size="small"> | ||
| 93 | + <el-option v-for="item in packageList" :key="item.id" :label="item.name" :value="item.id"/> | ||
| 94 | + </el-select> | ||
| 95 | + </el-form-item> | ||
| 79 | <el-form-item label="联系人" prop="contactName"> | 96 | <el-form-item label="联系人" prop="contactName"> |
| 80 | <el-input v-model="form.contactName" placeholder="请输入联系人" /> | 97 | <el-input v-model="form.contactName" placeholder="请输入联系人" /> |
| 81 | </el-form-item> | 98 | </el-form-item> |
| 82 | <el-form-item label="联系手机" prop="contactMobile"> | 99 | <el-form-item label="联系手机" prop="contactMobile"> |
| 83 | <el-input v-model="form.contactMobile" placeholder="请输入联系手机" /> | 100 | <el-input v-model="form.contactMobile" placeholder="请输入联系手机" /> |
| 84 | </el-form-item> | 101 | </el-form-item> |
| 102 | + <el-form-item v-if="form.id === undefined" label="用户名称" prop="username"> | ||
| 103 | + <el-input v-model="form.username" placeholder="请输入用户名称" /> | ||
| 104 | + </el-form-item> | ||
| 105 | + <el-form-item v-if="form.id === undefined" label="用户密码" prop="password"> | ||
| 106 | + <el-input v-model="form.password" placeholder="请输入用户密码" type="password" show-password /> | ||
| 107 | + </el-form-item> | ||
| 108 | + <el-form-item label="账号额度" prop="accountCount"> | ||
| 109 | + <el-input-number v-model="form.accountCount" placeholder="请输入账号额度" controls-position="right" :min="0" /> | ||
| 110 | + </el-form-item> | ||
| 111 | + <el-form-item label="过期时间" prop="expireTime"> | ||
| 112 | + <el-date-picker clearable size="small" v-model="form.expireTime" type="date" | ||
| 113 | + value-format="timestamp" placeholder="请选择过期时间" /> | ||
| 114 | + </el-form-item> | ||
| 115 | + <el-form-item label="绑定域名" prop="domain"> | ||
| 116 | + <el-input v-model="form.domain" placeholder="请输入绑定域名" /> | ||
| 117 | + </el-form-item> | ||
| 85 | <el-form-item label="租户状态" prop="status"> | 118 | <el-form-item label="租户状态" prop="status"> |
| 86 | <el-radio-group v-model="form.status"> | 119 | <el-radio-group v-model="form.status"> |
| 87 | <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" | 120 | <el-radio v-for="dict in this.getDictDatas(DICT_TYPE.COMMON_STATUS)" |
| @@ -100,6 +133,7 @@ | @@ -100,6 +133,7 @@ | ||
| 100 | <script> | 133 | <script> |
| 101 | import { createTenant, updateTenant, deleteTenant, getTenant, getTenantPage, exportTenantExcel } from "@/api/system/tenant"; | 134 | import { createTenant, updateTenant, deleteTenant, getTenant, getTenantPage, exportTenantExcel } from "@/api/system/tenant"; |
| 102 | import { CommonStatusEnum } from '@/utils/constants' | 135 | import { CommonStatusEnum } from '@/utils/constants' |
| 136 | +import {getTenantPackageList} from "@/api/system/tenantPackage"; | ||
| 103 | 137 | ||
| 104 | export default { | 138 | export default { |
| 105 | name: "Tenant", | 139 | name: "Tenant", |
| @@ -117,6 +151,8 @@ export default { | @@ -117,6 +151,8 @@ export default { | ||
| 117 | total: 0, | 151 | total: 0, |
| 118 | // 租户列表 | 152 | // 租户列表 |
| 119 | list: [], | 153 | list: [], |
| 154 | + // 租户套餐列表 | ||
| 155 | + packageList: [], | ||
| 120 | // 弹出层标题 | 156 | // 弹出层标题 |
| 121 | title: "", | 157 | title: "", |
| 122 | // 是否显示弹出层 | 158 | // 是否显示弹出层 |
| @@ -136,13 +172,23 @@ export default { | @@ -136,13 +172,23 @@ export default { | ||
| 136 | // 表单校验 | 172 | // 表单校验 |
| 137 | rules: { | 173 | rules: { |
| 138 | name: [{ required: true, message: "租户名不能为空", trigger: "blur" }], | 174 | name: [{ required: true, message: "租户名不能为空", trigger: "blur" }], |
| 175 | + packageId: [{ required: true, message: "租户套餐不能为空", trigger: "blur" }], | ||
| 139 | contactName: [{ required: true, message: "联系人不能为空", trigger: "blur" }], | 176 | contactName: [{ required: true, message: "联系人不能为空", trigger: "blur" }], |
| 140 | - status: [{ required: true, message: "租户状态(0正常 1停用)不能为空", trigger: "blur" }], | 177 | + status: [{ required: true, message: "租户状态不能为空", trigger: "blur" }], |
| 178 | + accountCount: [{ required: true, message: "账号额度不能为空", trigger: "blur" }], | ||
| 179 | + expireTime: [{ required: true, message: "过期时间不能为空", trigger: "blur" }], | ||
| 180 | + domain: [{ required: true, message: "绑定域名不能为空", trigger: "blur" }], | ||
| 181 | + username: [{ required: true, message: "用户名称不能为空", trigger: "blur" }], | ||
| 182 | + password: [{ required: true, message: "用户密码不能为空", trigger: "blur" }], | ||
| 141 | } | 183 | } |
| 142 | }; | 184 | }; |
| 143 | }, | 185 | }, |
| 144 | created() { | 186 | created() { |
| 145 | this.getList(); | 187 | this.getList(); |
| 188 | + // 获得租户套餐列表 | ||
| 189 | + getTenantPackageList().then(response => { | ||
| 190 | + this.packageList = response.data; | ||
| 191 | + }) | ||
| 146 | }, | 192 | }, |
| 147 | methods: { | 193 | methods: { |
| 148 | /** 查询列表 */ | 194 | /** 查询列表 */ |
| @@ -168,8 +214,12 @@ export default { | @@ -168,8 +214,12 @@ export default { | ||
| 168 | this.form = { | 214 | this.form = { |
| 169 | id: undefined, | 215 | id: undefined, |
| 170 | name: undefined, | 216 | name: undefined, |
| 217 | + packageId: undefined, | ||
| 171 | contactName: undefined, | 218 | contactName: undefined, |
| 172 | contactMobile: undefined, | 219 | contactMobile: undefined, |
| 220 | + accountCount: undefined, | ||
| 221 | + expireTime: undefined, | ||
| 222 | + domain: undefined, | ||
| 173 | status: CommonStatusEnum.ENABLE, | 223 | status: CommonStatusEnum.ENABLE, |
| 174 | }; | 224 | }; |
| 175 | this.resetForm("form"); | 225 | this.resetForm("form"); |
| @@ -249,6 +299,15 @@ export default { | @@ -249,6 +299,15 @@ export default { | ||
| 249 | this.$download.excel(response, '租户.xls'); | 299 | this.$download.excel(response, '租户.xls'); |
| 250 | this.exportLoading = false; | 300 | this.exportLoading = false; |
| 251 | }).catch(() => {}); | 301 | }).catch(() => {}); |
| 302 | + }, | ||
| 303 | + /** 套餐名格式化 */ | ||
| 304 | + getPackageName(packageId) { | ||
| 305 | + for (const item of this.packageList) { | ||
| 306 | + if (item.id === packageId) { | ||
| 307 | + return item.name; | ||
| 308 | + } | ||
| 309 | + } | ||
| 310 | + return '未知套餐'; | ||
| 252 | } | 311 | } |
| 253 | } | 312 | } |
| 254 | }; | 313 | }; |
更新日志.md
| @@ -29,7 +29,8 @@ TODO | @@ -29,7 +29,8 @@ TODO | ||
| 29 | * 【新增】后端 `yudao.tenant.enable` 配置项,前端 `VUE_APP_TENANT_ENABLE` 配置项,用于开关租户功能。 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) | 29 | * 【新增】后端 `yudao.tenant.enable` 配置项,前端 `VUE_APP_TENANT_ENABLE` 配置项,用于开关租户功能。 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) |
| 30 | * 【优化】调整默认所有表开启多租户的特性,可通过 `yudao.tenant.ignore-tables` 配置项进行忽略,替代原本默认不开启的策略 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) | 30 | * 【优化】调整默认所有表开启多租户的特性,可通过 `yudao.tenant.ignore-tables` 配置项进行忽略,替代原本默认不开启的策略 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) |
| 31 | * 【新增】通过 `yudao.tenant.ignore-urls` 配置忽略多租户的请求,例如说 ,例如说短信回调、支付回调等 Open API [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) | 31 | * 【新增】通过 `yudao.tenant.ignore-urls` 配置忽略多租户的请求,例如说 ,例如说短信回调、支付回调等 Open API [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/79311ecc71f0c6beabe0e5f84e1423ce745a5f09) |
| 32 | -* 【新增】租户套餐的管理,可配置每个租户的可使用的功能 | 32 | +* 【新增】租户套餐的管理,可配置每个租户的可使用的功能权限 [commit](https://gitee.com/zhijiantianya/ruoyi-vue-pro/commit/6b6d676a6baa2dad16ae9bf03d5002209064c8cc) |
| 33 | +* 【优化】新建租户时,自动创建对应的管理员账号、角色等基础信息 []() | ||
| 33 | 34 | ||
| 34 | ### 🐞 Bug Fixes | 35 | ### 🐞 Bug Fixes |
| 35 | 36 |