1、效果
2、组件代码
<template>
<ul :class="'level'+level" class="tree-container">
<li v-for="(item, Index) in menuData" :id="item.menLevel === 1 ? `key${Index+2}` : ''" :key="item.menu_id" :class="'level'+item.menLevel" style="list-style: none;">
<div :class="'level'+ item.menLevel" class="tree-node-title">
<el-checkbox :value="item.isChecked === 1 ? true : false" :indeterminate="item.isIndeterminate" @change="nodeClick(item, Index)">
{{ item.menu_name }}
<!-- -level{{ item.menLevel }} -->
</el-checkbox>
</div>
<div :class="'level'+item.menLevel" class="tree-childnode-container ">
<CheckBox :menu-data="item.child" :level="item.menLevel" />
</div>
</li>
</ul>
</template>
<script>
export default {
name: 'CheckBox',
// props: ['menuData', 'level'],
props: {
menuData: {
type: Array,
default: function() {
return []
}
},
level: {
type: Number,
default: null
}
},
data() {
return {
checkedVal: []
}
},
created() {
},
mounted() {
},
methods: {
nodeClick(node, index) {
// 通过isChecked判断是否为选中状态
if (node.isChecked === 1) {
this.$set(node, 'isChecked', 0)
this.$set(node, 'isIndeterminate', false)
} else {
this.$set(node, 'isChecked', 1)
this.$set(node, 'isIndeterminate', false)
}
this.refreshAllParentNodes(this)
this.refreshAllSonNodes(this.$children[index], node.isChecked, node)
},
refreshAllSonNodes(node, status, item) {
// if (node && node.$children.length) {
item.child.map((meunItem, j) => {
this.$set(meunItem, 'isChecked', status)
this.$set(meunItem, 'isIndeterminate', false)
this.refreshAllSonNodes([], status, meunItem)
})
// }
},
refreshAllParentNodes(node) {
if (node) {
var status = 0
var nullCount = 0
var fullCount = 0
var isIndeterminate
var isIndeterminateCount = 0
if (node.menuData && node.$parent.menuData) {
node.menuData.map((meunItem, j) => {
if (typeof meunItem.isChecked === 'undefined') {
nullCount++
} else if (meunItem.isChecked === 0) {
nullCount++
} else if (meunItem.isChecked === 1) {
fullCount++
}
if (meunItem.isIndeterminate === true) {
isIndeterminateCount++
}
})
if (fullCount === node.menuData.length) {
// 该状态说明当前点击层级和兄弟层级都没选中,所以父级也是未选中状态
status = 1
} else {
// 该状态说明当前点击层级和兄弟层级只要有一个选中,父级也是选中状态
status = 0
}
if (fullCount > 0 && fullCount < node.menuData.length || isIndeterminateCount > 0) {
isIndeterminate = true
} else {
isIndeterminate = false
}
node.$parent.menuData.map(child => {
node.menuData.map((meunItem, j) => {
if (child.menu_id === meunItem.parent_id) {
// 根据父级id和子级的parentId是否相等,来确定当前点击的层级的父级是哪一个
this.$set(child, 'isChecked', status)
this.$set(child, 'isIndeterminate', isIndeterminate)
}
})
})
}
// 递归计算父级
this.refreshAllParentNodes(node.$parent)
}
}
}
}
</script>
<style lang="scss">
.tree-container {
$borderColor: #C6E2FF;
width: 100%;
padding: 0;
&.level3 {
display: flex;
flex-wrap: wrap;
& > .level4 {
width: 25%;
padding: 0 20px 0 40px;
.level5 {
// background:#f7ffff;
width: 25%;
padding: 0 20px 0 10px;
}
}
}
& > .level2 {
display: flex;
align-items: center;
border: 1px solid $borderColor;
line-height: 45px;
.tree-node-title {
&.level2 {
width: 160px;
text-align: center;
}
}
}
.level3 {
.level3 + .level3 {
border-top: 1px solid $borderColor;
}
}
.tree-node-title {
&.level3 {
background-color: #f2f2f2;
width: 100%;
padding: 0 20px;
}
&.level1 {
padding: 20px 0;
}
}
.level2 + .level2 {
border-top: none;
}
.tree-childnode-container {
width: 100%;
&.level2 {
border-left: 1px solid $borderColor;
}
}
input {
margin-right: 5px;
}
label {
cursor: pointer;
}
}
</style>
3、template
<tree-table :menu-data="menuList" :level="1" />
4、data
menuList: [
// {
// isChecked: 1,
// menLevel: 1,
// menu_id: 239,
// menu_name: '数据报表',
// parent_id: 0,
// child: [
// {
// isChecked: 1,
// menLevel: 2,
// menu_id: 262,
// menu_name: '经纪人每日汇报(简)',
// parent_id: 239,
// child: []
// },
// {
// isChecked: '',
// menLevel: 2,
// menu_id: 265,
// menu_name: '数据报表详情',
// parent_id: 239,
// child: []
// }
// ]
// }
],
odlMenu: [],
newMenu:[],
id:[]
5、methods
// 获取所有权限列表,用于渲染列表
getMenuList2() {
this.menuList = []
Users.getMenuData().then(res => {
this.menuList = this.changeData(res.data, 1)
})
.then(res => {
this.getRoleMenuAndUser()
})
},
//数据格式化
changeData(data, level) {
return data.map(item => {
const newItem = {
menu_id: item.id,
...item,
isChecked: null,
menLevel: level
}
if (item.child && Array.isArray(item.child) && item.child.length) {
newItem.child = this.changeData(item.child, level + 1)
} else {
newItem.child = []
}
return newItem
})
},
// 获取角色列表下 权限 列表
getRoleMenuAndUser() {
const params = {
id: this.params.id ? this.params.id : 1,
type: 1
}
this.odlMenu.splice(0)
System.getRoleMenuAndUser(params).then(res => {
res.data.forEach((item, index) => {
this.odlMenu.push(item.menu_id)
})
this.odlMenu.forEach(odl_menu_id => {
this.recursion(odl_menu_id, this.menuList)
})
})
},
// 判断是否选中
recursion(menu_id, data) {
for (let i = 0, len = data.length; i < len; i++) {
if (data[i].menu_id === menu_id) {
data[i].isChecked = 1
return
}
if (data[i].child) {
this.recursion(menu_id, data[i].child)
}
}
},
// 权限修改保存
save() {
const newMenuArr = this.getId(this.menuList)
// 添加角色权限关联
this.newMenu = Array.from(new Set(newMenuArr))
const pramas = {
menu_id: this.newMenu,
id: this.params.id
}
System.saveRoleToMenuRelation(pramas).then(res => {
this.$message({
type: 'success',
message: '权限数据保存成功'
})
this.getRoleMenuAndUser()
})
},
//获取需要传给后端的id
getId(data, result = []) {
data.forEach(item => {
if (item.isChecked === 1 || item.isIndeterminate) {
result.push(item.menu_id, item.parent_id)
}
if (item.child && Array.isArray(item.child) && item.child.length) {
this.getId(item.child, result)
}
})
return result
},
6.mounted
mounted() {
this.getMenuList2()
},