同样树形架构的插件 vue-orgChart
jsPlumb

vue-org-tree官网vue-org-tree

<template>
  <div id="tree" class="tree-container">
      <el-button type="primary" plain class="addBtn" slot="reference" @click="addNode">新增</el-button>
        <div class="text-center">
          <vue2-org-tree
            name="test"
            :data="data"
             :pan = "pan"
             :zoom = "zoom"
            :horizontal="horizontal"
            :collapsable="collapsable"
            :label-class-name="labelClassName"
            :render-content="renderContent"
            @on-expand="onExpand"
            @on-node-click="onNodeClick"
          />
        </div>
        <my-dialog :customName="'dialogStyle'" :modalBoolean=false :dialogTitle="dialogTitle"  @doConfirm="doConfirm" ref="deleteDialaog">
          <span slot="dialogContent" class="deleteWord"><i class="iconfont icongantanhao marvel"></i> 是否确认删除?删除后该节点的所有子节点将整体脱离本模块</span>
        </my-dialog>
         <!-- <el-dialog
          :visible.sync="visible"
           width="30%"
          :modal=false
          title="新增从属关系"
          custom-class='dialogStyle'
          >
      </el-dialog> -->
      <my-dialog :customName="'dialogStyle'" :modalBoolean=false :dialogTitle="'新增从属关系'"  @doConfirm="addDoConfirm" ref="addDialaog">
          <el-form slot="dialogContent" :model="dependenceForm" status-icon ref="ruleForm" label-width="100px" class="demo-ruleForm" label-position="center">
            <el-row>
              <el-col :span="12">
                <el-form-item label="源节点">
                  <el-input placeholder="待添加" size="mini" v-model="dependenceForm.originNode"></el-input>
                </el-form-item>
              </el-col>
              <el-col :span="12">
                <el-form-item label="目标节点">
                  <el-input placeholder="待添加" size="mini" v-model="dependenceForm.targetNode"></el-input>
                </el-form-item>
              </el-col>
            </el-row>
            <!-- <el-form-item align="right">
              <el-button @click="visible= false">取消</el-button>
              <el-button type="primary" @click="submitForm('dependenceForm')">保存</el-button>
            </el-form-item> -->
          </el-form>
        </my-dialog>
      <!-- <el-dialog
          :visible.sync="childVisible"
          :modal=false
          custom-class='dialogChildStyle'
          :showClose=false
      >
<el-select v-model="optionsValue" filterable placeholder="请选择">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
          </el-option>
        </el-select>
      </el-dialog> -->
      <my-dialog :customName="'dialogChildStyle'" :dialogTitle="''" :modalBoolean=false :showClose=false ref="childDialog" :defaultButtonGroup=false>
        <!-- <el-select v-model="optionsValue" filterable placeholder="请选择" slot="dialogContent">
          <el-option
            v-for="item in options"
            :key="item.value"
            :label="item.label"
            :value="item.value">
          </el-option>
        </el-select> -->
        <div slot="dialogContent">
          <el-input placeholder="搜索" style="width: 100%"></el-input>
          <div class="search-content">
            <p>主页面</p >
            <p>设置</p >
            <p>设置</p >
            <p>设置</p >
            <p>设置</p >
            <p>设置</p >
          </div>
        </div>
      </my-dialog>
      </div>
