树形选择变成表格树选择
需求:在接口不改動(dòng)的情況下由樹(shù)形結(jié)構(gòu)改成表格樹(shù)結(jié)構(gòu),如下圖
原圖
調(diào)整后
1.這里使用的是antdesign框架,首先將a-tree改為a-table
2.定義table中的columns
// 這里除了第一列是菜單名稱以外,其余都是checkbox,checkbox采用插槽的方式實(shí)現(xiàn) /*** slots里面定義的是頭部插槽名字,頭部也有一個(gè)多選框* scopedSlots定義的是當(dāng)前列插槽的名字* */ columns: [{title: '授權(quán)菜單',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' }}],此時(shí)在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.修改后端返回?cái)?shù)據(jù)data,由于之前是根據(jù)樹(shù)形結(jié)構(gòu)顯示,后端在返回?cái)?shù)據(jù)之前已經(jīng)很友好的把數(shù)據(jù)封裝成樹(shù)形結(jié)構(gòu),示例如下:
(其中a10001、a10002、a10003、a10004分別表示錄入、編輯、審核、查詢權(quán)限)
由于樹(shù)形結(jié)構(gòu)的數(shù)據(jù)與表格樹(shù)的數(shù)據(jù)基本類型,因此只需要把最里面一層children(模塊可分配的權(quán)限)拿出來(lái)即可。
處理完以后的數(shù)據(jù)結(jié)構(gòu)如下:
處理數(shù)據(jù)的方法如下:
let promises = [獲取用戶權(quán)限的接口,獲取權(quán)限樹(shù)的接口];Promise.all(promises).then(result=>{// 對(duì)用戶權(quán)限做處理,用授權(quán)模塊的menu_code作為key存入對(duì)象,以便下面使用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(',') : [];})// 獲取到權(quán)限樹(shù)let data = [...result[1].responseList];// 定義一個(gè)方法對(duì)樹(shù)進(jìn)行處理function dealTree(item){let child = item.children;// 子節(jié)點(diǎn)不是菜單就是權(quán)限按鈕,一般子節(jié)點(diǎn)下都只存在一種類型,非1即2child.forEach(inner=>{// 通過(guò)title判斷,沒(méi)有的就是模塊可選的權(quán)限if(inner.title){dealTree(inner)}else{// 是模塊可選的權(quán)限了,存起來(lái)!item.authButtonGroup && (item.authButtonGroup = []);item.authButtonGroup.push(inner.authority_button_code);}})if(item.authButtonGroup){item.authButton = authButtonMap[item.menuCode] || []; // 存儲(chǔ)用戶在當(dāng)前模塊已有的權(quán)限delete item.children; // 刪除children}return item;}this.data = data.map(item=>{return dealTree(item);});此時(shí)數(shù)據(jù)結(jié)構(gòu)就變成了
菜單授權(quán)模塊(包含模塊可選的權(quán)限)菜單授權(quán)模塊(包含模塊可選的權(quán)限)下面給checkbox綁定屬性(點(diǎn)擊事件、默認(rèn)選中、菜單的半選狀態(tài))
先根據(jù)用戶存在的權(quán)限默認(rèn)選中:
// 如何當(dāng)前授權(quán)模塊中的authButton有a10001說(shuō)明該用戶存在這個(gè)權(quán)限,設(shè)置選中 <a-checkbox slot="checkBoxEntry" slot-scope="text,item" :checked="item.authButton.includes('a10001')"></a-checkbox>分析:
1.當(dāng)該節(jié)點(diǎn)是菜單時(shí),不存在authButton這個(gè)數(shù)組
2.checkbox是否顯示應(yīng)該根據(jù)authButtonGroup這個(gè)數(shù)組中是否有值,即該模塊可以被授什么權(quán)
進(jìn)行如下改造:
<template slot="checkBoxEntry" slot-scope="text,item">// 該節(jié)點(diǎn)存在authButtonGroup,即授權(quán)模塊<template v-if="item.authButtonGroup">// 判斷該模塊是否可以授權(quán)a10001,即authButtonGroup是否存在,有就顯示checkbox,沒(méi)有就不顯示<a-checkbox v-if="item.authButtonGroup.includes('a10001')" :checked="item.authButton.includes('a10001')"></a-checkbox><span v-else></span></template>// 菜單是否顯示checkbox,// 菜單顯示checkbox的用途是用于給下面所有模塊的全選或者全取消功能// 所有應(yīng)該判斷下面的模塊是否存在checkbox,這里的判讀條件不夠全面,下面再說(shuō)<a-checkbox v-else-if="item.children.some(inner => inner.authButtonGroup.includes('a10001'))" ></a-checkbox><span v-else></span> </template>綁定點(diǎn)擊事件
(由于每個(gè)checkbox設(shè)置的選中狀態(tài)都是通過(guò)該模塊的authButton數(shù)組是否有a10001、a10002、a10003、a10004。因此原理就是在該授權(quán)模塊的authButton將指定的authCode加入或者刪除)
設(shè)置菜單的選中、半選狀態(tài)
<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>/** 菜單的全選狀態(tài)checkAllSelect返回true即全選 **/ // 即只需找到一個(gè)授權(quán)模塊沒(méi)有選中即返回false,找不到返回true checkAllSelect(item,authCode){// 找到一個(gè)不滿足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;}})// 找到了不向下執(zhí)行if(!flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag; },/** 菜單的半選狀態(tài)設(shè)置checkout的indeterminate屬性為true,即半選**/ // 半選其實(shí)就是至少有一個(gè)選中并且不是全部選中 // :indeterminate="indeterminateCheck(item,'a10001') && !checkAllSelect(item,'a10001')" // 找到至少一個(gè)選中 indeterminateCheck(item,authCode){// 至少有一個(gè)選中l(wèi)et 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;}})// 找到了有一個(gè)if(flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag; },完成以上操作基本上菜單的全選、取消、半選狀態(tài),授權(quán)模塊的選擇取消都已經(jīng)處理完了
處理頂部的全選按鈕(其實(shí)方法都是執(zhí)行一樣的,只是傳參數(shù)的時(shí)候?qū)⑦@個(gè)表格數(shù)據(jù)data當(dāng)初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>/** 點(diǎn)擊事件 **/ 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: '授權(quán)菜單',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: {// 校驗(yàn)一個(gè)是否存在menucode或者子節(jié)點(diǎn)存在checkAllSelect(item,authCode){// 找到一個(gè)不滿足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;}})// 找到了不向下執(zhí)行if(!flag){break;}let next = stack.shift();children = next ? next.children : '';}return flag;},// 校驗(yàn)是否是半選狀態(tài)indeterminateCheck(item,authCode){// 至少有一個(gè)選中l(wèi)et 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;}})// 找到了有一個(gè)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();},// 在數(shù)組中增加或者減少一項(xiàng)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 = [獲取人員權(quán)限,獲取表格樹(shù)];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>總結(jié)
以上是生活随笔為你收集整理的树形选择变成表格树选择的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: vue.js用benz-amr-reco
- 下一篇: 植物大战僵尸 1.0 简体中文版