From 4946f2f45f313ef8d2f12795577157b88ed29111 Mon Sep 17 00:00:00 2001 From: dataprince Date: Wed, 3 Jan 2024 17:17:27 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E2=80=9C=E7=A7=9F=E6=88=B7?= =?UTF-8?q?=E5=A5=97=E9=A4=90=E7=AE=A1=E7=90=86=E2=80=9D=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/SysTenantPackageController.java | 150 ++++++ .../ruoyi/system/domain/SysTenantPackage.java | 75 +++ .../system/domain/bo/SysTenantPackageBo.java | 51 ++ .../system/domain/vo/SysTenantPackageVo.java | 64 +++ .../system/mapper/SysTenantPackageMapper.java | 15 + .../service/ISysTenantPackageService.java | 62 +++ .../impl/SysTenantPackageServiceImpl.java | 190 ++++++++ .../service/impl/SysTenantServiceImpl.java | 455 ++++++++++++++++++ .../mapper/system/SysTenantPackageMapper.xml | 7 + 9 files changed, 1069 insertions(+) create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysTenantPackageController.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTenantPackage.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysTenantPackageBo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysTenantPackageVo.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTenantPackageMapper.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantPackageService.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantPackageServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java create mode 100644 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantPackageMapper.xml diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysTenantPackageController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysTenantPackageController.java new file mode 100644 index 0000000..817ad82 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/system/SysTenantPackageController.java @@ -0,0 +1,150 @@ +package com.ruoyi.system.controller.system; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; +import com.ruoyi.common.core.constant.TenantConstants; +import com.ruoyi.common.core.core.domain.R; +import com.ruoyi.common.excel.utils.ExcelUtil; +import com.ruoyi.common.web.annotation.RepeatSubmit; +import com.ruoyi.common.log.annotation.Log; +import com.ruoyi.common.log.enums.BusinessType; +import com.ruoyi.common.orm.core.page.TableDataInfo; +import com.ruoyi.common.web.core.BaseController; +import com.ruoyi.system.domain.bo.SysTenantPackageBo; +import com.ruoyi.system.domain.vo.SysTenantPackageVo; +import com.ruoyi.system.service.ISysTenantPackageService; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 租户套餐管理 + * + * @author Michelle.Chung + * author 数据小王子 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/system/tenant/package") +public class SysTenantPackageController extends BaseController +{ + @Resource + private ISysTenantPackageService tenantPackageService; + + /** + * 查询租户套餐列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:list") + @GetMapping("/list") + public TableDataInfo list(SysTenantPackageBo sysTenantPackageBo) { + return tenantPackageService.selectPage(sysTenantPackageBo); + } + + /** + * 查询租户套餐下拉选列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:list") + @GetMapping("/selectList") + public R> selectList() { + return R.ok(tenantPackageService.selectList()); + } + + /** + * 导出租户套餐列表 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:export") + @Log(title = "租户套餐", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(SysTenantPackageBo sysTenantPackageBo, HttpServletResponse response) { + List list = tenantPackageService.queryList(sysTenantPackageBo); + ExcelUtil.exportExcel(list, "租户套餐", SysTenantPackageVo.class, response); + } + + /** + * 获取租户套餐详细信息 + * + * @param packageId 主键 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:query") + @GetMapping("/{packageId}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long packageId) { + return R.ok(tenantPackageService.selectById(packageId)); + } + + /** + * 新增租户套餐 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:add") + @Log(title = "租户套餐", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated @RequestBody SysTenantPackageBo sysTenantPackageBo) { + boolean inserted = tenantPackageService.insert(sysTenantPackageBo); + if (!inserted) { + return R.fail("新增租户套餐记录失败!"); + } + return R.ok(); + } + + /** + * 修改租户套餐 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:edit") + @Log(title = "租户套餐", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated @RequestBody SysTenantPackageBo sysTenantPackageBo) { + Boolean updated = tenantPackageService.update(sysTenantPackageBo); + if (!updated) { + R.fail("修改租户套餐记录失败!"); + } + return R.ok(); + } + + /** + * 状态修改 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:edit") + @Log(title = "租户套餐", businessType = BusinessType.UPDATE) + @PutMapping("/changeStatus") + public R changeStatus(@RequestBody SysTenantPackageBo sysTenantPackageBo) { + Boolean updated = tenantPackageService.updatePackageStatus(sysTenantPackageBo); + if (!updated) { + R.fail("修改租户套餐记录状态失败!"); + } + return R.ok(); + } + + /** + * 删除租户套餐 + * + * @param packageIds 主键串 + */ + @SaCheckRole(TenantConstants.SUPER_ADMIN_ROLE_KEY) + @SaCheckPermission("system:tenantPackage:remove") + @Log(title = "租户套餐", businessType = BusinessType.DELETE) + @DeleteMapping("/{packageIds}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] packageIds) { + boolean deleted = tenantPackageService.deleteByIds(packageIds, true); + if (!deleted) { + R.fail("删除租户套餐记录失败!"); + } + return R.ok(); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTenantPackage.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTenantPackage.java new file mode 100644 index 0000000..2feec0d --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysTenantPackage.java @@ -0,0 +1,75 @@ +package com.ruoyi.system.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import com.mybatisflex.annotation.Id; +import com.mybatisflex.annotation.Table; +import lombok.Data; +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 租户套餐对象 sys_tenant_package + * + * @author Michelle.Chung + * @author 数据小王子 + */ +@Data +@Table("sys_tenant_package") +public class SysTenantPackage implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + @Id + private Long packageId; + /** + * 套餐名称 + */ + private String packageName; + /** + * 关联菜单id + */ + private String menuIds; + /** + * 备注 + */ + private String remark; + /** + * 菜单树选择项是否关联显示( 0:父子不互相关联显示 1:父子互相关联显示) + */ + private Boolean menuCheckStrictly; + /** + * 状态(0正常 1停用) + */ + private String status; + /** + * 删除标志(0代表存在 1代表删除) + */ + private Integer delFlag; + + /** + * 创建者 + */ + private Long createBy; + + /** + * 创建时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date createTime; + + /** + * 更新者 + */ + private Long updateBy; + + /** + * 更新时间 + */ + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date updateTime; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysTenantPackageBo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysTenantPackageBo.java new file mode 100644 index 0000000..c6e0096 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/bo/SysTenantPackageBo.java @@ -0,0 +1,51 @@ +package com.ruoyi.system.domain.bo; + +import com.ruoyi.system.domain.SysTenantPackage; +import io.github.linpeilie.annotations.AutoMapper; +import io.github.linpeilie.annotations.AutoMapping; +import lombok.Data; +import jakarta.validation.constraints.*; +import java.io.Serializable; + +/** + * 租户套餐业务对象 sys_tenant_package + * + * @author Michelle.Chung + */ + +@Data +@AutoMapper(target = SysTenantPackage.class, reverseConvertGenerate = false) +public class SysTenantPackageBo implements Serializable { + + /** + * 租户套餐id + */ + private Long packageId; + + /** + * 套餐名称 + */ + @NotBlank(message = "套餐名称不能为空") + private String packageName; + + /** + * 关联菜单id + */ + @AutoMapping(target = "menuIds", expression = "java(com.ruoyi.common.core.utils.StringUtils.join(source.getMenuIds(), \",\"))") + private Long[] menuIds; + + /** + * 备注 + */ + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + private String status; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysTenantPackageVo.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysTenantPackageVo.java new file mode 100644 index 0000000..a24615b --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/SysTenantPackageVo.java @@ -0,0 +1,64 @@ +package com.ruoyi.system.domain.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import com.ruoyi.common.excel.annotation.ExcelDictFormat; +import com.ruoyi.common.excel.convert.ExcelDictConvert; +import com.ruoyi.system.domain.SysTenantPackage; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 租户套餐视图对象 sys_tenant_package + * + * @author Michelle.Chung + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = SysTenantPackage.class) +public class SysTenantPackageVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 租户套餐id + */ + @ExcelProperty(value = "租户套餐id") + private Long packageId; + + /** + * 套餐名称 + */ + @ExcelProperty(value = "套餐名称") + private String packageName; + + /** + * 关联菜单id + */ + @ExcelProperty(value = "关联菜单id") + private String menuIds; + + /** + * 备注 + */ + @ExcelProperty(value = "备注") + private String remark; + + /** + * 菜单树选择项是否关联显示 + */ + @ExcelProperty(value = "菜单树选择项是否关联显示") + private Boolean menuCheckStrictly; + + /** + * 状态(0正常 1停用) + */ + @ExcelProperty(value = "状态", converter = ExcelDictConvert.class) + @ExcelDictFormat(readConverterExp = "0=正常,1=停用") + private String status; +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTenantPackageMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTenantPackageMapper.java new file mode 100644 index 0000000..beea414 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysTenantPackageMapper.java @@ -0,0 +1,15 @@ +package com.ruoyi.system.mapper; + +import com.mybatisflex.core.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import com.ruoyi.system.domain.SysTenantPackage; + +/** + * 租户套餐Mapper接口 + * + * @author 数据小王子 + */ +@Mapper +public interface SysTenantPackageMapper extends BaseMapper { + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantPackageService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantPackageService.java new file mode 100644 index 0000000..312edbf --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysTenantPackageService.java @@ -0,0 +1,62 @@ +package com.ruoyi.system.service; + +import com.ruoyi.common.orm.core.service.IBaseService; +import com.ruoyi.system.domain.SysTenantPackage; +import com.ruoyi.system.domain.vo.SysTenantPackageVo; +import com.ruoyi.system.domain.bo.SysTenantPackageBo; +import com.ruoyi.common.orm.core.page.TableDataInfo; +import com.ruoyi.common.orm.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 租户套餐Service接口 + * + * @author 数据小王子 + */ +public interface ISysTenantPackageService extends IBaseService { + + /** + * 查询租户套餐 + */ + SysTenantPackageVo selectById(Long packageId); + + /** + * 分页查询租户套餐 + * + * @param sysTenantPackageBo 租户套餐Bo + * @return 租户套餐集合 + */ + TableDataInfo selectPage(SysTenantPackageBo sysTenantPackageBo); + + /** + * 查询租户套餐下拉选列表 + */ + List selectList(); + + /** + * 查询租户套餐列表 + */ + List queryList(SysTenantPackageBo bo); + + /** + * 新增租户套餐 + */ + Boolean insert(SysTenantPackageBo sysTenantPackageBo); + + /** + * 修改租户套餐 + */ + Boolean update(SysTenantPackageBo sysTenantPackageBo); + + /** + * 修改套餐状态 + */ + Boolean updatePackageStatus(SysTenantPackageBo sysTenantPackageBo); + + /** + * 校验并批量删除租户套餐信息 + */ + Boolean deleteByIds(Long[] packageIds, Boolean isValid); +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantPackageServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantPackageServiceImpl.java new file mode 100644 index 0000000..951d930 --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantPackageServiceImpl.java @@ -0,0 +1,190 @@ +package com.ruoyi.system.service.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.util.UpdateEntity; +import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl; +import com.ruoyi.common.security.utils.LoginHelper; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import com.ruoyi.common.core.constant.TenantConstants; +import com.ruoyi.common.core.exception.ServiceException; +import com.ruoyi.common.core.utils.MapstructUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.orm.core.page.PageQuery; +import com.ruoyi.common.orm.core.page.TableDataInfo; +import com.ruoyi.system.domain.SysTenantPackage; +import com.ruoyi.system.domain.bo.SysTenantPackageBo; +import com.ruoyi.system.domain.vo.SysTenantPackageVo; +import com.ruoyi.system.mapper.SysTenantMapper; +import com.ruoyi.system.mapper.SysTenantPackageMapper; +import com.ruoyi.system.service.ISysTenantPackageService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +import static com.ruoyi.system.domain.table.SysTenantPackageTableDef.SYS_TENANT_PACKAGE; +import static com.ruoyi.system.domain.table.SysTenantTableDef.SYS_TENANT; + +/** + * 租户套餐Service业务层处理 + * + * @author 数据小王子 + */ +@RequiredArgsConstructor +@Service +public class SysTenantPackageServiceImpl extends BaseServiceImpl implements ISysTenantPackageService { + + @Resource + private SysTenantPackageMapper tenantPackageMapper; + @Resource + private SysTenantMapper tenantMapper; + + @Override + public QueryWrapper query() { + return super.query().from(SYS_TENANT_PACKAGE); + } + + private QueryWrapper buildQueryWrapper(SysTenantPackageBo bo) { + return super.buildBaseQueryWrapper() + .and(SYS_TENANT_PACKAGE.PACKAGE_NAME.like(bo.getPackageName())) + .and(SYS_TENANT_PACKAGE.STATUS.eq(bo.getStatus())) + .orderBy(SYS_TENANT_PACKAGE.PACKAGE_ID.desc()); + } + + /** + * 查询租户套餐 + */ + @Override + public SysTenantPackageVo selectById(Long packageId){ + return this.getOneAs(query().where(SYS_TENANT_PACKAGE.PACKAGE_ID.eq(packageId)), SysTenantPackageVo.class); + } + + /** + * 分页查询租户套餐 + * + * @param sysTenantPackageBo 租户套餐Bo + * @return 租户套餐集合 + */ + @Override + public TableDataInfo selectPage(SysTenantPackageBo sysTenantPackageBo) + { + QueryWrapper queryWrapper = buildQueryWrapper(sysTenantPackageBo); + Page page = this.pageAs(PageQuery.build(), queryWrapper, SysTenantPackageVo.class); + return TableDataInfo.build(page); + } + + /** + * 查询租户套餐下拉选列表 + */ + @Override + public List selectList() { + SysTenantPackageBo tenantPackageBo = new SysTenantPackageBo(); + tenantPackageBo.setStatus(TenantConstants.NORMAL); + QueryWrapper queryWrapper = buildQueryWrapper(tenantPackageBo); + return this.listAs(queryWrapper, SysTenantPackageVo.class); + } + + /** + * 查询租户套餐列表 + */ + @Override + public List queryList(SysTenantPackageBo sysTenantPackageBo) { + QueryWrapper queryWrapper = buildQueryWrapper(sysTenantPackageBo); + return this.listAs(queryWrapper, SysTenantPackageVo.class); + } + + /** + * 新增租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean insert(SysTenantPackageBo sysTenantPackageBo) { + SysTenantPackage sysTenantPackage = MapstructUtils.convert(sysTenantPackageBo, SysTenantPackage.class); + if(ObjectUtil.isNull(sysTenantPackage)){ + return true; + } + // 保存菜单id + List menuIds = Arrays.asList(sysTenantPackageBo.getMenuIds()); + if (CollUtil.isNotEmpty(menuIds)) { + sysTenantPackage.setMenuIds(StringUtils.join(menuIds, ", ")); + } else { + sysTenantPackage.setMenuIds(""); + } + + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + sysTenantPackage.setCreateBy(loginUserId); + sysTenantPackage.setCreateTime(createTime); + sysTenantPackage.setUpdateBy(loginUserId); + sysTenantPackage.setUpdateTime(createTime); + + return this.save(sysTenantPackage); + } + + /** + * 修改租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean update(SysTenantPackageBo sysTenantPackageBo) { + SysTenantPackage sysTenantPackage = MapstructUtils.convert(sysTenantPackageBo, SysTenantPackage.class); + if(ObjectUtil.isNull(sysTenantPackage)){ + return true; + } + // 保存菜单id + List menuIds = Arrays.asList(sysTenantPackageBo.getMenuIds()); + if (CollUtil.isNotEmpty(menuIds)) { + sysTenantPackage.setMenuIds(StringUtils.join(menuIds, ", ")); + } else { + sysTenantPackage.setMenuIds(""); + } + + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + sysTenantPackage.setUpdateBy(loginUserId); + sysTenantPackage.setUpdateTime(createTime); + + return this.updateById(sysTenantPackage); + } + + /** + * 修改套餐状态 + * + * @param sysTenantPackageBo 套餐信息 + * @return 结果 + */ + @Override + public Boolean updatePackageStatus(SysTenantPackageBo sysTenantPackageBo) { + SysTenantPackage sysTenantPackage = UpdateEntity.of(SysTenantPackage.class, sysTenantPackageBo.getPackageId()); + + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + sysTenantPackage.setUpdateBy(loginUserId); + sysTenantPackage.setUpdateTime(createTime); + + sysTenantPackage.setStatus(sysTenantPackageBo.getStatus()); + return tenantPackageMapper.update(sysTenantPackage) > 0; + } + + /** + * 批量删除租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean deleteByIds(Long[] packageIds, Boolean isValid) { + if(isValid){ + boolean exists = tenantMapper.selectCountByQuery(query().where(SYS_TENANT.PACKAGE_ID.in(List.of(packageIds)))) >0; + if (exists) { + throw new ServiceException("租户套餐已被使用"); + } + } + return this.removeByIds(Arrays.asList(packageIds)); + } + +} diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java new file mode 100644 index 0000000..a2f992a --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysTenantServiceImpl.java @@ -0,0 +1,455 @@ +package com.ruoyi.system.service.impl; + +import cn.dev33.satoken.secure.BCrypt; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.mybatisflex.core.paginate.Page; +import com.mybatisflex.core.query.QueryWrapper; +import com.mybatisflex.core.util.UpdateEntity; +import com.ruoyi.common.orm.core.service.impl.BaseServiceImpl; +import com.ruoyi.common.security.utils.LoginHelper; +import com.ruoyi.system.domain.vo.SysTenantPackageVo; +import com.ruoyi.system.service.ISysRoleService; +import com.ruoyi.system.service.ISysTenantPackageService; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import com.ruoyi.common.core.constant.CacheNames; +import com.ruoyi.common.core.constant.Constants; +import com.ruoyi.common.core.constant.TenantConstants; +import com.ruoyi.common.core.exception.ServiceException; +import com.ruoyi.common.core.utils.MapstructUtils; +import com.ruoyi.common.core.utils.SpringUtils; +import com.ruoyi.common.core.utils.StringUtils; +import com.ruoyi.common.orm.core.page.PageQuery; +import com.ruoyi.common.orm.core.page.TableDataInfo; +import com.ruoyi.common.tenant.helper.TenantHelper; +import com.ruoyi.system.domain.*; +import com.ruoyi.system.domain.bo.SysTenantBo; +import com.ruoyi.system.domain.vo.SysTenantVo; +import com.ruoyi.system.mapper.*; +import com.ruoyi.system.service.ISysTenantService; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.List; + +import static com.ruoyi.system.domain.table.SysConfigTableDef.SYS_CONFIG; +import static com.ruoyi.system.domain.table.SysDictDataTableDef.SYS_DICT_DATA; +import static com.ruoyi.system.domain.table.SysDictTypeTableDef.SYS_DICT_TYPE; +import static com.ruoyi.system.domain.table.SysOssConfigTableDef.SYS_OSS_CONFIG; +import static com.ruoyi.system.domain.table.SysRoleMenuTableDef.SYS_ROLE_MENU; +import static com.ruoyi.system.domain.table.SysRoleTableDef.SYS_ROLE; +import static com.ruoyi.system.domain.table.SysTenantTableDef.SYS_TENANT; +import static com.ruoyi.system.domain.table.SysUserTableDef.SYS_USER; + +/** + * 租户Service业务层处理 + * + * @author Michelle.Chung + * author 数据小王子 + */ +@RequiredArgsConstructor +@Service +public class SysTenantServiceImpl extends BaseServiceImpl implements ISysTenantService { + + @Resource + private SysTenantMapper tenantMapper; + @Resource + private SysTenantPackageMapper tenantPackageMapper; + @Resource + private ISysTenantPackageService tenantPackageService; + @Resource + private SysUserMapper userMapper; + @Resource + private SysDeptMapper deptMapper; + @Resource + private SysRoleMapper roleMapper; + @Resource + private ISysRoleService roleService; + @Resource + private SysRoleMenuMapper roleMenuMapper; + @Resource + private SysRoleDeptMapper roleDeptMapper; + @Resource + private SysUserRoleMapper userRoleMapper; + @Resource + private SysDictTypeMapper dictTypeMapper; + @Resource + private SysDictDataMapper dictDataMapper; + @Resource + private SysConfigMapper configMapper; + @Resource + private SysOssConfigMapper ossConfigMapper; + + public QueryWrapper query() { + return super.query().from(SYS_TENANT); + } + + private QueryWrapper buildQueryWrapper(SysTenantBo sysTenantBo) { + return super.buildBaseQueryWrapper() + .and(SYS_TENANT.CONTACT_USER_NAME.like(sysTenantBo.getContactUserName())) + .and(SYS_TENANT.CONTACT_PHONE.eq(sysTenantBo.getContactPhone())) + .and(SYS_TENANT.COMPANY_NAME.like(sysTenantBo.getCompanyName())) + .and(SYS_TENANT.LICENSE_NUMBER.eq(sysTenantBo.getLicenseNumber())) + .and(SYS_TENANT.ADDRESS.eq(sysTenantBo.getAddress())) + .and(SYS_TENANT.INTRO.eq(sysTenantBo.getIntro())) + .and(SYS_TENANT.DOMAIN.like(sysTenantBo.getDomain())) + .and(SYS_TENANT.PACKAGE_ID.eq(sysTenantBo.getPackageId())) + .and(SYS_TENANT.EXPIRE_TIME.eq(sysTenantBo.getExpireTime())) + .and(SYS_TENANT.ACCOUNT_COUNT.eq(sysTenantBo.getAccountCount())) + .and(SYS_TENANT.STATUS.eq(sysTenantBo.getStatus())) + .orderBy(SYS_TENANT.TENANT_ID.desc()); + } + + /** + * 分页查询租户列表 + * + * @param sysTenantBo 租户Bo + * @return 租户列表集合 + */ + public TableDataInfo selectPage(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> { + QueryWrapper queryWrapper = buildQueryWrapper(sysTenantBo); + Page page = this.pageAs(PageQuery.build(), queryWrapper, SysTenantVo.class); + return TableDataInfo.build(page); + }); + } + + /** + * 查询租户列表 + */ + @Override + public List selectList(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> { + QueryWrapper queryWrapper = buildQueryWrapper(sysTenantBo); + return this.listAs(queryWrapper, SysTenantVo.class); + }); + } + + /** + * 基于租户ID查询租户 + */ + @Cacheable(cacheNames = CacheNames.SYS_TENANT, key = "#tenantId") + @Override + public SysTenantVo selectById(Long tenantId) { + return TenantHelper.ignore(() -> this.getOneAs(query().where(SYS_TENANT.TENANT_ID.eq(tenantId)), SysTenantVo.class)); + } + + /** + * 新增租户 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean insert(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> { + SysTenant sysTenant = MapstructUtils.convert(sysTenantBo, SysTenant.class); + if (ObjectUtil.isNull(sysTenant)) { + throw new ServiceException("新增租户参数为空"); + } + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + sysTenant.setCreateBy(loginUserId); + sysTenant.setCreateTime(createTime); + sysTenant.setUpdateBy(loginUserId); + sysTenant.setUpdateTime(createTime); + boolean inserted = this.save(sysTenant); + if (!inserted) { + throw new ServiceException("新增租户失败"); + } + Long tenantId = sysTenant.getTenantId(); + + + // 根据套餐创建角色 + Long roleId = createTenantRole(tenantId, sysTenantBo.getPackageId()); + + // 创建部门: 公司名是部门名称 + SysDept dept = new SysDept(); + dept.setTenantId(tenantId); + dept.setDeptName(sysTenantBo.getCompanyName()); + dept.setParentId(Constants.TOP_PARENT_ID); + dept.setAncestors(Constants.TOP_PARENT_ID.toString()); + dept.setDelFlag(0);//0 代表存在 + int insertedDeptRows = deptMapper.insert(dept, true); + if (insertedDeptRows != 1) { + throw new ServiceException("新增租户的部门记录失败"); + } + Long deptId = dept.getDeptId(); + + // 角色和部门关联表 + SysRoleDept roleDept = new SysRoleDept(); + roleDept.setRoleId(roleId); + roleDept.setDeptId(deptId); + int insertedRoleDept = roleDeptMapper.insertWithPk(roleDept); + if (insertedRoleDept != 1) { + throw new ServiceException("新增租户的角色部门记录失败"); + } + + // 新增系统用户 + SysUser user = new SysUser(); + user.setTenantId(tenantId); + user.setUserName(sysTenantBo.getUsername()); + user.setNickName(sysTenantBo.getUsername()); + user.setPassword(BCrypt.hashpw(sysTenantBo.getPassword())); + user.setDeptId(deptId); + user.setDelFlag(0); + user.setStatus("0"); + user.setUserType("sys_user");//sys_user是系统用户 + int insertedUser = userMapper.insert(user, true); + if (insertedUser != 1) { + throw new ServiceException("新增租户的用户记录失败"); + } + + // 用户和角色关联表 + SysUserRole userRole = new SysUserRole(); + userRole.setUserId(user.getUserId()); + userRole.setRoleId(roleId); + int insertedUserRole = userRoleMapper.insertWithPk(userRole); + if (insertedUserRole != 1) { + throw new ServiceException("新增租户的用户角色记录失败"); + } + + // 增加字典记录 + Long defaultTenantId = TenantConstants.DEFAULT_TENANT_ID; + List dictTypeList = dictTypeMapper.selectListByQuery(QueryWrapper.create().from(SYS_DICT_TYPE) + .where(SYS_DICT_TYPE.TENANT_ID.eq(defaultTenantId))); + List dictDataList = dictDataMapper.selectListByQuery( + QueryWrapper.create().from(SYS_DICT_DATA) + .where(SYS_DICT_DATA.TENANT_ID.eq(defaultTenantId))); + for (SysDictType dictType : dictTypeList) { + dictType.setDictId(null); + dictType.setTenantId(tenantId); + } + for (SysDictData dictData : dictDataList) { + dictData.setDictCode(null); + dictData.setTenantId(tenantId); + } + dictTypeMapper.insertBatch(dictTypeList); + dictDataMapper.insertBatch(dictDataList); + + // 增加参数配置记录 + List sysConfigList = configMapper.selectListByQuery( + QueryWrapper.create().from(SYS_CONFIG).where(SYS_CONFIG.TENANT_ID.eq(defaultTenantId))); + for (SysConfig config : sysConfigList) { + config.setConfigId(null); + config.setTenantId(tenantId); + } + configMapper.insertBatch(sysConfigList); + + //增加SysOssConfig记录 + List sysOssConfigList = ossConfigMapper.selectListByQuery( + QueryWrapper.create().from(SYS_OSS_CONFIG).where(SYS_OSS_CONFIG.TENANT_ID.eq(defaultTenantId))); + for (SysOssConfig ossConfig : sysOssConfigList) { + ossConfig.setOssConfigId(null); + ossConfig.setTenantId(tenantId); + } + ossConfigMapper.insertBatch(sysOssConfigList); + + return true; + }); + + } + + /** + * 根据租户菜单创建租户角色 + * + * @param tenantId 租户编号 + * @param packageId 租户套餐id + * @return 角色id + */ + private Long createTenantRole(Long tenantId, Long packageId) { + // 获取租户套餐 + SysTenantPackageVo tenantPackageVo = tenantPackageService.selectById(packageId); + if (ObjectUtil.isNull(tenantPackageVo)) { + throw new ServiceException("套餐不存在"); + } + // 获取套餐菜单id + List menuIds = StringUtils.splitTo(tenantPackageVo.getMenuIds(), Convert::toLong); + + // 创建角色 + SysRole role = new SysRole(); + role.setTenantId(tenantId); + role.setRoleName(TenantConstants.TENANT_ADMIN_ROLE_NAME); + role.setRoleKey(TenantConstants.TENANT_ADMIN_ROLE_KEY); + role.setRoleSort(1); + role.setStatus(TenantConstants.NORMAL); + role.setDelFlag(0); + role.setDataScope("1");//默认1:全部数据权限 + int insertedRows = roleMapper.insert(role, true); + if (insertedRows != 1) { + throw new ServiceException("添加租户管理员角色记录失败!"); + } + Long roleId = role.getRoleId(); + role.setMenuIds(menuIds.toArray(new Long[menuIds.size()])); + //新增角色菜单记录 + boolean insertedRoleMenu = roleService.insertRoleMenu(role); + if (!insertedRoleMenu) { + throw new ServiceException("添加租户管理员的角色菜单记录失败!"); + } + + return roleId; + } + + /** + * 修改租户 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#sysTenantBo.tenantId") + @Override + @Transactional(rollbackFor = Exception.class) + public boolean update(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> { + SysTenant tenant = MapstructUtils.convert(sysTenantBo, SysTenant.class); + if (ObjectUtil.isNull(tenant)) { + throw new ServiceException("租户的参数为空!"); + } + + //如果更换了套餐,则需要同步套餐sys_role_menu表 + SysTenantVo oldTenantVo = selectById(tenant.getTenantId()); + if (!oldTenantVo.getPackageId().equals(tenant.getPackageId())) { + boolean synced = syncTenantPackage(tenant.getTenantId(), tenant.getPackageId()); + if (!synced) { + throw new ServiceException("同步套餐失败!"); + } + } + + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + tenant.setUpdateBy(loginUserId); + tenant.setUpdateTime(createTime); + + return tenantMapper.update(tenant) > 0; + }); + } + + /** + * 修改租户状态 + * + * @param sysTenantBo 租户信息 + * @return 结果 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, key = "#sysTenantBo.tenantId") + @Override + public boolean updateTenantStatus(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> { + SysTenant sysTenant = UpdateEntity.of(SysTenant.class, sysTenantBo.getTenantId()); + + Long loginUserId = LoginHelper.getUserId(); + Date createTime = new Date(); + sysTenant.setUpdateBy(loginUserId); + sysTenant.setUpdateTime(createTime); + + sysTenant.setStatus(sysTenantBo.getStatus()); + + return tenantMapper.update(sysTenant) > 0; + }); + } + + /** + * 校验租户是否允许操作 + * + * @param tenantId 租户ID + */ + @Override + public void checkTenantAllowed(Long tenantId) { + if (ObjectUtil.isNotNull(tenantId) && TenantConstants.DEFAULT_TENANT_ID.equals(tenantId)) { + throw new ServiceException("不允许操作超级管理员租户"); + } + } + + /** + * 批量删除租户 + */ + @CacheEvict(cacheNames = CacheNames.SYS_TENANT, allEntries = true) + @Override + public boolean deleteByIds(Collection tenantIds, Boolean isValid) { + if (isValid) { + // 做一些业务上的校验,判断是否需要校验 + if (tenantIds.contains(TenantConstants.SUPER_ADMIN_ID)) { + throw new ServiceException("超级管理员租户不能删除"); + } + } + return TenantHelper.ignore(() -> this.removeByIds(tenantIds));//逻辑删除 + } + + /** + * 校验企业名称是否唯一 + */ + @Override + public boolean checkCompanyNameUnique(SysTenantBo sysTenantBo) { + return TenantHelper.ignore(() -> tenantMapper.selectCountByQuery( + query().where(SYS_TENANT.COMPANY_NAME.eq(sysTenantBo.getCompanyName())))) == 0; + } + + /** + * 校验账号余额 + */ + @Override + public boolean checkAccountBalance(Long tenantId) { + SysTenantVo tenant = SpringUtils.getAopProxy(this).selectById(tenantId); + // 如果余额为-1则代表不限制 + if (tenant.getAccountCount() == -1) { + return true; + } + Long userNumber = TenantHelper.ignore(() -> userMapper.selectCountByQuery(QueryWrapper.create().from(SYS_USER).where(SYS_USER.TENANT_ID.eq(tenantId)))); + // 如果余额大于0则代表还有可用名额 + return tenant.getAccountCount() - userNumber > 0; + } + + /** + * 校验有效期 + */ + @Override + public boolean checkExpireTime(Long tenantId) { + SysTenantVo tenant = SpringUtils.getAopProxy(this).selectById(tenantId); + // 如果未设置过期时间代表不限制 + if (ObjectUtil.isNull(tenant.getExpireTime())) { + return true; + } + // 如果当前时间在过期时间之前则通过 + return new Date().before(tenant.getExpireTime()); + } + + /** + * 同步租户套餐 + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean syncTenantPackage(Long tenantId, Long packageId) { + return TenantHelper.ignore(() -> { + SysTenantPackage tenantPackage = tenantPackageMapper.selectOneById(packageId); + List roles = TenantHelper.ignore(() -> roleMapper.selectListByQuery( + QueryWrapper.create().from(SYS_ROLE).where(SYS_ROLE.TENANT_ID.eq(tenantId)))); + List roleIds = new ArrayList<>(roles.size() - 1); + List menuIds = StringUtils.splitTo(tenantPackage.getMenuIds(), Convert::toLong); + roles.forEach(role -> { + if (TenantConstants.TENANT_ADMIN_ROLE_KEY.equals(role.getRoleKey())) { + int deletedRoleMenu = roleMenuMapper.deleteByQuery(QueryWrapper.create().from(SYS_ROLE_MENU).where(SYS_ROLE_MENU.ROLE_ID.eq(role.getRoleId()))); + if (deletedRoleMenu == 0) { + throw new ServiceException("删除租户的角色菜单记录失败!"); + } + + role.setMenuIds(menuIds.toArray(new Long[menuIds.size()])); + boolean insertedRoleMenu = roleService.insertRoleMenu(role); + if (!insertedRoleMenu) { + throw new ServiceException("添加租户管理员的角色菜单记录失败!"); + } + } else { + roleIds.add(role.getRoleId()); + } + }); + if (!roleIds.isEmpty()) { + int deletedRows = roleMenuMapper.deleteByQuery( + QueryWrapper.create().from(SYS_ROLE_MENU).where(SYS_ROLE_MENU.ROLE_ID.in(roleIds)).and(SYS_ROLE_MENU.MENU_ID.notIn(menuIds))); + if (deletedRows == 0) { + throw new ServiceException("删除租户的无用角色菜单记录失败!"); + } + } + return true; + } + ); + } +} diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantPackageMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantPackageMapper.xml new file mode 100644 index 0000000..23b46df --- /dev/null +++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysTenantPackageMapper.xml @@ -0,0 +1,7 @@ + + + + +