需求:在接口不改动的情况下由树形结构改成表格树结构,如下图

原图

调整后

1.这里使用的是antdesign框架,首先将a-tree改为a-table

<!-- <a-tree checkable v-model="checkedKeys" :treeData="menuTree" @check="checkItem"></a-tree> --><a-table :columns="columns" :data-source="data" :pagination="false"></a-table>

2.定义table中的columns

// 这里除了第一列是菜单名称以外,其余都是checkbox,checkbox采用插槽的方式实现
/*** slots里面定义的是头部插槽名字,头部也有一个多选框* scopedSlots定义的是当前列插槽的名字* */
columns: [{title: '授权菜单',dataIndex: 'title',key: 'title' },{dataIndex: 'entry',key: 'entry',align:'center',slots: { title: 'customEntry' },scopedSlots: { customRender: 'checkBoxEntry' }},{dataIndex: 'edit',align:'center',key: 'edit',slots: { title: 'customEdit' },scopedSlots: { customRender: 'checkBoxEdit' }},{dataIndex: 'approval',align:'center',key: 'approval',slots: { title: 'customApproval' },scopedSlots: { customRender: 'checkBoxApproval' }},{dataIndex: 'query',align:'center',key: 'query',slots: { title: 'customQuery' },scopedSlots: { customRender: 'checkBoxQuery' }}],

此时在table中加入checkbox插槽

// 例如头部
<a-checkbox slot="customEntry">录入</a-checkbox>
<a-checkbox slot="customEdit">编辑</a-checkbox>
<a-checkbox slot="customApproval">审核</a-checkbox>
<a-checkbox slot="customQuery">查询</a-checkbox>
// 每一列同理
<a-checkbox slot="checkBoxEntry" slot-scope="text,item"></a-checkbox>

3.修改后端返回数据data,由于之前是根据树形结构显示,后端在返回数据之前已经很友好的把数据封装成树形结构,示例如下:
(其中a10001、a10002、a10003、a10004分别表示录入、编辑、审核、查询权限)

