2025-11-20更新----------------
新增点击节点路径高亮功能,可以在我的gitee库中看示例,
代码拉下来pnpm i, pnpm run serve
https://gitee.com/zrr89/zrr-org-tree
2025-11-20更新完毕----------------
用js写的,主要用的h函数渲染,文件目录(图如下),放到components可直接当作组件调用

org-tree.vue
<template>
<div class="org-tree-container outBox">
<div
class="org-tree"
:class="{ horizontal, collapsable }"
v-drag
id="ddd"
:style="{ transform: `scale(${zoomFactor})` }"
@mousewheel.prevent="handleWheel"
>
<org-tree-node
:data="data"
:props="props"
:zoomFactor="zoomFactor"
:horizontal="horizontal"
:label-width="labelWidth"
:collapsable="collapsable"
:render-content="renderContent"
:label-class-name="labelClassName"
@on-expand="(e, data) => $emit('on-expand', e, data)"
@on-expand-mouseover="
(e, data) => $emit('on-expand-mouseover', e, data)
"
@on-expand-mouseout="(e, data) => $emit('on-expand-mouseout', e, data)"
@on-node-click="
(e, data) => {
$emit('on-node-click', e, data);
}
"
@on-node-mouseover="(e, data) => $emit('on-node-mouseover', e, data)"
@on-node-mouseout="(e, data) => $emit('on-node-mouseout', e, data)"
/>
</div>
</div>
</template>
<script>
import render from "./node";
export default {
name: "OrgTree",
components: {
OrgTreeNode: {
render,
functional: true,
},
},
data() {
return {
zoom: this.zoomFactor,
};
},
props: {
data: {
type: Object,
required: true,
},
props: {
type: Object,
default: () => ({
label: "deviceName",
expand: "expand",
childNodeList: "childNodeList",
}),
},
zoomFactor: Number,
horizontal: Boolean,
collapsable: Boolean,
renderContent: Function,
labelWidth: [String, Number],
labelClassName: [Function, String],
},
directives: {
drag: {
// 以下代码大家可以自己提出去封装一下
inserted: function (el) {
el.style.cursor = "move";
let firstTime = "";
let lastTime = "";
el.onmousedown = function (e) {
let disx = e.pageX - el.offsetLeft;
let disy = e.pageY - el.offsetTop;
document.getElementById("ddd").setAttribute("data-flag", false);
firstTime = new Date().getTime();
document.onmousemove = function (e) {
let x = e.pageX - disx;
let y = e.pageY - disy;
let maxX =
document.body.clientWidth -
parseInt(window.getComputedStyle(el).width);
let maxY =
document.body.clientHeight -
parseInt(window.getComputedStyle(el).height);
el.style.left = x + "px";
el.style.top = y + "px";
if (x < 0) {
x = 0;
} else if (x > maxX) {
x = maxX;
}
if (y < 0) {
y = 0;
} else if (y > maxY) {
y = maxY;
}
let et = e || window.event;
et.preventDefault();
};
document.onmouseup = function () {
lastTime = new Date().getTime();
if (lastTime - firstTime < 150) {
document.getElementById("ddd").setAttribute("data-flag", true);
}
document.onmousemove = document.onmouseup = null;
};
};
},
},
},
methods: {
handleWheel(event) {
this.zoom = this.zoomFactor;
event.preventDefault();
const delta = event.wheelDelta ? event.wheelDelta : -event.deltaY;
if (delta > 0) {
this.zoom = this.zoom + 0.05;
} else {
this.zoom = this.zoom > 0 ? this.zoom - 0.05 : 0;
}
this.$emit("on-mousewheel", this.zoom);
},
},
};
</script>
<style lang="less" scoped>
.outBox {
height: 100%;
width: 100%;
position: relative;
overflow: hidden;
}
#ddd {
width: 100%;
height: 100%;
position: absolute;
overflow: hidden;
}
.org-tree-container {
position: relative;
display: inline-block;
padding: 15px;
background-color: #fff;
}
.org-tree {
position: relative;
display: table;
text-align: center;
}
.org-tree:before,
.org-tree:after {
content: "";
display: table;
}
.org-tree:after {
clear: both;
}
.org-tree-node,
.org-tree-node-childNodeList {
position: relative;
margin: 0;
padding: 0;
list-style-type: none;
}
.org-tree-node:before,
.org-tree-node-childNodeList:before,
.org-tree-node:after,
.org-tree-node-childNodeList:after {
transition: all 0.35s;
}
.org-tree-node-label {
position: relative;
display: inline-block;
}
.org-tree-node-label .org-tree-node-label-inner {
text-align: center;
border-radius: 3px;
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
// tree节点不换行
// padding: 6px 20px;
// white-space: nowrap;
// tree节点换行
padding: 6px 10px;
width: 150px;
word-wrap: break-word;
}
.org-tree-node-btn {
position: absolute;
top: 100%;
left: 50%;
width: 20px;
height: 20px;
z-index: 10;
margin-left: -11px;
margin-top: 9px;
background-color: #fff;
border: 1px solid #ccc;
border-radius: 50%;
box-shadow: 0 0 2px rgba(0, 0, 0, 0.15);
cursor: pointer;
transition: all 0.35s ease;
}
.org-tree-node-btn:hover {
background-color: #e7e8e9;
transform: scale(1.15);
}
.org-tree-node-btn:before,
.org-tree-node-btn:after {
content: "";
position: absolute;
}
.org-tree-node-btn:before {
top: 50%;
left: 4px;
right: 4px;
height: 0;
border-top: 1px solid #ccc;
}
.org-tree-node-btn:after {
top: 4px;
left: 50%;
bottom: 4px;
width: 0;
border-left: 1px solid #ccc;
}
.org-tree-node-btn.expanded:after {
border: none;
}
.org-tree-node {
padding-top: 20px;
display: table-cell;
vertical-align: top;
}
.org-tree-node.is-leaf,
.org-tree-node.collapsed {
padding-left: 10px;
padding-right: 10px;
}
.org-tree-node:before,
.org-tree-node:after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 19px;
}
.org-tree-node:after {
left: 50%;
border-left: 1px solid #ddd;
}
.org-tree-node:not(:first-child):before,
.org-tree-node:not(:last-child):after {
border-top: 1px solid #ddd;
}
.collapsable .org-tree-node.collapsed {
padding-bottom: 30px;
}
.collapsable .org-tree-node.collapsed .org-tree-node-label:after {
content: "";
position: absolute;
top: 100%;
left: 0;
width: 50%;
height: 20px;
border-right: 1px solid #ddd;
}
.org-tree > .org-tree-node {
padding-top: 0;
}
.org-tree > .org-tree-node:after {
border-left: 0;
}
.org-tree-node-childNodeList {
padding-top: 20px;
display: table;
}
.org-tree-node-childNodeList:before {
content: "";
position: absolute;
top: 0;
left: 50%;
width: 0;
height: 20px;
border-left: 1px solid #ddd;
}
.org-tree-node-childNodeList:after {
content: "";
display: table;
clear: both;
}
.horizontal .org-tree-node {
display: table-cell;
float: none;
padding-top: 0;
padding-left: 20px;
}
.horizontal .org-tree-node.is-leaf,
.horizontal .org-tree-node.collapsed {
padding-top: 10px;
padding-bottom: 10px;
}
.horizontal .org-tree-node:before,
.horizontal .org-tree-node:after {
width: 19px;
height: 50%;
}
.horizontal .org-tree-node:after {
top: 50%;
left: 0;
border-left: 0;
}
.horizontal .org-tree-node:only-child:before {
top: 1px;
border-bottom: 1px solid #ddd;
}
.horizontal .org-tree-node:not(:first-child):before,
.horizontal .org-tree-node:not(:last-child):after {
border-top: 0;
border-left: 1px solid #ddd;
}
.horizontal .org-tree-node:not(:only-child):after {
border-top: 1px solid #ddd;
}
.horizontal .org-tree-node .org-tree-node-inner {
display: table;
}
.horizontal .org-tree-node-label {
display: table-cell;
vertical-align: middle;
}
.horizontal.collapsable .org-tree-node.collapsed {
padding-right: 30px;
}
.horizontal.collapsable .org-tree-node.collapsed .org-tree-node-label:after {
top: 0;
left: 100%;
width: 20px;
height: 50%;
border-right: 0;
border-bottom: 1px solid #ddd;
}
.horizontal .org-tree-node-btn {
top: 50%;
left: 100%;
margin-top: -11px;
margin-left: 9px;
}
.horizontal > .org-tree-node:only-child:before {
border-bottom: 0;
}
.horizontal .org-tree-node-childNodeList {
display: table-cell;
padding-top: 0;
padding-left: 20px;
}
.horizontal .org-tree-node-childNodeList:before {
top: 50%;
left: 0;
width: 20px;
height: 0;
border-left: 0;
border-top: 1px solid #ddd;
}
.horizontal .org-tree-node-childNodeList:after {
display: none;
}
.horizontal .org-tree-node-childNodeList > .org-tree-node {
display: block;
}
/* 第一层 */
.org-tree > .org-tree-node > .org-tree-node-label > .org-tree-node-label-inner {
display: flex;
position: relative;
justify-content: center;
color: #000;
background: #fff;
cursor: pointer;
user-select: none;
width: 150px;
height: 170px;
}
/* 2 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #36a4fd;
color: #fff;
}
/* 3 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #c2d4ff;
color: #4665b0;
}
/* 4 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #9dd4e9;
color: #4794b1;
}
/* 第5层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #e7f1fd;
color: #5b9be5;
}
/* 第6层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #fecece;
color: #f47171;
}
/* 第7层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #ffe4b4;
color: #dea540;
}
/* 第8层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #c8efef;
color: #76bebe;
}
/* 第9层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #e6d7f3;
color: #bd99dd;
}
/* 第10层 */
.org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-childNodeList
> .org-tree-node
> .org-tree-node-label
> .org-tree-node-label-inner {
background-color: #f4f7fe;
color: #9eb1dd;
}
/* 每层多.org-tree-node-childNodeList>.org-tree-node */
/* 节点.org-tree-node-label>.org-tree-node-label-inner*/
</style>
node.js
// 判断是否叶子节点
const isLeaf = (data, prop) => {
return !(Array.isArray(data[prop]) && data[prop].length > 0);
};
// console.info('Thank you for using vue-tree-color \nIf you have any questions about this plug-in, please contact me in the following ways \nWeChat: yanjiahui12345 \nWeChat official number: Web_Miao')
// 创建 node 节点
export const renderNode = (h, data, context) => {
const { props } = context;
const cls = ["org-tree-node"];
const childNodes = [];
const childNodeList = data[props.props.childNodeList];
if (isLeaf(data, props.props.childNodeList)) {
cls.push("is-leaf");
} else if (props.collapsable && !data[props.props.expand]) {
cls.push("collapsed");
}
childNodes.push(renderLabel(h, data, context));
if (!props.collapsable || data[props.props.expand]) {
childNodes.push(renderChildren(h, childNodeList, context));
}
return h(
"div",
{
domProps: {
className: cls.join(" "),
},
},
childNodes
);
};
// 创建展开折叠按钮
export const renderBtn = (h, data, { props, listeners }) => {
const expandHandler = listeners["on-expand"];
const expandMouseover = listeners["on-expand-mouseover"];
const expandMouseout = listeners["on-expand-mouseout"];
let cls = ["org-tree-node-btn"];
if (data[props.props.expand]) {
cls.push("expanded");
}
return h("span", {
domProps: {
className: cls.join(" "),
},
on: {
click: (e) => expandHandler && expandHandler(e, data),
mouseover: (e) => expandMouseover && expandMouseover(e, data),
mouseout: (e) => expandMouseout && expandMouseout(e, data),
},
});
};
// 创建 label 节点
export const renderLabel = (h, data, context) => {
const { props, listeners } = context;
const renderContent = props.renderContent;
// event handlers
const clickHandler = listeners["on-node-click"];
const mouseOverHandler = listeners["on-node-mouseover"];
const mouseOutHandler = listeners["on-node-mouseout"];
const childNodes = [];
if (typeof renderContent === "function") {
let vnode = renderContent(h, data);
let str = ``;
if (vnode.deviceNo) {
str = `${vnode.deviceName}<br/>${vnode.deviceNo}`;
} else {
str = `${vnode.deviceName}`;
}
vnode && childNodes.push(str);
}
if (props.collapsable && !isLeaf(data, props.props.childNodeList)) {
childNodes.push(renderBtn(h, data, context));
}
const cls = ["org-tree-node-label-inner"];
let {
labelWidth,
labelClassName,
selectedClassName,
selectedKey,
judge,
NodeClass,
} = props;
if (typeof labelWidth === "number") {
labelWidth += "px";
}
if (typeof labelClassName === "function") {
labelClassName = labelClassName(data);
}
labelClassName && cls.push(labelClassName);
// add selected class and key from props
if (typeof selectedClassName === "function") {
selectedClassName = selectedClassName(data);
}
selectedClassName &&
selectedKey &&
data[selectedKey] &&
cls.push(selectedClassName);
return h(
"div",
{
domProps: {
className: "org-tree-node-label",
},
},
[
h("div", {
domProps: {
className:
ChangeTheColor(data, judge, NodeClass) +
" org-tree-node-label-inner",
innerHTML: childNodes[0],
},
style: {
width: labelWidth,
},
on: {
click: (e) => clickHandler && clickHandler(e, data),
mouseover: (e) => mouseOverHandler && mouseOverHandler(e, data),
mouseout: (e) => mouseOutHandler && mouseOutHandler(e, data),
},
}),
childNodes[1],
]
);
};
function ChangeTheColor(e, judge, NodeClass) {
if (
judge !== "" &&
judge !== undefined &&
judge !== null &&
judge.swtich !== false
) {
for (var k in judge) {
var a = eval("e." + k);
if (NodeClass) {
for (let c = 0; c < NodeClass.length; c++) {
if (a === NodeClass[c]) return NodeClass[c];
else if (NodeClass.length - 1 == c) return "";
}
} else {
return "";
}
}
} else {
return "";
}
}
// 创建 node 子节点
export const renderChildren = (h, list, context) => {
if (Array.isArray(list) && list.length) {
const childNodeList = list.map((item) => {
return renderNode(h, item, context);
});
return h(
"div",
{
domProps: {
className: "org-tree-node-childNodeList",
},
},
childNodeList
);
}
return "";
};
export const render = (h, context) => {
const { props } = context;
return renderNode(h, props.data, context);
};
export default render;
index.js
import OrgTree from "./org-tree";
const install = (Vue) => {
if (install.installed) {
return;
}
install.installed = true;
Vue.component(OrgTree.name, OrgTree);
};
OrgTree.install = install;
if (typeof window !== "undefined" && window.Vue) {
window.Vue.use(OrgTree);
}
export default OrgTree;
调用方法:
index.vue
<template>
<div>
<!-- 查询工作栏 -->
<el-form
:model="queryParams"
ref="queryForm"
size="small"
:inline="true"
v-show="showSearch"
>
<el-form-item label="设备编号" prop="deviceNo">
<el-input
v-model="queryParams.deviceNo"
placeholder="请输入设备编号"
clearable
/>
</el-form-item>
<el-form-item label="设备名称" prop="deviceName">
<el-input
v-model="queryParams.deviceName"
placeholder="请输入设备名称"
clearable
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
class="search-button"
icon="el-icon-search"
@click="handleQuery"
>查询</el-button
>
<el-button
type="primary"
class="search-button"
icon="el-icon-refresh"
@click="resetQuery"
>重置</el-button
>
</el-form-item>
</el-form>
<div class="svg-content">
<div class="svg-header">
<div class="svg-header-legend"></div>
<div class="svg-header-scale">
<i @click="changeZoom(true)" class="el-icon-plus"></i>
<i class="number">{{ percent }}%</i>
<i @click="changeZoom(false)" class="el-icon-minus"></i>
</div>
</div>
<div class="svg-tree">
<org-tree
id="orgTreeNode"
:data="org"
:horizontal="horizontal"
:zoomFactor="zoomFactor"
collapsable
:render-content="renderContent"
@on-expand="onExpand"
@on-mousewheel="onMousewheel"
@on-node-mouseover="onMouseover"
@on-node-mouseout="onMouseout"
@on-expand-mouseover="Mouseover"
@on-expand-mouseout="Mouseout"
@on-node-click="cccc"
/>
<div
class="childNodeList-submenu"
ref="floating"
v-show="isShowF && bd"
@mouseover="isShowF = true"
@mouseout="isShowF = false"
@mousewheel.prevent="mouseWheelDia"
>
<div v-for="m in subList">
<span class="label">{{ m.label }}</span>
<span class="value" :title="subItem[m.value] || '暂无'">
{{ subItem[m.value] || "暂无" }}
{{ subItem[m.unit] || "" }}
</span>
</div>
<div class="more">查看更多</div>
</div>
</div>
</div>
</div>
</template>
<script>
import OrgTree from "@/components/org-tree";
export default {
name: "app",
components: {
OrgTree,
},
directives: {
focus: {
inserted: function (el) {
el.querySelector("input").focus();
},
},
},
data() {
return {
// 遮罩层
loading: true,
// 显示查询条件
showSearch: true,
// 查询参数
queryParams: {
deviceNo: "",
deviceName: "",
},
zoomFactor: 1,
bd: true,
isShowF: false,
org: {
deviceName: "主分支",
expand: true,
childNodeList: [],
},
defaultData: {},
subList: [
{ label: "名称", value: "deviceName" },
{ label: "读数", value: "lastNum", unit: "unitName" },
],
subItem: {},
horizontal: true,
collapsable: true,
labelClassName: "bg-white",
};
},
computed: {
percent() {
return Math.round(this.zoomFactor * 100);
},
},
mounted() {
this.org.childNodeList = [
{
deviceNo: "1",
deviceName: "设备1",
id: 1,
lastNum: 333.62,
unitName: "kWh",
childNodeList: [
{
deviceNo: "1-1",
deviceName: "设备1-1",
id: 2,
lastNum: 222.21,
unitName: "kWh",
childNodeList: [],
},
],
},
{
deviceNo: "2",
deviceName: "设备2",
id: 8,
lastNum: 44444.66,
unitName: "t",
childNodeList: [
{
deviceNo: "2-1",
deviceName: "设备2-1",
id: 10,
lastNum: 11.62,
unitName: "t",
childNodeList: [],
},
{
deviceNo: "2-2",
deviceName: "设备2-2",
id: 11,
lastNum: 2.03,
unitName: "t",
childNodeList: [],
},
{
deviceNo: "2-3",
deviceName: "设备2-3",
id: 12,
lastNum: 66.98,
unitName: "t",
childNodeList: [],
},
],
},
{
deviceNo: "3",
deviceName: "设备3",
id: 16,
lastNum: 3.34,
unitName: "kWh",
childNodeList: [],
},
];
this.toggleExpand(this.org.childNodeList, true); // 调用全部展开
// 默认数据存储
this.defaultData = this.org;
},
methods: {
handleQuery() {
this.org = { ...this.defaultData };
let list = this.filterTreeLabel(
this.org.childNodeList,
this.queryParams.deviceName,
this.queryParams.deviceNo
);
this.org.childNodeList = list;
this.org.expand = true;
this.toggleExpand(this.org.childNodeList, true); // 调用全部展开
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm("queryForm");
this.handleQuery();
},
renderContent(h, data) {
return {
deviceName: data.deviceName,
deviceNo: data.deviceNo,
};
},
filterTreeLabel(arr, deviceName, deviceNo) {
let result = [];
arr.forEach((m) => {
if (
String(m.deviceName).toLowerCase().includes(deviceName) &&
String(m.deviceNo).toLowerCase().includes(deviceNo)
) {
result.push(m);
} else {
if (m.childNodeList && m.childNodeList.length) {
let childNodeList = this.filterTreeLabel(
m.childNodeList,
deviceName,
deviceNo
);
let obj = { ...m, childNodeList };
if (childNodeList && childNodeList.length) {
result.push(obj);
}
}
}
});
return result;
},
changeZoom(delta) {
if (delta) {
// 向上滚动,放大
this.zoomFactor += 0.05;
} else {
// 向下滚动,缩小
this.zoomFactor = this.zoomFactor > 0 ? this.zoomFactor - 0.05 : 0;
}
},
cccc(a, b) {
// console.log(a);
// console.log(b);
},
mouseWheelDia() {
this.isShowF = false;
},
Mouseover() {
// 鼠标移入缩放icon
this.bd = false;
},
Mouseout() {
// 鼠标移出缩放icon
this.bd = true;
},
onMouseover(e, data) {
if (data.deviceNo) {
// 鼠标移入树节点
this.subItem = data; // 鼠标移入,该节点的所有数据
this.isShowF = true;
let floating = this.$refs.floating;
// 调整悬浮框位置 e.clientX - 100
floating.style.left = e.clientX + "px";
floating.style.top = e.clientY + "px";
}
},
onMouseout(e, data) {
// 鼠标移出树节点
this.isShowF = false;
},
onExpand(e, data) {
// 节点展开收缩
if (data.leave == 1 && data.expand == true) {
let dom = document.getElementById("ddd");
dom.style.top = "50%";
dom.style.left = "8%";
}
if ("expand" in data) {
data.expand = !data.expand;
if (!data.expand && data.childNodeList) {
this.collapse(data.childNodeList);
}
} else {
this.$set(data, "expand", true);
}
},
collapse(list) {
list.forEach((child) => {
if (child.expand) {
child.expand = false;
}
child.childNodeList && this.collapse(child.childNodeList);
});
},
toggleExpand(data, val) {
// 节点默认全部展开
let _this = this;
if (Array.isArray(data)) {
data.forEach(function (item) {
_this.$set(item, "expand", val);
if (item.childNodeList) {
_this.toggleExpand(item.childNodeList, val);
}
});
} else {
this.$set(data, "expand", val);
if (data.childNodeList) {
_this.toggleExpand(data.childNodeList, val);
}
}
},
onMousewheel(data) {
this.zoomFactor = data;
},
},
};
</script>
<style lang="scss" scoped>
.svg-content {
margin: 20px;
padding: 20px;
background-color: #fff;
user-select: none;
p {
margin: 0;
padding: 0;
}
.svg-header {
display: flex;
justify-content: space-between;
.svg-header-legend {
}
.svg-header-scale {
display: flex;
align-items: center;
padding: 10px 20px;
border: 1px solid #15dbf5;
border-radius: 12px;
background-color: #132f6c;
i {
color: #15dbf5;
font-weight: 600;
cursor: pointer;
user-select: none;
display: inline-block;
font-style: normal;
}
.number {
color: #fff;
text-align: center;
width: 50px;
}
}
}
.svg-tree {
position: relative;
font-size: 14px;
width: 100%;
height: calc(100vh - 320px);
}
}
.childNodeList-submenu {
position: absolute;
width: 200px;
height: 200px;
left: 0;
top: 0;
background-color: rgba($color: #000, $alpha: 0.8);
color: #fff;
font-size: 14px;
border-radius: 10px;
padding: 16px;
border: 1px solid #132f6c;
font-weight: 600;
> div {
padding-top: 8px;
display: flex;
}
span {
display: inline-block;
}
.label {
width: 38%;
color: #15dbf5;
margin-right: 5px;
}
.value {
width: 60%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.more {
text-align: center;
justify-content: center;
color: red;
}
}
</style>
<style lang="scss">
.addOrEditDia,
.delDia {
padding: 14px 18px 10px 18px;
border-radius: 4px !important;
.el-dialog__header {
display: flex;
justify-content: space-between;
}
.el-dialog__body {
margin-top: 37px;
}
.el-dialog__footer {
padding: 27px 0 9px 0 !important;
}
.el-dialog__headerbtn {
position: static !important;
}
}
.bg-white {
background-color: white;
}
.bg-orange {
background-color: orange;
}
.bg-gold {
background-color: gold;
}
.bg-gray {
background-color: gray;
}
.bg-lightpink {
background-color: lightpink;
}
.bg-chocolate {
background-color: chocolate;
}
.bg-tomato {
background-color: tomato;
}
</style>
跟原版差别在于不能编辑删除,可直接从原创代码复制过来
原创指路: vue实现可新增、编辑、删除、拖拽、缩放、纵横的树形tree结构_vue思维导图插件可新增删除拖拽-CSDN博客


9402

被折叠的 条评论
为什么被折叠?



