效果图如下:
一、需求要求:
1、勾选左侧的功能资源,点击【添加】,可将内容添加到右侧,并且左侧勾选的数据删除;勾选右侧的已选资源,效果同左侧一样;
2、勾选全选,则资源全部添加到右侧,左侧的则显示为空
二、代码如下:
<div>
<el-row>
<el-col :span="12">
<div class="transfer-box">
<div class="transfer-box-header">
<el-checkbox @change="getLeftValue" v-model="leftCheck" ><b>可分配的功能资源</b></el-checkbox>
<div style="float:right; margin-right:10px"><el-button type="success" size="small" @click="add">添加<i class="el-icon-arrow-right el-icon--right"></i></el-button></div>
</div>
<div class="transfer-box-content">
<el-tree
:data="data"
show-checkbox
node-key="resId"
ref="tree"
:expand-on-click-node="false"
:props="defaultProps">
</el-tree>
</div>
</div>
</el-col>
<el-col :span="12">
<div class="transfer-box">
<div class="transfer-box-header">
<el-checkbox @change="getRightValue" v-model="rightCheck"><b>已选择的功能资源</b></el-checkbox>
<div style="float:right; margin-right:10px"><el-button type="success" icon="el-icon-arrow-left" size="small" @click="del">移除</el-button></div>
</div>
<div class="transfer-box-content">
<el-tree
:data="targetData"
show-checkbox
node-key="resId"
:expand-on-click-node="false"
default-expand-all
:props="defaultProps"
ref="treeRight"
>
</el-tree>
</div>
</div>
</el-col>
</el-row>
</div>
1、先给el-tree绑定显示定义
data() {
return {
perId:'',
btnLoading:false,
selectedResRows:[],
leftCheck:'',
rightCheck:'',
data:[],
defaultProps: {
children: 'children',//子集
label: 'resName'//显示的文本
},
targetData: [],
getNodeId:[],//初始化时获取所有勾选的id
};
},
2、实现左右移除的功能
<script>
function recursion(obj, cb) {
if (Array.isArray(obj) && obj.length > 0) {
for (const item of obj) {
if (item.children) recursion(item.children, cb);
typeof cb == "function" && cb(obj, item);
}
}
}
export default {
methods: {
getLeftValue(val){
console.log(val)
if(val){
this.$refs.tree.setCheckedNodes(this.data)
}
else{
this.$refs.tree.setCheckedKeys([])
}
},
getRightValue(val){
if(val){
this.$refs.treeRight.setCheckedNodes(this.targetData)
}
else{
this.$refs.treeRight.setCheckedKeys([])
}
},
getTop(){
let param={
perId:this.perId
}
this.$api.per.getPerDetail(param).then(res => {
if (res.data.code == "0") {
this.topInfo = res.data.data;
this.getAllResTreeList(this.topInfo.mdcKey)
}
})
.catch(error => {
});
},
//获取所有菜单信息
getAllResTreeList(mdcKey){
this.$api.resource.selectMenuTreeByMdcKey({mdcKey:mdcKey}).then(res => {
if(res.data.code == '0'){
this.data = res.data.data
this.getPerBindResList()
}else{
this.$message({
type: 'error',
message: res.data.msg
});
}
})
},
add() {
let selectedKeysLeft = this.$refs.tree.getCheckedKeys();//获取勾选的,不包含父级id
let selectedNodesLeft = this.$refs.tree.getCheckedNodes(false, true);//获取所有勾选的node
if(selectedKeysLeft.length>0){
//复制选择的元素
this.handleData(selectedKeysLeft,selectedNodesLeft,this.targetData,this.data);
//重置选择
this.$refs.tree.setCheckedKeys([]);
this.leftCheck=false;
this.rightCheck=false;
}
else{
this.$message.info('请先勾选数据')
}
},
del() {
let selectedKeysRight = this.$refs.treeRight.getCheckedKeys();//获取勾选的,不包含父级id
let selectedNodesRight = this.$refs.treeRight.getCheckedNodes(false, true);//获取所有勾选的node
if(selectedKeysRight.length>0){
this.handleData(selectedKeysRight,selectedNodesRight,this.data,this.targetData);
//重置选择
this.$refs.treeRight.setCheckedKeys([]);
this.rightCheck=false;
this.leftCheck=false;
}
else{
this.$message.info('请先勾选数据')
}
},
/**
*selectedKeys参数为勾选的id,不包含半勾选
selectedNodes参数为获取所有勾选的node
targetData参数为操作后获得的结果数据
data参数为需要操作勾选的源数据 **/
handleData(selectedKeys,selectedNodes,targetData,data){
selectedNodes.forEach((nodes) => {
let parentNode;
recursion(targetData, function(obj, item) {
//寻找要插入的元素的父节点是否存在
if (nodes.resParentid == item.resId) parentNode = item;
});
//初始化要插入的节点数据
let nodeObj = {
resId: nodes.resId,
resName: nodes.resName,
resParentid:nodes.resParentid,
};
nodes.resParentid && (nodeObj.nodeObj = nodes.resParentid);
nodes.children && (nodeObj.children = []);
//如果找到父节点,那么代表是子节点,没有找到那么就是一级节点。
if (parentNode) {
//判断父节点是否已经存在这个节点。如果不存在就插入
if (
!parentNode.children.find((item) => item.resId == nodes.resId)
)
parentNode.children.push(nodeObj);
} else {
//一级节点需要在顶层数组里插入
if (!targetData.find((item) => item.resId == nodes.resId))
targetData.push(nodeObj);
}
});
//删除选中的元素
recursion(data, function(obj, item) {
selectedKeys.forEach((delItem) => {
//找到选中的元素删除
let index = obj.findIndex((findItem) => {
return delItem == findItem.resId;
});
index > -1 && obj.splice(index, 1);
});
});
},
},
created() {
this.getTop();
}
};
</script>
3、保存后点击编辑,左侧显示未分配的资源,右侧显示已分配的资源
后台给到的数据是:所有的资源(多维数组)和已分配的资源(一维数组,包含(半勾选)父级数据)
//获取所有菜单信息
getAllResTreeList(mdcKey){
this.$api.resource.selectMenuTreeByMdcKey({mdcKey:mdcKey}).then(res => {
if(res.data.code == '0'){
this.data = res.data.data
this.getPerBindResList()
}else{
this.$message({
type: 'error',
message: res.data.msg
});
}
})
},
//获取当前权限绑定资源信息,一维数组
getPerBindResList(){
let that = this
this.$api.per.selectResListByPerId({perId:this.perId}).then(res => {
if(res.data.code == '0'){
that.selectedResRows = res.data.data
that.selectedResRows.forEach((n) => {
//获取tree中的节点
var node = that.$refs.tree.getNode(n);
if (node.isLeaf) {
//获取勾选状态的数据
//that.getNodeId.push(node.data.resId)
//设置某个节点的勾选状态
that.$refs.tree.setChecked(node, true);
}
})
}
let selectedKeys = this.$refs.tree.getCheckedKeys();//获取勾选的,不包含父级id
let selectedNodes = this.$refs.tree.getCheckedNodes(false, true);//获取所有勾选的node
this.handleData(selectedKeys,selectedNodes,that.targetData,that.data);
//重新渲染el-tree
this.data = [...this.data]
})
},