vue2-org-tree设置

1,216 阅读1分钟

<template>
  <div class="arch-poho-wrapper">
    <p-spin v-if="Object.keys(data).length <= 0" class="loading-spin" size="large" />
    <div class="down-btn" v-if="Object.keys(data).length > 0 && isEdit">
      <!-- <p-button type="primary" ghost icon="download" /> -->
      <p-button type="primary" ghost icon="download" size="small" :loading="downLoading" @click="handleDown" title="下载">{{ $t('front.59') }}</p-button>
    </div>

    <div class="orgTree-part">
      <vue2-org-tree
        ref="orgTreeContainer"
        id="org-tree-container"
        :style="{ height: TreeDomHeight }"
        :data="data"
        :props="props"
        collapsable
        :label-class-name="labelClassName"
        :render-content="renderContent"
        :selected-key="selectedKey"
        @on-expand="onExpand"
        @on-node-click="onNodeClick"
      />
    </div>
  </div>
</template>

<script>
import html2canvas from 'html2canvas'
import EventBus from '@/utils/eventBus'
import { getProcessTreeById } from '../api/api'

export default {
  name: '',
  props: {
    archId: {
      type: String,
      default: ''
    },
    isEdit: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      data: {},
      props: { label: 'name', children: 'child', expand: 'expand' },
      collapsable: true,
      labelClassName: 'bg-color',
      TreeDomHeight: '600px',
      downLoading: false
    }
  },
  watch: {
    archId: {
      handler: function (val) {
        this.loadData(val)
      }
    }
  },

  created() {
    // 监听自定义事件(本页面和面包屑功能的自定义事件)
    EventBus.$on('eventBus', (data) => {
      this.archId = data.id
    })
  },
  mounted() {
    this.computedOrgTreeHeight()
    // 监听屏幕高度
    window.addEventListener('resize', this.computedOrgTreeHeight)
  },
  destroyed() {
    window.removeEventListener('resize', this.computedOrgTreeHeight)
  },
  methods: {
    renderContent(h, data) {
      return <div class={data.archRegion == 'C' ? 'bg-color-C' : data.archRegion == 'W' ? 'bg-color-W' : data.archRegion == 'S' ? 'bg-color-S' : 'bg-color-base'}>{data.name}</div>
    },
    // 折叠
    collapse(list) {
      var _this = this
      list.forEach(function (child) {
        if (child.expand) {
          child.expand = false
        }
        child.child && _this.collapse(child.child)
      })
    },
    // 展开
    onExpand(e, data) {
      if ('expand' in data) {
        data.expand = !data.expand
        if (!data.expand && data.child) {
          this.collapse(data.child)
        }
      } else {
        this.$set(data, 'expand', true)
      }
    },

    toggleExpand(data, val) {
      var _this = this
      if (Array.isArray(data)) {
        data.forEach(function (item) {
          _this.$set(item, 'expand', val)
          if (item.child) {
            _this.toggleExpand(item.child, val)
          }
        })
      } else {
        this.$set(data, 'expand', val)
        if (data.child) {
          _this.toggleExpand(data.child, val)
        }
      }
    },

    loadData(param) {
      getProcessTreeById(param).then((res) => {
        let resData = res.data
        if (resData.success) {
          let data = resData.data
          this.data = Object.assign({}, this.data, data)
          // this.toggleExpand(this.data, false)
        } else {
          this.data = { error: 1 }
          this.$message.error(resData.msg || '请稍后重试')
        }
      })
    },
    // 点击架构节点
    onNodeClick: function (e, data) {
      this.data = Object.assign({}, data)
      // 点击节点可以不用调接口的 this.$set(this.data, 'expand', true) 这样本页面和面包屑需要两个不同名的自定义事件
      // this.$set(this.data, 'expand', true)
      // 点击的时候触发自定义事件(本页面和面包屑页面,左边树组件监听)
      EventBus.$emit('eventBus', data)
    },

    // 计算架构图组织的容器的高度
    computedOrgTreeHeight() {
      // let orgTreeDom = document.getElementById('org-tree-container')
      let len = this.isEdit ? 64 : 32
      let orgTreeDom = this.$refs.orgTreeContainer.$el
      let screenHeight = document.body.clientHeight
      let orgTreeDomTop = orgTreeDom.getBoundingClientRect().top + len
      this.TreeDomHeight = screenHeight - orgTreeDomTop + 'px'
    },

    // 将架构图生成图片进行下载
    handleDown() {
      let orgTreeContainer = this.$refs.orgTreeContainer.$el
      // const imgWidth = orgTreeContainer.offsetWidth,
      //   imgHeight = orgTreeContainer.offsetHeight
      // const size = [imgWidth, imgHeight]
      this.downLoading = true
      html2canvas(orgTreeContainer, { useCORS: true, logging: true, allowTaint: true }).then((canvas) => {
        var _imgUrl = canvas.toDataURL('image/png')
        let eleLink = document.createElement('a')
        let nameArr = this.data?.name.split(' ')

        eleLink.href = _imgUrl
        eleLink.download = nameArr[nameArr.length - 1] || '图片'
        document.body.appendChild(eleLink)
        // 触发点击
        eleLink.click()

        setTimeout(() => {
          this.downLoading = false
        }, 100)
        // 然后移除
        document.body.removeChild(eleLink)
      })
    }
  }
}
</script>

<style lang="less">
.arch-poho-wrapper {
  position: relative;

  .down-btn {
    display: flex;
    justify-content: flex-end;
    align-items: top;
    margin-bottom: 8px;
  }
  // height: 68vh;
  .loading-spin {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
  .orgTree-part {
    overflow: auto;
    .org-tree-container {
      min-width: 100%;

      // height: 67vh;
      background: rgb(244, 247, 254);

      > .org-tree {
        > .org-tree-node {
          > .org-tree-node-label {
            .bg-color-base {
              background-color: #0077ff !important;
            }
          }

          > .org-tree-node-children {
            .org-tree-node-children {
              background: #fff;
              border: 2px solid #e0e5f1;
              border-radius: 6px;
              margin-left: 8px;
              margin-right: 8px;
              margin-bottom: 4px;
              padding-bottom: 10px;
            }
          }

          &:not(:first-child):before,
          &:not(:last-child):after {
            border-top: 1px solid rgb(171, 180, 205);
          }

          .org-tree-node:after {
            left: 50%;
            border-left: 1px solid rgb(171, 180, 205);
          }
          .org-tree-node:not(:first-child):before,
          .org-tree-node:not(:last-child):after {
            border-top: 1px solid rgb(171, 180, 205);
          }

          .org-tree-node-children:before {
            content: '';
            position: absolute;
            top: 0;
            left: 50%;
            width: 0;
            height: 20px;
            border-left: 1px solid rgb(171, 180, 205);
          }

          .org-tree-node-btn {
            background: #fff;
          }
        }
      }
    }
  }

  .bg-color {
    padding: 0;
    color: #ffffff;
    font-weight: 400;
    > div {
      padding: 10px 15px;
      cursor: pointer;
      // width: 136px;
      // line-height: 14px;
    }
  }
  // .bg-color-root {
  //   background-color: #0077ff;
  // }
  .bg-color-base {
    background-color: #014ba2;
  }
  .bg-color-S {
    background-color: #4772ff;
  }
  .bg-color-C {
    background-color: #7c6ff1;
  }
  .bg-color-W {
    background-color: #35bbbb;
  }
  .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 rgb(171, 180, 205);
  }
}
</style>



image.png