/* * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * Neither the name of the dreamlu.net developer nor the names of its * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * Author: Chill 庄骞 (smallchill@163.com) */ package org.springblade.system.service.impl; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.core.toolkit.IdWorker; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.AllArgsConstructor; import org.springblade.core.cache.utils.CacheUtil; import org.springblade.core.log.exception.ServiceException; import org.springblade.core.mp.base.BaseServiceImpl; import org.springblade.core.tenant.TenantId; import org.springblade.core.tool.api.R; import org.springblade.core.tool.constant.BladeConstant; import org.springblade.core.tool.jackson.JsonUtil; import org.springblade.core.tool.support.Kv; import org.springblade.core.tool.utils.DesUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.StringUtil; import org.springblade.system.cache.ParamCache; import org.springblade.system.entity.*; import org.springblade.system.mapper.TenantMapper; import org.springblade.system.service.*; import org.springblade.system.user.entity.User; import org.springblade.system.user.enums.UserEnum; import org.springblade.system.user.feign.IUserClient; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.Date; import java.util.LinkedList; import java.util.List; import java.util.stream.Collectors; import static org.springblade.common.constant.TenantConstant.*; import static org.springblade.core.cache.constant.CacheConstant.SYS_CACHE; /** * 服务实现类 * * @author Chill */ @Service @AllArgsConstructor public class TenantServiceImpl extends BaseServiceImpl implements ITenantService { private final TenantId tenantId; private final IRoleService roleService; private final IMenuService menuService; private final IDeptService deptService; private final IPostService postService; private final IRoleMenuService roleMenuService; private final IDictBizService dictBizService; private final IUserClient userClient; @Override public IPage selectTenantPage(IPage page, Tenant tenant) { return page.setRecords(baseMapper.selectTenantPage(page, tenant)); } @Override public Tenant getByTenantId(String tenantId) { return getOne(Wrappers.query().lambda().eq(Tenant::getTenantId, tenantId)); } @Override @Transactional(rollbackFor = Exception.class) public boolean submitTenant(Tenant tenant) { if (Func.isEmpty(tenant.getId())) { List tenants = baseMapper.selectList(Wrappers.query().lambda().eq(Tenant::getIsDeleted, BladeConstant.DB_NOT_DELETED)); List codes = tenants.stream().map(Tenant::getTenantId).collect(Collectors.toList()); String tenantId = getTenantId(codes); tenant.setTenantId(tenantId); // 获取参数配置的账号额度 int accountNumber = Func.toInt(ParamCache.getValue(ACCOUNT_NUMBER_KEY), DEFAULT_ACCOUNT_NUMBER); tenant.setAccountNumber(accountNumber); // 新建租户对应的默认角色 Role role = new Role(); role.setTenantId(tenantId); role.setParentId(BladeConstant.TOP_PARENT_ID); role.setRoleName("管理员"); role.setRoleAlias("admin"); role.setSort(2); role.setIsDeleted(BladeConstant.DB_NOT_DELETED); roleService.save(role); // 新建租户对应的角色菜单权限 LinkedList userMenus = new LinkedList<>(); // 获取参数配置的默认菜单集合,逗号隔开 List menuCodes = Func.toStrList(ParamCache.getValue(ACCOUNT_MENU_CODE_KEY)); List menus = getMenus((menuCodes.size() > 0 ? menuCodes : MENU_CODES), userMenus); List roleMenus = new ArrayList<>(); menus.forEach(menu -> { RoleMenu roleMenu = new RoleMenu(); roleMenu.setMenuId(menu.getId()); roleMenu.setRoleId(role.getId()); roleMenus.add(roleMenu); }); roleMenuService.saveBatch(roleMenus); // 新建租户对应的默认部门 Dept dept = new Dept(); dept.setTenantId(tenantId); dept.setParentId(BladeConstant.TOP_PARENT_ID); dept.setAncestors(String.valueOf(BladeConstant.TOP_PARENT_ID)); dept.setDeptName(tenant.getTenantName()); dept.setFullName(tenant.getTenantName()); dept.setDeptCategory(1); dept.setSort(2); dept.setIsDeleted(BladeConstant.DB_NOT_DELETED); deptService.save(dept); // 新建租户对应的默认岗位 Post post = new Post(); post.setTenantId(tenantId); post.setCategory(1); post.setPostCode("ceo"); post.setPostName("首席执行官"); post.setSort(1); postService.save(post); // 新建租户对应的默认业务字典 LinkedList dictBizs = new LinkedList<>(); List dictBizList = getDictBizs(tenantId, dictBizs); dictBizService.saveBatch(dictBizList); // 新建租户对应的默认管理用户 User user = new User(); user.setTenantId(tenantId); user.setName("admin"); user.setRealName("admin"); user.setAccount("admin"); // 获取参数配置的密码 String password = Func.toStr(ParamCache.getValue(PASSWORD_KEY), DEFAULT_PASSWORD); user.setPassword(password); user.setRoleId(String.valueOf(role.getId())); user.setDeptId(String.valueOf(dept.getId())); user.setPostId(String.valueOf(post.getId())); user.setBirthday(new Date()); user.setSex(1); user.setUserType(UserEnum.WEB.getCategory()); user.setIsDeleted(BladeConstant.DB_NOT_DELETED); boolean temp = super.saveOrUpdate(tenant); R result = userClient.saveUser(user); if (!result.isSuccess()) { throw new ServiceException(result.getMsg()); } return temp; } else { CacheUtil.clear(SYS_CACHE, tenant.getTenantId()); return super.saveOrUpdate(tenant); } } @Override @Transactional(rollbackFor = Exception.class) public boolean removeTenant(List ids) { List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids)) .stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList()); CacheUtil.clear(SYS_CACHE, tenantIds); if (tenantIds.contains(BladeConstant.ADMIN_TENANT_ID)) { throw new ServiceException("不可删除管理租户!"); } boolean tenantTemp = this.deleteLogic(ids); R result = userClient.removeUser(StringUtil.join(tenantIds)); if (!result.isSuccess()) { throw new ServiceException(result.getMsg()); } return tenantTemp; } @Override public boolean setting(Integer accountNumber, Date expireTime, String ids) { List tenantIds = this.list(Wrappers.query().lambda().in(Tenant::getId, ids)) .stream().map(tenant -> Func.toStr(tenant.getTenantId())).distinct().collect(Collectors.toList()); CacheUtil.clear(SYS_CACHE, tenantIds); Func.toLongList(ids).forEach(id -> { Kv kv = Kv.create().set("accountNumber", accountNumber).set("expireTime", expireTime).set("id", id); String licenseKey = DesUtil.encryptToHex(JsonUtil.toJson(kv), DES_KEY); update( Wrappers.update().lambda() .set(Tenant::getAccountNumber, accountNumber) .set(Tenant::getExpireTime, expireTime) .set(Tenant::getLicenseKey, licenseKey) .eq(Tenant::getId, id) ); }); return true; } private String getTenantId(List codes) { String code = tenantId.generate(); if (codes.contains(code)) { return getTenantId(codes); } return code; } private List getMenus(List codes, LinkedList menus) { codes.forEach(code -> { Menu menu = menuService.getOne(Wrappers.query().lambda().eq(Menu::getCode, code).eq(Menu::getIsDeleted, BladeConstant.DB_NOT_DELETED)); if (menu != null) { menus.add(menu); recursionMenu(menu.getId(), menus); } }); return menus; } private void recursionMenu(Long parentId, LinkedList menus) { List menuList = menuService.list(Wrappers.query().lambda().eq(Menu::getParentId, parentId).eq(Menu::getIsDeleted, BladeConstant.DB_NOT_DELETED)); menus.addAll(menuList); menuList.forEach(menu -> recursionMenu(menu.getId(), menus)); } private List getDictBizs(String tenantId, LinkedList dictBizs) { List dictBizList = dictBizService.list(Wrappers.query().lambda().eq(DictBiz::getParentId, BladeConstant.TOP_PARENT_ID).eq(DictBiz::getIsDeleted, BladeConstant.DB_NOT_DELETED)); dictBizList.forEach(dictBiz -> { Long oldParentId = dictBiz.getId(); Long newParentId = IdWorker.getId(); dictBiz.setId(newParentId); dictBiz.setTenantId(tenantId); dictBizs.add(dictBiz); recursionDictBiz(tenantId, oldParentId, newParentId, dictBizs); }); return dictBizs; } private void recursionDictBiz(String tenantId, Long oldParentId, Long newParentId, LinkedList dictBizs) { List dictBizList = dictBizService.list(Wrappers.query().lambda().eq(DictBiz::getParentId, oldParentId).eq(DictBiz::getIsDeleted, BladeConstant.DB_NOT_DELETED)); dictBizList.forEach(dictBiz -> { Long oldSubParentId = dictBiz.getId(); Long newSubParentId = IdWorker.getId(); dictBiz.setId(newSubParentId); dictBiz.setTenantId(tenantId); dictBiz.setParentId(newParentId); dictBizs.add(dictBiz); recursionDictBiz(tenantId, oldSubParentId, newSubParentId, dictBizs); }); } }