需求背景:角色管理资源,资源返回树形结构数据,左侧树形展示列表可查询,右侧勾选资源权限平铺。
本身组件不支持全选,所以增加了全选按钮。覆写了级联面板宽度。可传只勾选code或者顺序当前节点二维数组列表。
效果
因未配置id报错
<div v-if="dataValueOptions.length" style="height: 32px; line-height 32px; display: flex; align-items: center; border: 1px solid #E4E7ED; border-radius: 4px;">
<el-checkbox v-model="isAllSelected" @change="handleAllSelectedChange" style=" margin-left: 20px;">全选</el-checkbox>
</div>
<el-cascader-panel
v-if="dataValueOptions.length"
id="cascaderPanel" 一定要有防止动态生成时,组件报错 option.level 找不到
ref="cascaderPanel"
v-model="selectedValues"
:key="cascaderPanelKey"
:options="dataValueOptions"
:props="{
expandTrigger: 'click',
checkStrictly: false,
multiple: isMultiple,
emitPath: false, 决定勾选以及初始化选中数据结果
value: 'code',
label: 'name',
}"
@change="handleSelected"
placeholder="请选择"
style="width: 100%; height: 400px; overflow-x: auto;"
:filter-method="dataFilter"
filterable
>
<template slot-scope="{ node, data }">
<span v-if="data.name" >{{ `${data.name}` }}</span>
</template>
</el-cascader-panel>
<div v-else style="text-align: center; padding-top: 50px;">暂无数据</div>
</div>
return {
relations: [{
content: '角色'
}, {
content: '应用',
}],
sureLoad: false,
roleInfo: {},
leftLoad: false,
selectApp: {},
appName: "",
appList: [],
defaultExpandKeys: [],
defaultProps: {
children: 'children',
label: 'name'
},
searchLoad: false,
resourceList: [],
rightLoad: false,
isMultiple: true,
selectedValues: [],
dataValueOptions: [],
isAllSelected: false,
cascaderPanelKey: ""
}
// 存储初始化勾选的资源
initSelectedCodes(data) {
for (let i = 0; i < data.length; i++) {
const node = data[i]
if (node.selected) {
this.selectedValues.push(node.code)
}
if (node.children) {
this.initSelectedCodes(node.children)
}
}
},
getAppResourceTree(appId) {
this.rightLoad = true
const params = {
appId: appId,
roleCode: this.roleInfo.code
}
this.$api.getResourceTreeByAppId(params).then(res => {
this.rightLoad = false
if (res.code === '0') {
// 左侧级联选择器默认数据
this.dataValueOptions = res.result
// 动态设置key值防止报level错误
this.cascaderPanelKey = Date.now()
// 级联选择器默认选中数据
if (this.dataValueOptions.length) {
this.initSelectedCodes(this.dataValueOptions)
// 数据初始化完成且组件已渲染
this.$nextTick(() => {
this.handleSelected()
})
}
}
}).catch((err) => {
this.$message.error(err)
this.rightLoad = false
})
},
handleSelected() {
if (this.dataValueOptions.length) {
// 获取所有codes,如果长度跟选中长度一致说明是全选,否则部分选中
const codes = []
this.getAllCodes(this.dataValueOptions, codes)
if (this.$refs.cascaderPanel && this.selectedValues && this.selectedValues.length) {
this.isAllSelected = codes.length === this.$refs.cascaderPanel.getCheckedNodes().length
}
}
},
dataFilter(node, val){
const baseName = node.data.baseName.toUpperCase()
const baseValue = node.data.baseValue.toUpperCase()
const inputVal = val.toUpperCase()
if(baseName.indexOf(inputVal) !== -1 || baseValue.indexOf(inputVal) !== -1){
return true
}
}
resetQuery() {
this.isAllSelected = false
this.appName = ""
this.resourceList = []
this.selectedValues = []
this.dataValueOptions = []
this.getAppList()
}
// 额外方法,如果后台需要勾选的节点的所有顺序父节点包括勾选的节点
findParentCodes(treeData, selectedCode, parentCodes = []) {
for (let i = 0; i < treeData.length; i++) {
const node = treeData[i]
if (node.code === selectedCode) {
return [...parentCodes, node.code]
}
if (node.children) {
const result = this.findParentCodes(node.children, selectedCode, [...parentCodes, node.code])
if (result) {
return result
}
}
}
return null;
}
方法使用。
for (let i = 0; i < this.selectedRootCodes.length; i++) {
const selectedRootCode = this.selectedRootCodes[i]
if (selectedRootCode) {
const selectedCodes = this.findParentCodes(this.dataValueOptions, selectedRootCode)
if (selectedCodes.length) {
this.selectedValues.push(selectedCodes)
}
}
}
/* 自定义面板样式 */
#right .el-cascader-menu__wrap,
#right .el-scrollbar__wrap {
overflow-x: auto;
overflow-y: hidden;
height: 404px;
margin-right: 0px !important;
}