element-ui树形组件实现懒加载、右键新增、右键删除、右键编辑,以及拖拽更换节点_JSON

<template>
<el-card shadow="never" class="aui-card--fill">
<div class="tree-box">
<div class="tree-title">
<el-input placeholder="输入关键字进行过滤" v-model.trim="tree.filterText" size="small"></el-input>
</div>
<div class="tree-content" v-loading="tree.loading">

<div v-if="position=='page'" style="position:relative">
<span style="position:absolute;z-index:2;top:6px;right:3px;font-size:12px;color:#9c9b9b">(右键可编辑视频树形分类)</span>
</div>
<el-tree
class="filter-tree"
:load="loadNode"
lazy
:draggable="$hasPermission('video:video-manage:dragclass')"
@node-expand="handleNodeExpand"
@node-collapse="handleNodeCollapse"
:default-expanded-keys="tree.expandedKeys"
node-key="id"
:highlight-current="highlightCurrent"
:props="tree.defaultProps"
:expand-on-click-node="false"
:filter-node-method="filterNode"
@node-click="hadleNodeClick"
@node-contextmenu="rihgtClick"
@node-drop="handleDrop"
:allow-drop="allowDrop"
:allow-drag="allowDrag"
ref="tree"
></el-tree>
<div v-show="menuVisible" id="rightClickMenu">
<ul class="menu-list">
<li>
<el-button
type="text"
size="small"
@click="NodeConfig('add')"
v-if="$hasPermission('video:video-manage:addclass')"
>新增子分类</el-button>
</li>
<li>
<el-button
type="text"
size="small"
:disabled="DATA&&DATA.id=='1270550715957256193'"
@click="NodeDel()"
v-if="$hasPermission('video:video-manage:deleteclass')"
>删除分类</el-button>
</li>
<li>
<el-button
type="text"
size="small"
:disabled="DATA&&DATA.id=='1270550715957256193'"
@click="NodeConfig('edit')"
v-if="$hasPermission('video:video-manage:editclass')"
>编辑分类</el-button>
</li>
</ul>
</div>
</div>
</div>
<videoConfig ref="videoConfig" @updateTree="updateTree" />
</el-card>
</template>
<script>
import videoConfig from "@/components/video/model-videoClass-config";
import debounce from "lodash/debounce";
export default {
name: "",
components: {
videoConfig,
},
props: {
currentKey: {
type: String,
default: "",
},
position: {
type: String,
default: "page",
},
isSelect: {
type: Boolean,
default: false,
},
},
data() {
return {
configType: "",
menuVisible: false,
objectID: "",
DATA: null,
VALUE: null,
highlightCurrent: true,
tree: {
data: [],
expandedKeys: ['1270550715957256193'],/**设置默认展开的节点,此时必须设置node-key,其值为节点数据中的一个字段名,该字段在整棵树中是唯一的。 */
node: null,
resolve: null,
loading: false,
filterText: "",
defaultProps: {
children: "children",
label: "name",
isLeaf: "isLeaf",
},
},
};
},
watch: {
"tree.filterText"(val) {
this.$refs.tree.filter(val);
},
},
computed: {
dataRule() {
return {
name: [
{
required: true,
message: this.$t("validate.required"),
trigger: "blur",
},
],
};
},
enabledConfig() {
return (
this.$hasPermission("video:video-manage:addclass") ||
this.$hasPermission("video:video-manage:editclass") ||
this.$hasPermission("video:video-manage:deleteclass")
);
},
},
created() {},
mounted() {},
methods: {
//懒加载
async loadNode(node, resolve) {
if (node.level === 0) {
this.tree.node = node;
this.tree.resolve = resolve;
let rootData = [
{ id: "1270550715957256193", name: "视频分类", parentId: null ,children:[]},
];
this.tree.expandedKeys = [rootData[0].id];
resolve(rootData);
this.$nextTick(() => {
this.$refs["tree"].setCurrentKey("1270550715957256193");
this.$emit("updateTreeItem", rootData[0]);
});
} else {
let ndoeData = await this.loadTreeData(node.data.id);
resolve(ndoeData);
}
if (this.currentKey) {
this.reShowHighlight();
}
},
//高亮其中一项
reShowHighlight() {
this.$nextTick(() => {
this.$refs.tree.setCurrentKey(this.currentKey);
});
},
//加载树形数据
loadTreeData(parentId) {
return new Promise((resolve, reject) => {
this.$http
.get("/vod/mrcategory/list", {
params: {
parentId: parentId,
selectChildList: 0,
},
})
.then(({ data: res }) => {
resolve(res.data);
})
.catch((er) => {
reject(er);
});
});
},
// 搜索
filterNode(value, data) {
if (!value) return true;
return data.name.indexOf(value) !== -1;
},
// 右击
rihgtClick(event, object, node, element) {
if (
this.position === "modal" ||
!(
this.$hasPermission("video:video-manage:addclass") ||
this.$hasPermission("video:video-manage:editclass") ||
this.$hasPermission("video:video-manage:deleteclass")
)
) {
return;
}

if (this.objectID !== object.id) {
this.objectID = object.id;
this.menuVisible = true;
this.DATA = object;//该节点所对应的对象
this.NODE = node;//该节点所对应的node
const parent = this.NODE.parent;
// this.$refs.tree.append(({ name: this.dataForm.name }, object));
} else {
this.menuVisible = !this.menuVisible;
}
document.addEventListener("click", (e) => {
this.menuVisible = false;
});
let menu = document.querySelector("#rightClickMenu");
/* 菜单定位基于鼠标点击位置 */
menu.style.left = event.offsetX + 50 + "px";
menu.style.top = event.offsetY + 50 + "px";
// menu.style.left = event.clientX + 30 + "px";
// menu.style.top = event.clientY + 30 + "px";
},
// 点击树的item
hadleNodeClick(data, node) {
this.menuVisible = false;
if (
this.position == "modal" &&
data.name == "视频分类" &&
this.isSelect
) {
this.highlightCurrent = false;
this.$emit("updateTreeItem", {
id: "",
name: "",
parentId: null,
});
} else {
this.highlightCurrent = true;
this.$emit("updateTreeItem", data);
}
},
// 树展开某一节点的时候
handleNodeExpand(data, node, ele) {
this.$set(ele, "expanded", true);
if (node.expanded) {
this.tree.expandedKeys.push(data.id);
this.tree.expandedKeys = Array.from(new Set(this.tree.expandedKeys));//去重
}
},
// 树关闭某一节点的时候
handleNodeCollapse(data, node, ele) {
let index = this.tree.expandedKeys.findIndex((item) => item === data.id);
if (index !== -1) {
this.tree.expandedKeys.splice(index, 1);
}
this.$set(ele, "expanded", false);//需要手动折叠当前节点
},
NodeConfig(type) {
this.configType = type;
if (type === "add") {
this.$refs.videoConfig.initModal({ parentId: this.DATA.id });
} else {
let data = JSON.parse(JSON.stringify(this.DATA));
this.$refs.videoConfig.initModal(data);
}
},
//新增或者编辑的回调
updateTree(data) {
if (this.configType === "edit") {
this.$set(this.DATA, "name", data.name);
} else {
if (!this.DATA.children) {
this.$set(this.DATA, "children", []);
}
this.$nextTick(() => {
this.DATA.children.push(data);
});
}
},
//删除
NodeDel() {
this.$confirm(
this.$t("prompt.info", { handle: this.$t("delete") }),
this.$t("prompt.title"),
{
confirmButtonText: this.$t("confirm"),
cancelButtonText: this.$t("cancel"),
type: "warning",
}
)
.then(() => {
this.$http
.delete("/vod/mrcategory", {
data: [this.DATA.id],
})
.then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg);
}
this.$message({
message: this.$t("prompt.success"),
type: "success",
duration: 500,
onClose: () => {
// let node = this.$refs.tree.getNode(this.DATA.parentId);
// node.loaded = false;
// node.expand();
// const parent = this.NODE.parent;
// const children = parent.data.children || parent.data;
// const index = children.findIndex(d => d.id === this.DATA.id);
// children.splice(index, 1);
this.$refs.tree.remove(this.NODE);
},
});
})
.catch(() => {});
})
.catch(() => {});
},
//拖拽执行的更新方法
handleDrop(draggingNode, dropNode, dropType, ev) {
this.$http["put"]("/vod/mrcategory", {
name: draggingNode.data.name,
id: draggingNode.data.id,
parentId:
dropType === "inner" ? dropNode.data.id : dropNode.data.parentId,
})
.then(({ data: res }) => {
if (res.code !== 0) {
return this.$message.error(res.msg);
}
this.$message({
message: this.$t("prompt.success"),
type: "success",
duration: 500,
onClose: () => {},
});
})
.catch(() => {});
},
//允许被扔放的节点
allowDrop(draggingNode, dropNode, type) {
return dropNode.data.id !== "1270550715957256193";
// if (dropNode.data.id === "1270550715957256193") {
// return type !== "before";
// } else {
// return true;
// }
},
//允许拖拽的节点
allowDrag(draggingNode) {
return draggingNode.data.id !== "1270550715957256193";
},
},
destroyed() {},
};
</script>
<style lang='scss'>
#video-manage {
.el-tree__empty-block{
margin-top: 100px;
}
.tree-box {
.tree-title {
margin-bottom: 10px;
}
.tree-content {
height: calc(100vh - 50px - 38px - 30px - 40px - 42px);
overflow: auto;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
&::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 8px;
}
&::-webkit-scrollbar-track-piece {
/*内层轨道,滚动条中间部分(位置4)*/
border-radius: 2px 2px 0px 0px;
}
&::-webkit-scrollbar-thumb {
background: #c1c1c1;
border-radius: 6px;
}
&::-webkit-scrollbar-thumb:hover {
background: #aba8a8;
}
&::-webkit-scrollbar-corner {
background: #f6f6f6;
}


#rightClickMenu {
background: #fff;
position: absolute;
z-index: 3;
transform-origin: left center;
width: 100px;
height: 150px;
padding: 10px;
border-radius: 5px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
ul {
li {
.el-button {
width: 100%;
text-align: left;
}
}
}
}
}
}
}
</style>