实现流程图,借鉴vue-tree-color
引入依赖
npm install vue-tree-color
同时查看项目中是否已安装less和less-loader,因为该组件使用到less
npm install --save-dev less less-loader
如果这里启动项目报错,有可能是less和less-loader的版本过高,可以降低版本,或者指定版本号
npm i less@3.9.0 less-loader@4.1.0 -D
添加全局
import Vue2OrgTree from 'vue-tree-color'
Vue.use(Vue2OrgTree)
目录结构
index copy.vue
<template>
<!-- 组织架构 -->
<div ref="appContainer" class="app-container">
<div style="margin-left: 30px">
<el-row :gutter="20">
<el-col :span="5">
<el-switch
v-model="horizontal"
:width="50"
active-text="横排"
inactive-text="竖排"
style="margin-top: 8px"
/>
</el-col>
<el-col :span="5">
<el-switch
v-model="expandAll"
:width="50"
active-text="全部展开"
inactive-text="全部折叠"
style="margin: 8px"
@change="expandChange"
/>
</el-col>
</el-row>
</div>
<div style="font-size: 12px; margin-top: 30px">
<el-scrollbar :style="scrollTreeStyle" class="el-org-tree">
<vue2-org-tree
:data="treeData.data"
:horizontal="!horizontal"
:collapsable="collapsable"
:label-class-name="treeData.labelClassName"
:render-content="renderContent"
name="organ"
@on-expand="onExpand"
@on-node-click="onNodeClick"
/>
</el-scrollbar>
</div>
<br /><br />
</div>
</template>
<script>
export default {
name: "TreeTest",
data() {
return {
treeData: {
labelClassName: "bg-color-orange",
basicInfo: { id: null, label: "---null" },
basicSwitch: false,
data: {
id: 0,
label: "XXX科技有限公司",
children: [
{
id: 2,
label: "产品研发部",
children: [
{
id: 5,
label: "研发-前端",
children: [
{
id: 55,
label: "前端1",
},
{
id: 56,
label: "前端2",
},
{
id: 57,
label: "前端3",
},
{
id: 58,
label: "前端4",
},
],
},
{
id: 6,
label: "研发-后端",
},
{
id: 9,
label: "UI设计",
},
{
id: 10,
label: "产品经理",
},
],
},
{
id: 3,
label: "销售部",
children: [
{
id: 7,
label: "销售一部",
},
{
id: 8,
label: "销售二部",
},
],
},
{
id: 4,
label: "财务部",
},
{
id: 9,
label: "HR人事",
},
],
},
},
horizontal: true, //横版 竖版
collapsable: false,
expandAll: true, //是否全部展开
scrollTreeStyle: "width:100%;",
};
},
methods: {
//渲染节点
renderContent(h, data) {
return (
<div>
<div>
<i class="el-icon-user-solid"></i>
<span>{data.label}</span>
<span>男</span>
</div>
<div style="font-size:12px;line-height:20px;">测试人员</div>
</div>
);
},
//鼠标移出
onMouseout(e, data) {
this.treeData.basicSwitch = false;
},
//鼠标移入
onMouseover(e, data) {
this.treeData.basicInfo = data;
this.treeData.basicSwitch = true;
var floating = document.getElementsByClassName("floating")[0];
floating.style.left = e.clientX + "px";
floating.style.top = e.clientY + "px";
},
//点击节点
NodeClick(e, data) {
console.log(e, data);
},
//默认展开
toggleExpand(data, val) {
if (Array.isArray(data)) {
data.forEach((item) => {
this.$set(item, "expand", val);
if (item.children) {
this.toggleExpand(item.children, val);
}
});
} else {
this.$set(data, "expand", val);
if (data.children) {
this.toggleExpand(data.children, val);
}
}
},
collapse(list) {
list.forEach((child) => {
if (child.expand) {
child.expand = false;
}
child.children && this.collapse(child.children);
});
},
//展开
onExpand(e, data) {
if ("expand" in data) {
data.expand = !data.expand;
if (!data.expand && data.children) {
this.collapse(data.children);
}
} else {
this.$set(data, "expand", true);
}
},
getList() {
// 后台回去的数据 赋值给data即可
},
// 自定义您的点击事件
onNodeClick(e, data) {
alert("点击");
},
expandChange() {
this.collapsable = true;
this.toggleExpand(this.treeData.data, this.expandAll);
},
},
};
</script>
<style lang="less">
.org-tree-node-label-inner {
color: #fff;
background-color: orange;
}
.el-org-tree {
.el-scrollbar__wrap {
overflow-x: hidden;
}
.org-tree-node-label {
white-space: nowrap;
}
.el-tree-node__content {
background: white;
}
.org-tree-node-label .org-tree-node-label-inner {
padding-top: 8px;
padding-right: 10px;
padding-bottom: 5px;
padding-left: 10px;
cursor: pointer;
}
.horizontal .org-tree-node.is-leaf {
padding-top: 5px;
padding-bottom: 5px;
}
}
</style>
index.vue
<template>
<!-- 元素放大缩小 拖动 -->
<div
id="drag"
@mousewheel.prevent="changeCanvas($event)"
@mousedown="mouseDrag($event)"
@dragover="allowDrop($event)"
@dragenter="dragEnter($event)"
@mouseup="mouseUp($event)"
@mousemove="mouseMove($event)"
>
<div id="flowContainer" ref="flowContainer">
<simple-tree />
</div>
</div>
</template>
<script>
import simpleTree from "./index copy";
export default {
name: "",
components: {
simpleTree,
},
computed: {},
data() {
return {
msg: "111",
zoomNum: 1,
disX: null,
disY: null,
mainX: null,
mainY: null,
ifDrag: false,
};
},
methods: {
allowDrop(evt) {
this.preventDefault(evt);
},
dragEnter(evt) {
this.preventDefault(evt);
},
//阻止冒泡以及默认事件
preventDefault(ev) {
var evt = ev || window.event;
if (typeof evt.preventDefault == "function") {
evt.preventDefault();
} else {
evt.returnValue = false;
}
if (typeof evt.stopPropagation == "function") {
evt.stopPropagation();
} else {
evt.cancelBubble = true;
}
},
// ==漫游====
// 拖拽
mouseDrag(e) {
// console.log('拖拽',e);
this.linemove = false;
// console.log(e)
let _this = this;
this.ifDrag = true;
let pos = _this.getPos(e); //获取鼠标坐标
_this.disX = pos.x;
_this.disY = pos.y;
_this.mainX = _this.$refs.flowContainer.offsetLeft;
_this.mainY = _this.$refs.flowContainer.offsetTop-60;
// if (this.ifDrag) {
// this.mouseMove(e);
// }
},
mouseMove(e) {
// console.log('move', document)
var _this = this;
// document.onmousemove = function (e) {
// debugger
// console.log(e)
// e.preventDefault()
if (!this.ifDrag) {
return;
}
var evt = window.event || e;
var left = evt.clientX - _this.disX + _this.mainX;
var top = evt.clientY - _this.disY + _this.mainY;
_this.$refs.flowContainer.style.left = left + "px";
_this.$refs.flowContainer.style.top = top + "px";
// }
// this.mouseUp();
},
mouseUp() {
// console.log('up', document.onmousemove)
var _this = this;
this.ifDrag = false;
//鼠标抬起
document.onmouseup = function (e) {
// console.log(e)
var evt = window.event || e;
// document.onmousemove = null;
// document.onmouseup = null;
// _this.ifDrag = false;
};
},
// 获取位置
getPos(ev) {
let scrollTop =
document.documentElement.scrollTop || document.body.scrollTop;
let scrollLeft =
document.documentElement.scrollLeft || document.body.scrollLeft;
return { x: ev.clientX + scrollLeft, y: ev.clientY + scrollTop };
},
// 改变画布大小--通过鼠标滚轮 缩小,放大
changeCanvas(event) {
var delta = 0;
var canvasDom = document.getElementById("flowContainer");
var p = ["webkit", "moz", "ms", "o"];
if (!event) event = window.event;
if (event.wheelDelta) {
//IE、chrome浏览器使用的是wheelDelta,并且值为“正负120”
delta = event.wheelDelta / 120;
if (window.opera) delta = -delta; //因为IE、chrome等向下滚动是负值,FF是正值,为了处理一致性,在此取反处理
} else if (event.detail) {
//FF浏览器使用的是detail,其值为“正负3”
delta = -event.detail / 3;
}
if (delta > 0) {
// 向上滚
if (this.zoomNum < 2) {
this.zoomNum += 0.1;
}
} else if (delta < 0) {
// 向下滚
if (this.zoomNum > 0.2) {
this.zoomNum -= 0.1;
}
}
for (var i = 0; i < p.length; i++) {
canvasDom.style[p[i] + "Transform"] = "scale(" + this.zoomNum + ")";
}
canvasDom.style["transform"] = "scale(" + this.zoomNum + ")";
return false;
},
},
mounted() {
},
created() {},
destroyed() {},
};
</script>
<style scoped>
#drag {
width: 100%;
height: 800px;
background: #ccc;
overflow: hidden;
}
#flowContainer {
width: 100%;
height: 100%;
background: #fff;
position: relative;
overflow: hidden;
left: 0px;
top: 0px;
transform-origin: 50% 50%;
}
</style>