[{                                                            //一级菜单"title": "计划管理",                                       "children": [{                                          // 授权模块"menuCode": "15","title": "设备需求计划",                              "children": [{                                       // 模块可分配的权限"authority_button_name": "录入","authority_button_code": "a10001","menu_id": "15"},{"authority_button_name": "编辑","authority_button_code": "a10002","menu_id": "15"},{"authority_button_name": "审核","authority_button_code": "a10003","menu_id": "15"},{"authority_button_name": "查询","authority_button_code": "a10004","menu_id": "15"}],}],"menuCode": "14"},{"title": "设备进场管理","children": [{"title": "设备进场验收管理","children": [{"authority_button_name": "录入","authority_button_code": "a10001","menu_id": "33"}],"menuCode": "33"},{"title": "水电管理","children": [{                                              //  二级菜单"title": "水电抄表记录单","children": [{"authority_button_name": "录入","authority_button_code": "a10001","menu_id": "40"},{"authority_button_name": "编辑","authority_button_code": "a10002","menu_id": "40"},{"authority_button_name": "审核","authority_button_code": "a10003","menu_id": "40"},{"authority_button_name": "查询","authority_button_code": "a10004","menu_id": "40"}],"menuCode": "40"}],"menuCode": "112"}],"menuCode": "38"},],

由于树形结构的数据与表格树的数据基本类型,因此只需要把最里面一层children(模块可分配的权限)拿出来即可。

处理完以后的数据结构如下:

  1. authButtonGroup保存该模块下可选择的权限,即原始数据中的children中的数据,删除该children字段
  2. authButton保存该用户在该模块下已经存在的权限
[{                                                            //一级菜单"title": "计划管理",                                       "children": [{                                          // 授权模块"menuCode": "15","title": "设备需求计划",   authButtonGroup: ['a10001','a10002','a10003','a10004'],     // 授权模块可选的权限authButton: ['a10001']                                      // 该用户目前已经拥有的权限}],"menuCode": "14"},{"title": "设备进场管理","children": [{"title": "设备进场验收管理",authButtonGroup: ['a10001'],authButton: ['a10001'],"menuCode": "33"          },{"title": "水电管理","children": [{                                              //  二级菜单"title": "水电抄表记录单",authButtonGroup: ['a10001','a10002','a10003','a10004'],authButton: ['a10001']                           "menuCode": "40"}],"menuCode": "112"}],"menuCode": "38"},],

处理数据的方法如下:

      let promises = [获取用户权限的接口,获取权限树的接口];Promise.all(promises).then(result=>{// 对用户权限做处理,用授权模块的menu_code作为key存入对象,以便下面使用let authButton = result[0].responseList;let authButtonMap = {};Array.isArray(authButton) && authButton.forEach(item=>{authButtonMap[item.menu_code] = item.authority_button_codes ? item.authority_button_codes.split(',') : [];})// 获取到权限树let data = [...result[1].responseList];// 定义一个方法对树进行处理function dealTree(item){let child = item.children;// 子节点不是菜单就是权限按钮,一般子节点下都只存在一种类型,非1即2child.forEach(inner=>{// 通过title判断,没有的就是模块可选的权限if(inner.title){dealTree(inner)}else{// 是模块可选的权限了,存起来!item.authButtonGroup && (item.authButtonGroup = []);item.authButtonGroup.push(inner.authority_button_code);}})if(item.authButtonGroup){item.authButton = authButtonMap[item.menuCode] || [];      //  存储用户在当前模块已有的权限delete item.children;  // 删除children}return item;}this.data = data.map(item=>{return dealTree(item);});

此时数据结构就变成了

菜单授权模块(包含模块可选的权限)菜单授权模块(包含模块可选的权限)

下面给checkbox绑定属性(点击事件、默认选中、菜单的半选状态)

先根据用户存在的权限默认选中:

// 如何当前授权模块中的authButton有a10001说明该用户存在这个权限,设置选中
<a-checkbox slot="checkBoxEntry" slot-scope="text,item" :checked="item.authButton.includes('a10001')"></a-checkbox>

分析:
1.当该节点是菜单时,不存在authButton这个数组
2.checkbox是否显示应该根据authButtonGroup这个数组中是否有值,即该模块可以被授什么权

进行如下改造:

<template slot="checkBoxEntry" slot-scope="text,item">//  该节点存在authButtonGroup,即授权模块<template v-if="item.authButtonGroup">//  判断该模块是否可以授权a10001,即authButtonGroup是否存在,有就显示checkbox,没有就不显示<a-checkbox v-if="item.authButtonGroup.includes('a10001')" :checked="item.authButton.includes('a10001')"></a-checkbox><span v-else></span></template>//  菜单是否显示checkbox,//  菜单显示checkbox的用途是用于给下面所有模块的全选或者全取消功能//  所有应该判断下面的模块是否存在checkbox,这里的判读条件不够全面,下面再说<a-checkbox v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10001'))" ></a-checkbox><span v-else></span>
</template>

绑定点击事件
(由于每个checkbox设置的选中状态都是通过该模块的authButton数组是否有a10001、a10002、a10003、a10004。因此原理就是在该授权模块的authButton将指定的authCode加入或者删除)

<template slot="checkBoxEntry" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox@change="onChangeRecord($event,item,'a10001')" v-if="item.authButtonGroup.includes('a10001')" :checked="item.authButton.includes('a10001')"></a-checkbox><span v-else></span></template><a-checkbox@change="onChangeRecordMenu($event,item,'a10001')"v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10001'))"></a-checkbox><span v-else></span>
</template>/**   授权模块的点击事件  **/
onChangeRecord(event,record,authCode){this.compareDleteOrAdd(record.authButton,authCode,true,true);  // 之前是选中点击即删除,之前未选中点击即添加this.$forceUpdate();  // 由于绑定的都是方法执行结果,手动触发视图更新
},
// 在数组中增加或者减少一项
compareDleteOrAdd(arr,item,isAdd,isDel){let index = arr.indexOf(item)if(index > -1){if(isDel){arr.splice(index,1);}}else{if(isAdd){arr.push(item);}}return index;
},
/**   菜单的点击事件  **/
onChangeRecordMenu(event,record,authCode){// 先获取当前点击按钮是选中还是取消,选中即菜单下所有模块全部选中,相反取消则全部取消let flag = event.target.checked;// 获取菜单下面的授权模块或者下级菜单let children = record.children;let stack = [];// 循环遍历,将所有的子模块都添加或者删除authCodewhile(children){children.forEach(item=>{// 是授权模块则直接删除或添加if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){if(flag){this.compareDleteOrAdd(item.authButton,authCode,true,false);}else{this.compareDleteOrAdd(item.authButton,authCode,false,true);}}}else{// 如果是菜单,定义一个stack栈存入,下级菜单中的授权模块也需要处理stack.push(item);}})//  将stack栈中的菜单从第一个推出,再循环(主要是存在多级菜单的原因)let next = stack.shift();children = next ? next.children : '';}this.$forceUpdate();   // 手动触发视图更新
},

设置菜单的选中、半选状态

<template slot="checkBoxEntry" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox@change="onChangeRecord($event,item,'a10001')" v-if="item.authButtonGroup.includes('a10001')" :checked="item.authButton.includes('a10001')"></a-checkbox><span v-else></span></template><a-checkbox@change="onChangeRecordMenu($event,item,'a10001')"v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10001'))":checked="checkAllSelect(item,'a10001')":indeterminate="indeterminateCheck(item,'a10001') && !checkAllSelect(item,'a10001')" ></a-checkbox><span v-else></span>
</template>/**   菜单的全选状态checkAllSelect返回true即全选  **/
// 即只需找到一个授权模块没有选中即返回false,找不到返回true
checkAllSelect(item,authCode){// 找到一个不满足let flag = true;let children = item.children;if(!item || !item.children){return false;}let stack = [];while(children){children.some(item=>{if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){flag = item.authButton.includes(authCode);return !flag;}}else{stack.push(item);return false;}})// 找到了不向下执行if(!flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag;
},/**   菜单的半选状态设置checkout的indeterminate属性为true,即半选**/
//  半选其实就是至少有一个选中并且不是全部选中
// :indeterminate="indeterminateCheck(item,'a10001') && !checkAllSelect(item,'a10001')"
// 找到至少一个选中
indeterminateCheck(item,authCode){// 至少有一个选中let flag = false;let children = item.children;let stack = [];while(children){children.some(item=>{if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){flag = item.authButton.includes(authCode);return flag;}}else{stack.push(item);return false;}})// 找到了有一个if(flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag;
},

完成以上操作基本上菜单的全选、取消、半选状态,授权模块的选择取消都已经处理完了

处理顶部的全选按钮(其实方法都是执行一样的,只是传参数的时候将这个表格数据data当初children传人即可)

<a-checkbox @change="onChangeAll($event,'a10001')" :checked="checkAllSelect({children:data},'a10001')":indeterminate="indeterminateCheck({children:data},'a10001') && !checkAllSelect({children:data},'a10001')"slot="customEntry">录入</a-checkbox>/**  点击事件 **/
onChangeAll(event,authCode){this.onChangeRecordMenu(event,{children:this.data},authCode);
},

完整代码如下:

<template><div class="permission-auth-model"><a-table :columns="columns" :data-source="data" :pagination="false"><a-checkbox @change="onChangeAll($event,'a10001')" :checked="checkAllSelect({children:data},'a10001')":indeterminate="indeterminateCheck({children:data},'a10001') && !checkAllSelect({children:data},'a10001')"slot="customEntry">录入</a-checkbox><a-checkbox @change="onChangeAll($event,'a10002')" :checked="checkAllSelect({children:data},'a10002')":indeterminate="indeterminateCheck({children:data},'a10002') && !checkAllSelect({children:data},'a10002')"slot="customEdit">编辑</a-checkbox><a-checkbox @change="onChangeAll($event,'a10003')":checked="checkAllSelect({children:data},'a10003')":indeterminate="indeterminateCheck({children:data},'a10003') && !checkAllSelect({children:data},'a10003')" slot="customApproval">审核</a-checkbox><a-checkbox @change="onChangeAll($event,'a10004')":checked="checkAllSelect({children:data},'a10004')":indeterminate="indeterminateCheck({children:data},'a10004') && !checkAllSelect({children:data},'a10004')"slot="customQuery">查询</a-checkbox><template slot="checkBoxEntry" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox @change="onChangeRecord($event,item,'a10001')" v-if="item.authButtonGroup.includes('a10001')" :checked="item.authButton.includes('a10001')"></a-checkbox><span v-else></span></template><a-checkbox @change="onChangeRecordMenu($event,item,'a10001')" v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10001'))" :checked="checkAllSelect(item,'a10001')":indeterminate="indeterminateCheck(item,'a10001') && !checkAllSelect(item,'a10001')"></a-checkbox><span v-else></span></template><template slot="checkBoxEdit" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox @change="onChangeRecord($event,item,'a10002')" v-if="item.authButtonGroup.includes('a10002')" :checked="item.authButton.includes('a10002')"></a-checkbox><span v-else></span></template><a-checkbox @change="onChangeRecordMenu($event,item,'a10002')" v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10002'))" :checked="checkAllSelect(item,'a10002')":indeterminate="indeterminateCheck(item,'a10002') && !checkAllSelect(item,'a10002')"></a-checkbox><span v-else></span></template><template slot="checkBoxApproval" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox @change="onChangeRecord($event,item,'a10003')" v-if="item.authButtonGroup.includes('a10003')" :checked="item.authButton.includes('a10003')"></a-checkbox><span v-else></span></template><a-checkbox @change="onChangeRecordMenu($event,item,'a10003')" v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10003'))" :checked="checkAllSelect(item,'a10003')":indeterminate="indeterminateCheck(item,'a10003') && !checkAllSelect(item,'a10003')"></a-checkbox><span v-else></span></template><template slot="checkBoxQuery" slot-scope="text,item"><template v-if="item.authButtonGroup"><a-checkbox @change="onChangeRecord($event,item,'a10004')" v-if="item.authButtonGroup.includes('a10004')" :checked="item.authButton.includes('a10004')"></a-checkbox><span v-else></span></template><a-checkbox @change="onChangeRecordMenu($event,item,'a10004')" v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10004'))" :checked="checkAllSelect(item,'a10004')":indeterminate="indeterminateCheck(item,'a10004') && !checkAllSelect(item,'a10004')"></a-checkbox><span v-else></span></template></a-table></div>
</template><script>
export default {name: 'EnumModal',data() {return {columns: [{title: '授权菜单',dataIndex: 'title',key: 'title' },{dataIndex: 'entry',key: 'entry',align:'center',slots: { title: 'customEntry' },scopedSlots: { customRender: 'checkBoxEntry' }},{dataIndex: 'edit',align:'center',key: 'edit',slots: { title: 'customEdit' },scopedSlots: { customRender: 'checkBoxEdit' }},{dataIndex: 'approval',align:'center',key: 'approval',slots: { title: 'customApproval' },scopedSlots: { customRender: 'checkBoxApproval' }},{dataIndex: 'query',align:'center',key: 'query',slots: { title: 'customQuery' },scopedSlots: { customRender: 'checkBoxQuery' }}],data: []}},created(){this.getTableData();},methods: {// 校验一个是否存在menucode或者子节点存在checkAllSelect(item,authCode){// 找到一个不满足let flag = true;let children = item.children;if(!item || !item.children){return false;}let stack = [];while(children){children.some(item=>{if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){flag = item.authButton.includes(authCode);return !flag;}}else{stack.push(item);return false;}})// 找到了不向下执行if(!flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag;},// 校验是否是半选状态indeterminateCheck(item,authCode){// 至少有一个选中let flag = false;let children = item.children;let stack = [];while(children){children.some(item=>{if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){flag = item.authButton.includes(authCode);return flag;}}else{stack.push(item);return false;}})// 找到了有一个if(flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag;},onChangeAll(event,authCode){let data = this.data.filter(item=>{return item.menuCode != 82;})let flag = this.checkAllSelect({children:this.data},authCode);event.target.checked = !flag;this.onChangeRecordMenu(event,{children:data},authCode);},onChangeRecordMenu(event,record,authCode){let flag = event.target.checked;let children = record.children;let stack = [];while(children){console.log(children);children.forEach(item=>{if(item.authButtonGroup){if(item.authButtonGroup.includes(authCode)){if(flag){this.compareDleteOrAdd(item.authButton,authCode,true,false);}else{this.compareDleteOrAdd(item.authButton,authCode,false,true);}}}else{stack.push(item);}})let next = stack.shift();children = next ? next.children : '';}this.$forceUpdate();},onChangeRecord(event,record,authCode){this.compareDleteOrAdd(record.authButton,authCode,true,true);this.$forceUpdate();},// 在数组中增加或者减少一项compareDleteOrAdd(arr,item,isAdd,isDel){let index = arr.indexOf(item)if(index > -1){if(isDel){arr.splice(index,1);}}else{if(isAdd){arr.push(item);}}return index;},getTableData() {let promises = [获取人员权限,获取表格树];Promise.all(promises).then(result=>{let authButton = result[0].responseList;let authButtonMap = {};Array.isArray(authButton) && authButton.forEach(item=>{authButtonMap[item.menu_code] = item.authority_button_codes ? item.authority_button_codes.split(',') : [];})let data = [...result[1].responseList];function dealTree(item){let child = item.children;if(Array.isArray(child)){if(child.length == 0){item.authButtonGroup = ['a10004'];}else {child.forEach(inner=>{if(inner.title){dealTree(inner)}else{!item.authButtonGroup && (item.authButtonGroup = []);item.authButtonGroup.push(inner.authority_button_code);}})}}if(item.authButtonGroup){item.authButton = authButtonMap[item.menuCode] || [];delete item.children;}return item;}this.data = data.map(item=>{return dealTree(item);});},
}
</script>

树形选择变成表格树选择相关推荐

  1. 数据库树形结构存储方法的选择

    树形结构存储方法的选择 简单的方法跟踪多级回复构成的树形分支:parent_id 一开始的思路 使用parent_id跟踪分支 使用先找出所有节点,按照一定顺序整合成树形结构 缺陷: 在深度过深时仅用 ...

  2. Ant Design Pro在使用TreeSelect树选择组件时,报错未注册

    Ant Design Pro在使用树选择组件时,报错未注册 did you register the component correctly? 经过检查发现Ant Design Pro是按需引入的,需 ...

  3. 计算机表格怎样筛选男女,excel表格数据男女筛选-EXCEL表格中选择性别怎么做 就是如何做筛选 ,比如......

    如何将一张EXCEL表格中同时符合2个条件的数据筛选... 利用excel的数据有效性功能可以达到目标,以下步骤以excel2007为例. 1.首先在电脑上打开目标表格文件,选中目标单元格. 2.然后 ...

  4. Excel技巧【标记多行数据连续一样的行】【第一个单元格公式适用于所有本列所有行】【按照逗号分列】【快速统计出各个项出现的次数】【冻结窗口】[表格分段选择数据][根据单元格内容引索其他单元格数据指针]

    标记多行数据一样的行 我这里有一列数据,现在想识别出多行数据连续一样的目的行,数据如下左图所示: 这里可以对F1单元格使用这样的公式:=IF(AND(E1=E2,E2=E3,E3=E4,E4=E5,E ...

  5. 树选择排序(Tree Selection Sorting)介绍

    简介 或许你有一个疑问:为什么堆排序使用二叉树,但是叫堆排序,而不是树排序? 因为堆排序的前身正是叫做树选择排序(Tree Selection Sorting),使用树结构,但是要稍微简单一些. 高德 ...

  6. 选下拉框的的值对应上传相应的图片_如何在excel中实现,选择下拉菜单某一项,该表格中就出现选项对应的数据?(excel表格制作选择数据)...

    怎样从多个excel表格中提取数据,做数据分析图呢 1. 数据的.录入.表格的设置,效果如示. 2.如图所示,选进行分析的图据范围 3.如图所示,点击菜单栏目上的"插入",选择&q ...

  7. [4G/5G/6G专题基础-160]: BLER与MCS的关系、MCS表格的选择

    目录 第1章 什么是MCS 1.1 基本概念 1.2 三张不同的MCS表 1.3 MCS表的选择 1.4 MCS index的选择 第2章 什么是BLER 2.1 什么是比特误码率BER 2.2 什么 ...

  8. 为什么MySQL数据库索引选择使用B+树?

    在进一步分析为什么MySQL数据库索引选择使用B+树之前,我相信很多小伙伴对数据结构中的树还是有些许模糊的,因此我们由浅入深一步步探讨树的演进过程,在一步步引出B树以及为什么MySQL数据库索引选择使 ...

  9. antd 表格树如何展开_ant-design-pro protable 树形表格默认展开

    Protable 是在antd 的 table 上进行了一层封装,antd -table中有的属性它都支持. 当表格数据中有children字段,table会默认生成树形可展开表格,有时候需要一开始就 ...

最新文章

  1. Android Linux 9,linux学习(一)(ubuntu9.10 玩转android)
  2. 拥抱AI大趋势,ARM发布两款AI芯片架构
  3. 广东省哈工大(深圳)赛区赛事活动安排
  4. 项目:部署LNMP动态网站
  5. jQuery Vue的CDN
  6. 中间人攻击-http流量嗅探
  7. babel原理_带你了解 snowpack 原理,你还学得动么(下)
  8. oracle11连12c报权限错误,关于Oracle12c连接报错的问题
  9. CentOS报错:Could not retrieve mirrorlist http://mirrorlist.centos.org/?release=7arch=x86_64repo=osi...
  10. HDU 1542:Atlantis(扫描线+线段树 矩形面积并)***
  11. SAP License:SAP有限度的多语言支持
  12. 简单的方法完成项目上传到github
  13. 大学学习路线规划建议贴
  14. linux如何查看路由器ip地址,如何查找路由器IP地址?
  15. 更改C盘用户目录下的文件夹名称
  16. 全靠我啃烂了这份2021最新面试题!吊打面试官
  17. centos6如何添加阿里云centos和epel源
  18. wangeditor设置字体_自定义颜色、字体、字号
  19. 249、海康8700监控服务平台如何配置手机远程访问
  20. html5之音乐播放器实例 (可以切换歌曲和背景照片)

热门文章

  1. 需要使用新应用以打开此ms-gamingoverlay链接
  2. problem中Project'XX'is missing required library:'[路径]\XXX.jar'解决方法
  3. 解决Word表格粘贴的“错位”问题(转)
  4. Python综合案例—利用tkinter实现计算器的程序
  5. 国外15个免费网页模板下载的集合网站
  6. PostgreSQL修炼之道:从小工到专家. 导读
  7. 蒲慕明院士PNAS最新研究:神经元数量在共同激活诱导大脑神经元兴奋性增强的重要性...
  8. excel计算机系统验证方案,Excel公式计算数据完整性验证方案
  9. 库克自愿降薪超 40%,年薪减至 4900 万美元
  10. 【leetcode】小彩蛋|主页draw