Leanote's Blog
I love Leanote!
Toggle navigation
Leanote's Blog
Home
Chrome
Git
Linux
Windows
Others
工具大全
VsCode
Expo
Html
JavaScript
Npm
Node
Mock
React-Native
React
TypeScript
小程序
插件
正则
Dva
Ant-Design-React
Umi
Vue
Vux
Ant-Design-Vue
Http
Java
flutter
开发小工具
About Me
Archives
Tags
vue表格权限树组件
2021-05-08 07:43:00
4
0
0
admin
### **两列表格(完整版)** ``` <template> <div class="permission"> <div class="check_all_box"> <el-checkbox v-model="checkAll" :indeterminate="!!checkedList && !! checkedList.length && isIndeterminate['all']" @change="handleCheckAllChange" > 全选 </el-checkbox> </div> <el-checkbox-group v-model="checkedList" @change="handleItemChange" > <template v-for="(Ritem, Ridx) in allPermission"> <div class="check_item_box rflex" :key="Ritem[allPermissionDataType.code]" > <div class="parent_box border_box rflex flex_align_items_center"> <el-checkbox :label="Ritem[allPermissionDataType.code]" :indeterminate="getItemAll(Ritem)" @change="v => handleCheckChange(v, [Ridx], Ritem)" > {{ Ritem[allPermissionDataType.name] }} </el-checkbox> </div> <div class="children_container rflex flex_wrap" v-if="Array.isArray(Ritem[allPermissionDataType.childList]) && Ritem[allPermissionDataType.childList].length" > <template v-for="(Iitem, Iidx) in Ritem[allPermissionDataType.childList]"> <div :key="Iitem[allPermissionDataType.code]" class="children_row" > <div class="item_container"> <el-checkbox :label="Iitem.label" :indeterminate="isIndeterminate[Iitem[allPermissionDataType.code]]" @change="v => handleCheckChange(v, [Ridx, Iidx], Iitem)" > {{ Iitem[allPermissionDataType.name] }} </el-checkbox> </div> </div> </template> </div> </div> </template> </el-checkbox-group> </div> </template> <script> export default { name: "permissionTable", props: { /** * 所有权限数据 * 格式 * [ * { * name: String, //名称 * label: String, //选中标识 * code: String | Number, // 标识 * childList: [], // 子数据 * }, * ... * ] */ allPermission: { type: Array, default: () => [], }, /** * 已有权限数据 * 格式 * [ * String | Number, // 标识 * ... * ] */ hasPermission: { type: Array, default: () => [], }, /** * 所有权限数据key */ allPermissionDataType: { type: Object, default: () => ({ name: "name", label: "label", code: "code", childList: "childList", }) } }, data() { return { checkAll: false, checkObj: {}, checkedList: [], isIndeterminate: { all: true }, allPermissionId: [], defaultPermission: [], userIdList: [], noUserParent: [], tureAll: [], userCode: "", loginPerMission: [], } }, methods: { // 权限相关 getItemAll(item) { if (this.checkedList.includes(item[this.allPermissionDataType.code])) { // 无子权限 if (!item[this.allPermissionDataType.childList] || !item[this.allPermissionDataType.childList].length) { return false } let state = false // 有子权限 for (let index in item[this.allPermissionDataType.childList]) { let code = item[this.allPermissionDataType.childList][index][this.allPermissionDataType.code] if (!this.checkedList.includes(code)) { state = true } } return state } }, initData() { this.checkAll = false this.checkedList = [] // this.hasPermission = [] this.isIndeterminate = { all: true } }, getAllId(arr) { const list = arr.reduce((pre, cur) => { pre.push(cur[this.allPermissionDataType.code]) if (cur[this.allPermissionDataType.childList] instanceof Array && cur[this.allPermissionDataType.childList].length) { pre = pre.concat(this.getAllId(cur[this.allPermissionDataType.childList])) } return pre }, []) return list }, handleCheckAllChange(val) { this.checkedList = val ? this.tureAll : [] this.isIndeterminate['all'] = false }, handleCheckChange(val, idxArr, item) { let newVal let setArr = this.checkedList const list = this.allPermission let state = false if (item[this.allPermissionDataType.childList] && item[this.allPermissionDataType.childList].length) { for (let index in item[this.allPermissionDataType.childList]) { let code = item[this.allPermissionDataType.childList][index][this.allPermissionDataType.code] if (!this.checkedList.includes(code)) { state = true } } } else { state = true } if (val && state) { // 上选 -> 下全选 if (idxArr.length !== 3) { setArr = [...setArr, ...this.selectChildsAll(idxArr)] } if (idxArr.length !== 1) { // 下选 -> 上级所有选中 setArr = [...setArr, ...this.addErgodicItem(list, idxArr)] } newVal = Array.from(new Set(setArr)) } else { if (idxArr.length !== 3) { // 上不选 -> 下全不选 setArr = this.removeErgodicItem(list, idxArr) } // 下不选 -> 上判断是否有下选 setArr = this.hasChildsSelect(setArr, idxArr) newVal = Array.from(new Set(setArr)) } this.checkedList = newVal }, handleItemChange(val) { const count = val.length this.checkAll = count === this.allPermissionId.length this.isIndeterminate['all'] = count > 0 && count < this.allPermissionId.length }, /** * 下不选 -> 上判断是否有下选 */ hasChildsSelect(checkedList, idxArr) { const list = this.allPermission let arr = new Set(checkedList) if (idxArr.length === 1) { } else if (idxArr.length === 2) { const cArr = list[idxArr[0]][this.allPermissionDataType.childList].map(i => i[this.allPermissionDataType.code]) const hasChild = checkedList.some(i => cArr.includes(i)) if (!hasChild) { arr.delete(list[idxArr[0]][this.allPermissionDataType.code]) } } else if (idxArr.length === 3) { const cArr2 = list[idxArr[0]][this.allPermissionDataType.childList][idxArr[1]][this.allPermissionDataType.childList].map(i => i[this.allPermissionDataType.code]) const hasChild2 = checkedList.some(i => cArr2.includes(i)) if (!hasChild2) { arr.delete(list[idxArr[0]][this.allPermissionDataType.childList][idxArr[1]][this.allPermissionDataType.code]) } const cArr1 = list[idxArr[0]][this.allPermissionDataType.childList].map(i => i[this.allPermissionDataType.code]) const hasChild1 = Array.from(arr).some(i => cArr1.includes(i)) if (!hasChild1) { arr.delete(list[idxArr[0]][this.allPermissionDataType.code]) } } return Array.from(arr) }, /** * 往下便利数据 */ ergodicDownList(list, idxArr = []) { const f = idxArr[0] let arr = [] for (let i = 0; i < list.length; i++) { if (f === undefined || f === i) { const child = list[i][this.allPermissionDataType.childList] ? this.ergodicDownList(list[i][this.allPermissionDataType.childList], idxArr.slice(1)) : [] arr = [...arr, list[i][this.allPermissionDataType.code], ...child] } } return arr }, /** * 全选 */ selectChildsAll(idxArr = []) { const list = this.allPermission let val = [] val = this.ergodicDownList(list, idxArr) return val }, /** * 上选 -> 下全选 */ chooseChildsAll(list, idxArr = []) { let val = [] val = this.ergodicDownList(list, idxArr) return val }, /** * 下选 -> 上级所有选中 */ addErgodicItem(list, idxArr = []) { let val = new Set() const item = list[idxArr[0]] const newIdx = idxArr.slice(1) val.add(item[this.allPermissionDataType.code]) if (item[this.allPermissionDataType.childList] && newIdx.length) { val.add(...this.addErgodicItem(item[this.allPermissionDataType.childList], newIdx)) } return val }, /** * 上不选 -> 下全不选 */ removeErgodicItem(list, idxArr = []) { const set = new Set(this.checkedList) if (idxArr.length === 2) { try { list[idxArr[0]][this.allPermissionDataType.childList][idxArr[1]][this.allPermissionDataType.childList].forEach(item => { set.delete(item[this.allPermissionDataType.code]) }) } catch (err) { } } else if (idxArr.length === 1) { for (let index in list[idxArr[0]][this.allPermissionDataType.childList]) { let code = list[idxArr[0]][this.allPermissionDataType.childList][index][this.allPermissionDataType.code] if (!this.checkedList.includes(code)) { let arr = this.chooseChildsAll(list, idxArr) arr.forEach(item => set.add(item)) return Array.from(set) } } const child = list[idxArr[0]] set.delete(child[this.allPermissionDataType.code]) if (child[this.allPermissionDataType.childList] && child[this.allPermissionDataType.childList].length) { child[this.allPermissionDataType.childList].forEach(Ritem => { set.delete(Ritem[this.allPermissionDataType.code]) if (Ritem[this.allPermissionDataType.childList]) { Ritem[this.allPermissionDataType.childList].forEach(Iitem => { set.delete(Iitem[this.allPermissionDataType.code]) }) } }) } } return Array.from(set) }, } } </script> <style scoped lang="scss"> .permission { font-size: 14px; color: #656b7b; padding-left: 10px; padding-right: 10px; .check_all_box { background-color: #fafafa; border: 1px solid #eee; height: 38px; line-height: 38px; padding-left: 14px; } .check_item_box { border: 1px solid #eee; border-top: 0; .parent_box { width: 110px; min-height: 38px; border-right: 1px solid #eee; box-sizing: border-box; padding-left: 14px; overflow: hidden; } .children_container { flex: 1; padding: 14px 0 0 10px; .children_row { .item_container { width: 110px; border-left: 0; padding-bottom: 14px; .children_box { border-left: 0; } } .opts_box { .opts_item { line-height: 38px; } } } } } } </style> ``` ### **三列表格(仅展示)** ``` <template> <div class="permission"> <el-checkbox-group :value="hasPermission" > <template v-for="(Ritem, Ridx) in allPermission"> <div class="check_item_box rflex" :key="Ritem[allPermissionDataType.code]" > <div class="parent_box border_box rflex flex_align_items_center"> <el-checkbox :label="Ritem[allPermissionDataType.code]" :readonly="true" > {{ Ritem[allPermissionDataType.name] }} </el-checkbox> </div> <div class="border_box cflex flex_1"> <div v-for="(Iitem, Iidx) in Ritem[allPermissionDataType.childList]" v-if="Array.isArray(Ritem[allPermissionDataType.childList]) && Ritem[allPermissionDataType.childList].length" class="border_box last_item_border_none rflex flex_1" > <div :key="Iitem[allPermissionDataType.code]" class="parent_box border_box rflex flex_align_items_center" > <div class="item_container"> <el-checkbox :label="Iitem[allPermissionDataType.label]" > {{ Iitem[allPermissionDataType.name] }} </el-checkbox> </div> </div> <div class="children_container rflex flex_wrap" v-if="Array.isArray(Iitem[allPermissionDataType.childList]) && Iitem[allPermissionDataType.childList].length" > <template v-for="(Sitem, Sidx) in Iitem[allPermissionDataType.childList]"> <div :key="Sitem[allPermissionDataType.code]" class="children_row" > <div class="item_container"> <el-checkbox :label="Sitem[allPermissionDataType.label]" > {{ Sitem[allPermissionDataType.name] }} </el-checkbox> </div> </div> </template> </div> </div> </div> </div> </template> </el-checkbox-group> </div> </template> <script> export default { name: "permissionTable", props: { /** * 所有权限数据 * 格式 * [ * { * name: String, //名称 * label: String, //选中标识 * code: String | Number, // 标识 * childList: [], // 子数据 * }, * ... * ] */ allPermission: { type: Array, default: () => [], }, /** * 已有权限数据 * 格式 * [ * String | Number, // 标识 * ... * ] */ hasPermission: { type: Array, default: () => [], }, /** * 所有权限数据key */ allPermissionDataType: { type: Object, default: () => ({ name: "name", label: "label", code: "code", childList: "childList", }) } }, data() { return {} }, } </script> <style scoped lang="scss"> .permission { font-size: 14px; color: #656b7b; .check_item_box { border: 1px solid #EBEEF5; border-bottom: 0; &:nth-last-child(1) { border-bottom: 1px solid #EBEEF5; } .parent_box { width: 130px; min-height: 38px; border-right: 1px solid #EBEEF5; box-sizing: border-box; padding-left: 14px; overflow: hidden; } .border_box { border-bottom: 1px solid #EBEEF5; &.last_item_border_none:nth-last-child(1) { border-bottom: 0; } } .children_container { flex: 1; padding: 14px 0 0 10px; .children_row { .item_container { min-width: 120px; border-left: 0; padding-bottom: 14px; } .opts_box { .opts_item { line-height: 38px; } } } } } } </style> ```
Pre:
element-ui表单自定义常用验证
Next:
vue跨标签页共享sessionStorage
0
likes
4
Weibo
Wechat
Tencent Weibo
QQ Zone
RenRen
Submit
Sign in
to leave a comment.
No Leanote account?
Sign up now.
0
comments
More...
Table of content
No Leanote account? Sign up now.