</template>
<script>
import Vue from 'vue'
import Vue2OrgTree from 'vue2-org-tree'
import MyDialog from '@/components/customDialog/index.vue'
Vue.use(Vue2OrgTree)
export default {
  components: {
    MyDialog
  },
  data () {
    return {
      data: {
        id: 0,
        label: '度量指标体系',
        children: [
          {
            id: 1,
            label: '交付质量',
            children: [
              {
                id: 11,
                label: '生产质量',
                children: [
                  {
                    id: 111,
                    label: '生产事件'
                  }
                ]
              },
              {
                id: 12,
                label: '开发质量',
                children: [
                  {
                    id: 121,
                    label: '项目开发缺陷密度'
                  }
                ]
              },
              {
                id: 13,
                label: '发布质量',
                children: [
                  {
                    id: 131,
                    label: '上线失败率'
                  }
                ]
              },
              {
                id: 14,
                label: '过程质量',
                children: [
                  {
                    id: 141,
                    label: '项目过程符合度'
                  }
                ]
              }
            ]
          }
        ]
      },
      horizontal: true, // 横向
      collapsable: false, // 可折叠
      expandAll: true,
      labelClassName: 'bg-white',
      zoom: true,
      pan: true,
      dependenceForm: {
        originNode: '',
        targetNode: ''
      },
      visible: false,
      deleteDialogVisible: false, // 删除框的boolean
      childVisible: false, // 子弹窗
      deleteNode: '',
      options: [{
        value: '选项1',
        label: '黄金糕'
      }, {
        value: '选项2',
        label: '双皮奶'
      }, {
        value: '选项3',
        label: '蚵仔煎'
      }, {
        value: '选项4',
        label: '龙须面'
      }, {
        value: '选项5',
        label: '北京烤鸭'
      }],
      optionsValue: ''
      // 背景色 labelWidth:节点标签宽度
      // renderContent:如何渲染节点标签
      // labelClassName:节点标签类
      // selectedKey: 所选节点的密钥
      // selectedClassName: 所选节点的className
      // props: 配置属性
      // pan: 移动
      // zoom: 放大
      // click  mouseover mouseout
    }
  },
computed: {
    dialogTitle () {
      return `删除 ${this.deleteNode} 节点`
    }
  },
  methods: {
    doConfirm () {

    },
    addDoConfirm (callback) {
      console.log(1)
      callback()
    },
    addNode () {
      this.$refs.addDialaog.changeDialogStatus(true)
    },
    clickNode () {
    },
    renderContent (h, data) {
      console.log(data)
      return (
        <span>
          <el-dropdown oncommand={(v) => this.onClick(v, data)}>
            <span class="el-dropdown-link">
              {data.label}
              <i class="el-icon-arrow-down el-icon--right"></i>
            </span>
            <el-dropdown-menu
              slot="dropdown"
            >
              <el-dropdown-item command='addChild'>新增子节点</el-dropdown-item>
              <el-dropdown-item command='del'>删除</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </span>
      )
    },
onClick (type, node) {
      console.log(type, node)
      this.$message.info('点击事件')
      if (type === 'del') {
        if (node.children && node.children.length > 0) {
          this.$message.info('当前节点存在子部门,请先删除子节点')
          return false
        }
        // this.deleteDialogVisible = true
        this.$refs.deleteDialaog.changeDialogStatus(true)
        this.deleteNode = node.label
      }
      if (type === 'addChild') {
        this.childVisible = true
        this.$refs.childDialog.changeDialogStatus(true)
      }
      // if (keyObj.key === 'del') {
      //   if (node.children && node.children.length > 0) {
      //     this.$message.info('当前部门存在子部门,请先删除子部门')
      //   } else {
      //     this.$http.get('/rdDept/del', { params: { id: node.value } })
      //       .then(res => {
      //         if (res.success && res.data) {
      //           this.$message.success('删除成功')
      //           this.loadTree()
      //         } else {
      //           this.$message.error(res.errorMessage)
      //         }
      //       })
      //   }
      // } else {
      //   this.$refs.modifyDept.showModal(keyObj.key, node)
      // }
    },
    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)
      }
    },
    // 点击选项执行的方法,可以用于跳转到其他链接,注意一定要写协议头
    onNodeClick (e, data) {
      console.log(data)
      if (data.url == null) {
        return false
      } else {
        window.open(data.url)
      }
    },
collapse (list) {
      var _this = this
      list.forEach(function (child) {
        if (child.expand) {
          child.expand = false
        }
        child.children && _this.collapse(child.children)
      })
    },
    expandChange () {
      this.toggleExpand(this.data, this.expandAll)
    },
    toggleExpand (data, val) {
      var _this = this
      if (Array.isArray(data)) {
        data.forEach(function (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)
        }
      }
    }
  }
}
</script>
<style lang="less">
.tree-container{
  background-color: #fff;
  width:1100px;
  overflow: auto;
  .addBtn{
    margin-left: 1000px;
  }
  .el-popover__title {
    color: #303133;
    font-size: 16px;
    line-height: 1;
    padding-bottom: 10px;
    margin-bottom: 12px;
    border-bottom: 1px solid #eee !important;
}
.dialogStyle{
    position: absolute;
    top: 200px;
    right: 30px;
    width: 550px !important;
    .el-dialog__body{
      padding-bottom: 10px;
    }
}
.dialogChildStyle{
    width: 210px !important;
    .el-dialog__header {
    display: none;
    border:none;
}
  .el-dialog__footer{
    border:none !important;
}
.search-content{
  margin-top: 10px;
  padding-bottom:10px;
  p{
    text-align: center;
  }
}
}
.el-dialog__footer{
  text-align: right;
}
.deleteName{
  font-size: 14px;
}
.deleteWord{
  color: gray;
  font-size: 14px;
}
.bg-white {
    background-color: #ECF5FF;
}
.org-tree-node-label .org-tree-node-label-inner {
    padding: 10px 15px;
    text-align: center;
    border-radius: 3px;
    box-shadow: 0 1px 5px rgba(0, 0, 0, 0.15);
    border: 1px solid lightblue;
}
.el-dropdown-link{
  color:#419EFF;
}
.el-icon--right{
  color: #aaa;
}
.marvel{
  font-size: 22px;
  color: orange;
  margin-right: 10px;
  vertical-align: -3px;
}
}
</style>
<style type="text/css">
.org-tree-node-label {
  white-space: nowrap;
}
.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;
}
.org-tree-container {
    display: inline-block;
    padding: 15px;
    background-color: #fff;
    width: 100%;
    height: 100%;
}
</style>

HappyCodingTop
526 声望847 粉丝

Talk is cheap, show the code!!