dengzedong
2024-10-14 558ffc4bcaf7aa5c683e7c9ce01e971feb9e4d95
iailab-module-system/iailab-module-system-biz/src/main/java/com/iailab/module/system/service/app/AppServiceImpl.java
@@ -1,15 +1,40 @@
package com.iailab.module.system.service.app;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.iailab.framework.common.pojo.PageResult;
import com.iailab.framework.common.util.object.BeanUtils;
import com.iailab.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.iailab.framework.security.core.util.SecurityFrameworkUtils;
import com.iailab.framework.tenant.core.aop.TenantIgnore;
import com.iailab.module.system.controller.admin.app.vo.AppPageReqVO;
import com.iailab.module.system.controller.admin.app.vo.AppSaveReqVO;
import com.iailab.module.system.dal.dataobject.app.AppDO;
import com.iailab.module.system.dal.dataobject.permission.MenuDO;
import com.iailab.module.system.dal.dataobject.permission.RoleDO;
import com.iailab.module.system.dal.dataobject.permission.RoleMenuDO;
import com.iailab.module.system.dal.dataobject.tenant.TenantDO;
import com.iailab.module.system.dal.dataobject.tenant.TenantPackageDO;
import com.iailab.module.system.dal.mysql.app.AppMapper;
import com.iailab.module.system.dal.mysql.permission.MenuMapper;
import com.iailab.module.system.dal.mysql.permission.RoleMapper;
import com.iailab.module.system.dal.mysql.permission.RoleMenuMapper;
import com.iailab.module.system.dal.mysql.tenant.TenantMapper;
import com.iailab.module.system.dal.mysql.tenant.TenantPackageMapper;
import com.iailab.module.system.enums.permission.MenuTypeEnum;
import com.iailab.module.system.service.permission.PermissionService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.*;
import static com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.iailab.framework.tenant.core.context.TenantContextHolder.getTenantId;
import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_EXISTS_CHILDREN;
import static com.iailab.module.system.enums.ErrorCodeConstants.MENU_NOT_EXISTS;
/**
 * @author PanZhibao
@@ -23,23 +48,54 @@
    @Resource
    private AppMapper appMapper;
    @Resource
    private MenuMapper menuMapper;
    @Resource
    private RoleMapper roleMapper;
    @Resource
    private RoleMenuMapper roleMenuMapper;
    @Resource
    private PermissionService permissionService;
    @Resource
    private TenantPackageMapper tenantPackageMapper;
    @Resource
    private TenantMapper tenantMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
    @TenantIgnore
    public Long create(AppSaveReqVO createReqVO) {
        AppDO app = BeanUtils.toBean(createReqVO, AppDO.class);
        appMapper.insert(app);
//        //为应用创建默认菜单并授权
        dealAppMenu(1, app);
        return app.getId();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @TenantIgnore
    public Long update(AppSaveReqVO createReqVO) {
        AppDO app = BeanUtils.toBean(createReqVO, AppDO.class);
        appMapper.updateById(app);
//        //修改默认菜单并授权
        dealAppMenu(2, app);
        return app.getId();
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    @TenantIgnore
    public void delete(Long id) {
        AppDO appDO = new AppDO();
        appDO.setId(id);
        dealAppMenu(3, appDO);
        appMapper.deleteById(id);
    }
@@ -53,4 +109,164 @@
        return appMapper.selectPage(pageReqVO);
    }
    @Override
    public List<AppDO> getList() {
        Long tenantId = getTenantId();
        LambdaQueryWrapperX<MenuDO> menuDOLambdaQueryWrapperX = new LambdaQueryWrapperX<>();
        menuDOLambdaQueryWrapperX.eq(MenuDO::getParentId, 0)
                .eq(MenuDO::getAppId, 0);
        if (tenantId != 1) {
            //非系统租户查租户套餐
            TenantDO tenantDO = tenantMapper.selectById(tenantId);
            TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId());
            menuDOLambdaQueryWrapperX.in(MenuDO::getId, tenantPackageDO.getMenuIds());
        }
        //查询系统应用菜单
//        List<MenuDO> menuDOS = menuMapper.selectList(menuDOLambdaQueryWrapperX);
//        List<AppDO> systemApps = convertMenuToApp(menuDOS);
        //创建一个系统管理应用菜单
        AppDO aDo = new AppDO();
        aDo.setAppType(1);
        aDo.setAppName("系统管理");
        aDo.setOrderNum(0);
        List<AppDO> systemApps = new ArrayList<>();
        systemApps.add(aDo);
        List<AppDO> appDOS = appMapper.selectList();
        //暂时先遍历处理应用菜单和应用类型
        appDOS.stream().forEach(appDO -> {
            List<MenuDO> menuDOS = menuMapper.selectList(new LambdaQueryWrapper<MenuDO>().eq(MenuDO::getParentId, 0)
                    .eq(MenuDO::getAppId, appDO.getId()));
            appDO.setAppMenuId(menuDOS.get(0).getId());
            appDO.setAppType(2);
        });
        systemApps.addAll(appDOS);
        return systemApps;
    }
    @Override
    public AppDO getAppByTenantId(Long tenantId) {
        //暂时支持一个租户对应一个应用
        List<AppDO> appDOS = appMapper.selectList(new LambdaQueryWrapper<AppDO>().eq(AppDO::getTenantId, tenantId));
        if(ObjectUtils.isNotEmpty(appDOS)) {
            return appDOS.get(0);
        } else {
            AppDO appDO = new AppDO();
            appDO.setTenantId(tenantId);
            appDO.setId(0L);
            return appDO;
        }
    }
//    @Override
//    public List<MenuRespDTO> getAppMenu(Long id) {
//
//        List<MenuDO> children = new LinkedList<>();
//        // 遍历每一层
//        Collection<Long> parentIds = Collections.singleton(id);
//        for (int i = 0; i < Short.MAX_VALUE; i++) { // 使用 Short.MAX_VALUE 避免 bug 场景下,存在死循环
//            // 查询当前层,所有的子应用菜单
//            List<MenuDO> menus = menuMapper.selectListByParentId(parentIds);
//            // 1. 如果没有子菜单,则结束遍历
//            if (CollUtil.isEmpty(menus)) {
//                break;
//            }
//            // 2. 如果有子应用菜单,继续遍历
//            children.addAll(menus);
//            parentIds = convertSet(menus, MenuDO::getId);
//        }
//        children = menuService.filterDisableMenus(children);
//        return AuthConvert.INSTANCE.buildMenuTree(id, children);
//
//    }
    private void dealAppMenu(Integer type, AppDO app){
        String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname();
        MenuDO menuDO = new MenuDO();
        menuDO.setAppId(app.getId());
        menuDO.setName(app.getAppName());
        menuDO.setType(MenuTypeEnum.DIR.getType());
        menuDO.setSort(app.getOrderNum());
        menuDO.setPath("/" + app.getAppCode());
        menuDO.setTenantId(app.getTenantId());
        if(type == 1){
            menuDO.setCreator(loginUserNickname);
            menuDO.setCreateTime(app.getCreateTime());
            menuMapper.insert(menuDO);
            //内置租户角色分配菜单
            assignRoleMenu(menuDO.getId(), app.getTenantId());
        } else if(type == 2){
            LambdaUpdateWrapper<MenuDO> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(MenuDO::getAppId, app.getId());
            updateWrapper.eq(MenuDO::getParentId, 0L);
            List<MenuDO> menuDOS = menuMapper.selectList(updateWrapper);
            if(menuDOS.size() > 0){
                menuDO.setUpdater(loginUserNickname);
                menuDO.setUpdateTime(app.getUpdateTime());
                menuMapper.update(menuDO, updateWrapper);
            } else {
                menuDO.setCreator(loginUserNickname);
                menuDO.setCreateTime(app.getCreateTime());
                menuMapper.insert(menuDO);
                //内置租户角色分配菜单
                assignRoleMenu(menuDO.getId(), app.getTenantId());
            }
        } else if(type == 3){
            //删除租户、角色权限
            app = appMapper.selectById(app.getId());
            LambdaQueryWrapperX<MenuDO> menuWrapper = new LambdaQueryWrapperX<>();
            menuWrapper.eq(MenuDO::getAppId, app.getId());
            menuWrapper.eq(MenuDO::getType, MenuTypeEnum.DIR.getType());
            MenuDO menu = menuMapper.selectOne(menuWrapper);
            TenantDO tenantDO = tenantMapper.selectById(app.getTenantId());
            TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId());
            Set<Long> menuIds = tenantPackageDO.getMenuIds();
            menuIds.remove(menu.getId());
            // 校验是否还有子菜单
            if (menuMapper.selectCountByParentId(menu.getId()) > 0) {
                throw exception(MENU_EXISTS_CHILDREN);
            }
            // 校验删除的菜单是否存在
            if (menuMapper.selectById(menu.getId()) == null) {
                throw exception(MENU_NOT_EXISTS);
            }
            // 标记删除
            menuMapper.deleteById(menu.getId());
            // 删除授予给角色的权限
            permissionService.processMenuDeleted(menu.getId());
            //删除菜单
            menuMapper.delete(menuWrapper);
        }
    }
    private void assignRoleMenu(Long menuId, Long tenantId) {
        //查询内置租户管理员
        LambdaQueryWrapperX<RoleDO> roleQueryWrapper = new LambdaQueryWrapperX<>();
        roleQueryWrapper.eq(RoleDO::getCode, "tenant_admin");
        roleQueryWrapper.eq(RoleDO::getTenantId, tenantId);
        RoleDO roleDO = roleMapper.selectOne(roleQueryWrapper);
        RoleMenuDO entity = new RoleMenuDO();
        entity.setRoleId(roleDO.getId());
        entity.setMenuId(menuId);
        entity.setTenantId(tenantId);
        roleMenuMapper.insert(entity);
        TenantDO tenantDO = tenantMapper.selectById(tenantId);
        TenantPackageDO tenantPackageDO = tenantPackageMapper.selectById(tenantDO.getPackageId());
        Set<Long> menuIds = tenantPackageDO.getMenuIds();
        menuIds.add(menuId);
        tenantPackageMapper.updateById(tenantPackageDO);
    }
    private List<AppDO> convertMenuToApp(List<MenuDO> menuDOS) {
        List<AppDO> appDOS = new ArrayList<>();
        menuDOS.stream().forEach(menuDO -> {
            AppDO appDO = new AppDO();
            appDO.setAppName(menuDO.getName());
            appDO.setOrderNum(menuDO.getSort());
            appDO.setAppMenuId(menuDO.getId());
            appDO.setAppType(1);
            appDOS.add(appDO);
        });
        return appDOS;
    }
}