二、删除ZTree中的所有父节点与用户组的关联关系(删除多重复杂关系)

(一)案例背景
这里写图片描述
  如上图所示,该功能是依托于ZTree开发的一个权限分配系统。其中用户组和菜单组是相关联的,点击用户组,相关联的菜单树中的节点就被勾选上。菜单树中的节点分为两种:Menu节点(菜单节点)和Action节点(动作节点),例:“内容管理”就是Menu节点,“广告管理”就是Action节点。现在,想开发一个功能:删除Action节点。

(二)问题分析
  因为“用户组”是和Action节点是相关联的,所以:
  第一步:得先删除“用户组”和Action节点的关联关系;
  第二步:再删除Action节点;
  第三步:若Action节点删除以后,其父节点菜单及其父节点菜单的父节点菜单下若再无下辖的Action节点,则需要删除“用户组”和Menu节点的关联关系。

  关于最后一点,我需要详细说明下。由于ZTree的特性,我们在勾选Action节点时,其父节点和父节点的父节点也会被勾选上,如下图:
这里写图片描述
  这样,我们在为“超级管理员组”分配Action节点(1节点)时,同时还建立了“超级管理员组”与“内容管理”、“测试菜单1”和“测试菜单2”的“用户组”和Menu节点的关联关系。当我们删除了Action节点(1节点)时,此时“超级管理员组”与“内容管理”、“测试菜单1”和“测试菜单2”的关联关系还是存在的,就变成了这样:
这里写图片描述
  这样显然是违背我们想要得到的效果的,我们想要的效果是:当删除了Action节点(1节点)时,“内容管理”、“测试菜单1”和“测试菜单2”不应该被勾选上,因为这些菜单节点下已经没有Action节点与“超级管理员组”有关系了。所以我们需要进行第三步:若Action节点删除以后,其父节点菜单及其父节点菜单的父节点菜单下若再无下辖的Action节点,则需要删除“用户组”和Menu节点的关联关系。

(三)解决办法
  解决的核心思想就是:迭代!!具体见代码:

@Override
    public ResultDto removeActionWithId(Integer id) {
        Action action = new Action();
        action.setId(id);
        action = getAction(action);
        if (action == null){
            return new ResultDto(PageCodeEnum.ACTION_NOT_EXISTS);
        }
        //删除Action的关联关系与Action
        removeRelationshipWithAction(action);
        return new ResultDto(PageCodeEnum.DELETE_SUCCESS);
    }

/**
     * 删除Action节点的关联关系(group/action)
     * 重难点:
     *     若菜单及其所有子菜单均无下辖的Action节点,则清除该父节点与用户组之间的关联关系(group/menu),
     *     若父菜单及其所下辖的其他子菜单均无下辖的Action节点,则清除该父菜单与用户组之间的关联关系(group/menu)
     */
    private void removeRelationshipWithAction(Action action){
        //删除Action节点的关联关系(group/action)
        groupActionService.deleteGroupActionByActionId(action.getId());
        //留着
        Integer menuId = action.getMenuId();
        //删除Action
        deleteAction(action);
        //若删除该action以后,父节点菜单及其所有子节点菜单均无其他下辖的Action节点,则清除该父节点与用户组之间的关联关系(group/menu)
        removeGroupMenuIfMenuEmpty(menuId);
    }

/**
     * 若菜单及其所有子菜单均无下辖的Action节点,则清除该父节点与用户组之间的关联关系(group/menu),
     * 若父菜单及其所下辖的其他子菜单均无下辖的Action节点,则清除该父菜单与用户组之间的关联关系(group/menu)
     * @param menuId 菜单id
     */
    private void removeGroupMenuIfMenuEmpty(Integer menuId) {
        Menu menu = new Menu();
        menu.setId(menuId);
        if (CollectionUtils.isNotEmpty(menuService.getMenu(menu))){
            menu = menuService.getMenu(menu).get(0);

            //若菜单及其所有子菜单均无下辖的Action节点,则清除该父节点与用户组之间的关联关系(group/menu)
            removeGroupMenuIfSelfEmpty(menu);

            //清除父节点
            Menu parentMenu = new Menu();
            parentMenu.setId(menu.getParentId());
            if (CollectionUtils.isNotEmpty(menuService.getMenu(parentMenu))){
                //若父菜单及其所下辖的其他子菜单均无下辖的Action节点,则清除该父菜单与用户组之间的关联关系(group/menu)
                removeGroupMenuIfMenuEmpty(menuService.getMenu(parentMenu).get(0).getId());
            }
        }
    }
    /**
     *     若删除该action以后,父节点菜单无其他下辖的Action节点或下辖的所有子菜单,无Action节点,则清除该父节点与用户组
     * 之间的关联关系(group/menu)
     * @param menu Action节点所属的菜单节点
     *     重难点:所有子菜单无Action节点
     */
    private void removeGroupMenuIfSelfEmpty(Menu menu) {
        //自身及所有子菜单均无Action节点
        if (isAllActionListEmpty(menu)){
            //删除与用户组之间的关联关系(group/menu)
            groupMenuService.deleteGroupMenuByMenuId(menu.getId());
        }
    }

    /**
     * 菜单节点本身及其所下辖的所有子菜单节均无Action
     * @param menu 菜单节点
     * @return true:无 false:有
     */
    private boolean isAllActionListEmpty(Menu menu) {
        //下辖actionList不为空
        if (CollectionUtils.isNotEmpty(menu.getActionList())){
            return false;
        }
        //以该菜单节点为父节点的菜单节点actionList不为空
        Menu childMenu = new Menu();
        childMenu.setParentId(menu.getId());
        List<Menu> childMenuList = menuService.getMenu(childMenu);
        if (CollectionUtils.isNotEmpty(childMenuList)){
            for (Menu tempMenu : childMenuList){
                isAllActionListEmpty(tempMenu);
            }
        }
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值