矩阵 orgCharts

https://balkan.app/OrgChartJS/Demos/FirstLook

js部分

// 机构图
import OrgChart from '@balkangraph/orgchart.js/orgchart'
import { group, groupDisable, personIcon, personBg, personBgDisable, deptIcon, deptBg, deptBgDisable } from './img/groupImg.js'

export default class Chart {
  constructor(dom, treeData, direction = 'top') {
    this.direction = direction // 图形方向: top-从上到下,left-从左到右
    this.idKey = 'id' // 节点id key
    this.parentIdKey = 'pid' // 节点的父id key
    this.nameKey = 'name' // 节点的名称 key
    this.descKey = 'desc' // 节点的描述 key
    this.countKey = 'count' // 节点的数量 key
    this.iconKey = 'icon' // 节点的图标 key
    this.childKey = 'childList' // 子节点key
    return this.init(dom, treeData)
  }
  // 初始化
  init(dom, treeData) {
    const tree = this.delParentId(treeData)
    const list = []
    this.treeArray(tree, list)
    return this.draw(dom, list)
  }

  // 删除顶级节点的父id
  delParentId(treeData) {
    if (!treeData) {
      console.error('图数据为空,请检查')
      return false
    }
    if (!Array.isArray(treeData)) {
      console.error('图数据必须是数组,请检查')
      return false
    }
    if (treeData.length === 0) {
      return false
    }

    const list = treeData.map(item => {
      delete item[this.parentIdKey]
      return item
    })
    return list
  }

  // 把树形格式化为数组
  treeArray(list, result = []) {
    if (list && Array.isArray(list) && list.length > 0) {
      list.forEach(item => {
        const type = item.type
        const permission = item.permission
        if (type === '1' && permission === '0') {
          item.imgBg = deptBg
          item.imgIcon = deptIcon
        } else if (type === '1' && permission === '1') {
          item.imgBg = deptBgDisable
          item.imgIcon = deptIcon
        } else if (type === '2' && permission === '0') {
          item.imgBg = group
          item.imgIcon = ''
        } else if (type === '2' && permission === '1') {
          item.imgBg = groupDisable
          item.imgIcon = ''
        } else if (type === '3' && permission === '0') {
          item.imgBg = personBg
          item.imgIcon = personIcon
        } else if (type === '3' && permission === '1') {
          item.imgBg = personBgDisable
          item.imgIcon = personIcon
        }

        // item.desc = `${item[this.descKey]}`
        // item.number = `人员数量:${item[this.countKey]}`
        // item.img = item[this.iconKey]

        result.push(item)
        this.treeArray(item[this.childKey], result)
      })
    }
  }

  // 渲染机构树图形
  draw(dom, list) {
    this.setTmp1()
    this.setTmp2()
    this.setTmp3()
    const nodes = list.map(item => {
      if (item.type === '1') {
        item.tags = ['dept']
      } else if (item.type === '2') {
        item.tags = ['group']
      } else if (item.type === '3') {
        item.tags = ['person']
      }

      return item
    })
    return new OrgChart(dom, {
      nodes: nodes,
      nodeBinding: {
        field_1: 'desc',
        field_2: 'number',
        img_0: 'imgBg',
        img_1: 'imgIcon',
        field_0: 'name',
        field_3: 'groupName'
      },
      tags: {
        dept: {
          template: 'deptTemplate'
        },
        group: {
          template: 'myTemplate'
        },
        person: {
          template: 'personTemplate'
        }
      },
      // menu: {
      //   pdf: { text: '导出 PDF' },
      //   png: { text: '导出 PNG' },
      //   svg: { text: '导出 SVG' },
      //   csv: { text: '导出 CSV' }
      // },
      toolbar: {
        layout: false,
        zoom: false,
        fit: false,
        expandAll: false
      },
      layout: OrgChart.tree,
      orientation: OrgChart.orientation[this.direction], // 方向
      enableSearch: false, // 是否可以搜索
      nodeMouseClick: OrgChart.action.none // 关闭点击后出现的效果,该效果有很多,可以去官网查看
    })
  }

  // 模板部门
  setTmp1() {
    OrgChart.templates.deptTemplate = Object.assign({}, OrgChart.templates.ana)
    OrgChart.templates.deptTemplate.size = [271, 103]
    OrgChart.templates.deptTemplate.node =
      `<g class="box-wrapper" style="cursor: pointer">
            <rect class="hy_node" width="264" height="100" rx="4" ry="4" fill="transparent" ></rect>
        </g>
        `
    // 鼠标点击效果
    OrgChart.templates.deptTemplate.ripple = {
      radius: 0,
      color: '#FC8E58',
      rect: null
    }
    OrgChart.templates.deptTemplate.field_0 =
      `
        <g>
          <linearGradient y2="1" x2="0" y1="0" x1="0" id="harder_bg">
            <stop stop-color="#0dccff" offset="0"/>
            <stop stop-color="#4760ff" offset="1"/>
          </linearGradient>
            <rect class="hy_node header-rect" width="264" height="100" rx="2" ry="2" fill="url(#ulaImg)" ></rect>
            <text
             style="font-size: 18px; cursor: pointer; line-height: 1;font-weight: bold;;
             writing-mode: tb-lr;"
             fill="#fff"
             x="138"
             y="55"
             text-anchor="middle">{val}</text>
        </g>
        `
    OrgChart.templates.deptTemplate.img_0 =
      '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#ulaImg)" xlink:href="{val}" x="0" y="0" width="264" height="100">' +
      '</image>'
    OrgChart.templates.deptTemplate.img_1 =
      '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#ulaImg)" xlink:href="{val}" x="56" y="28" width="43" height="43">' +
      '</image>'
    // 连接线条
    OrgChart.templates.deptTemplate.link = '<path stroke="#299ef9" stroke-width="1px" fill="none" link-id="[{id}][{child-id}]" d="M{xa},{ya} C{xb},{yb} {xc},{yc} {xd},{yd}" />'
    OrgChart.templates.deptTemplate.plus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>' +
      '<line x1="15" y1="11" x2="15" y2="19" stroke-width="1" stroke="#fff"></line>'

    OrgChart.templates.deptTemplate.minus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>'
  }
  // 模板分组
  setTmp2() {
    OrgChart.templates.myTemplate = Object.assign({}, OrgChart.templates.ana)
    OrgChart.templates.myTemplate.size = [50, 147]
    OrgChart.templates.myTemplate.node =
      `<g class="box-wrapper" style="cursor: pointer">
            <rect class="hy_node" width="50" height="147" rx="4" ry="4" fill="#e6efff" ></rect>
        </g>
        `
    // 鼠标点击效果
    OrgChart.templates.myTemplate.ripple = {
      radius: 0,
      color: '#FC8E58',
      rect: null
    }
    OrgChart.templates.myTemplate.field_0 =
      `
        <g>
          <linearGradient y2="1" x2="0" y1="0" x1="0" id="harder_bg">
            <stop stop-color="#0dccff" offset="0"/>
            <stop stop-color="#4760ff" offset="1"/>
          </linearGradient>
            <rect class="hy_node header-rect" width="50" height="147" rx="2" ry="2" fill="url(#ulaImg)" ></rect>
            <text
             style="font-size: 16px; cursor: pointer; line-height: 1;
             writing-mode: vertical-lr;
             writing-mode: tb-lr;"
             text-overflow="multiline"
             fill="#fff"
             x="25"
             y="71"
             text-anchor="middle">{val}</text>
        </g>
        `
    OrgChart.templates.myTemplate.img_0 =
      '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#ulaImg)" xlink:href="{val}" x="0" y="0" width="50" height="147">' +
      '</image>'

    // 连接线条
    OrgChart.templates.myTemplate.link = '<path stroke="#299ef9" stroke-width="1px" fill="none" link-id="[{id}][{child-id}]" d="M{xa},{ya} C{xb},{yb} {xc},{yc} {xd},{yd}" />'
    OrgChart.templates.myTemplate.plus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>' +
      '<line x1="15" y1="11" x2="15" y2="19" stroke-width="1" stroke="#fff"></line>'

    OrgChart.templates.myTemplate.minus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>'
  }
  // 模板分组
  setTmp3() {
    OrgChart.templates.personTemplate = Object.assign({}, OrgChart.templates.ana)
    OrgChart.templates.personTemplate.size = [159, 92]
    OrgChart.templates.personTemplate.node =
      `<g class="box-wrapper" style="cursor: pointer">
            <rect class="hy_node" width="159" height="92" rx="4" ry="4" fill="transparent" ></rect>
        </g>
        `
    // 鼠标点击效果
    OrgChart.templates.personTemplate.ripple = {
      radius: 0,
      color: '#FC8E58',
      rect: null
    }
    OrgChart.templates.personTemplate.field_0 =
      `
        <g>
          <linearGradient y2="1" x2="0" y1="0" x1="0" id="harder_bg">
            <stop stop-color="#0dccff" offset="0"/>
            <stop stop-color="#4760ff" offset="1"/>
          </linearGradient>
            <rect class="hy_node header-rect" width="159" height="92" rx="2" ry="2" fill="url(#ulaImg)" ></rect>
            <text
             style="font-size: 16px; cursor: pointer; line-height: 1;
             writing-mode: "
             fill="#fff"
             x="90"
             y="57"
             text-anchor="middle">{val}</text>
        </g>
        `
    OrgChart.templates.personTemplate.field_3 =
      `
          <g>
            <linearGradient y2="1" x2="0" y1="0" x1="0" id="harder_bg">
              <stop stop-color="#0dccff" offset="0"/>
              <stop stop-color="#4760ff" offset="1"/>
            </linearGradient>
              <rect class="hy_node header-rect" width="51" height="96" rx="2" ry="2" fill="url(#ulaImg)" ></rect>
              <text
               style="font-size: 14px; cursor: pointer; line-height: 1;
               writing-mode:"
               fill="#fff"
               x="79"
               y="19"
               text-anchor="middle">{val}</text>
          </g>
          `

    OrgChart.templates.personTemplate.img_0 =
      '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#ulaImg)" xlink:href="{val}" x="0" y="0" width="159" height="92">' +
      '</image>'
    OrgChart.templates.personTemplate.img_1 =
      '<image preserveAspectRatio="xMidYMid slice" clip-path="url(#ulaImg)" xlink:href="{val}" x="25" y="35" width="35" height="35">' +
      '</image>'
    // 连接线条
    OrgChart.templates.personTemplate.link = '<path stroke="#299ef9" stroke-width="1px" fill="none" link-id="[{id}][{child-id}]" d="M{xa},{ya} C{xb},{yb} {xc},{yc} {xd},{yd}" />'
    OrgChart.templates.personTemplate.plus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>' +
      '<line x1="15" y1="11" x2="15" y2="19" stroke-width="1" stroke="#fff"></line>'

    OrgChart.templates.personTemplate.minus =
      '<rect x="7" y="7" width="16" height="16" rx="8" ry="8" fill="#299ef9" stroke="#0fbfe9" stroke-width="2"></rect>' +
      '<line x1="11" y1="15" x2="19" y2="15" stroke-width="1" stroke="#fff"></line>'
  }
}

html部分

<div class="chart"  ref="orgChartDom"></div>
<div class="new-header">
      <div class="title">销售部门</div>
      <div class="top-options">
        <div class="item"
             @click="handleEnlarge">
          <div class="text">放大</div>
          <div class="img big" />
        </div>
        <div class="item"
             @click="handleTurnDown">
          <div class="text">缩小</div>
          <div class="img small" />
        </div>
        <div class="item"
             @click="handleFit">
          <div class="text">适配窗口</div>
        </div>
        <div class="item"
             @click="handleRouterHome">
          <div class="text">返回</div>
          <div class="img back" />
        </div>
      </div>
    </div>

import OrgChart from './js/groupChart'

data() {
    return {
      layer: 2,
      layerList: [1, 2, 3, 4, 5, 6, 7, 8, 9],
      direction: 'top',
      dataSource: [],
      tagObjTagList: [],
      orgChartData: [],
      showOrgChartData: [],
      orgChartObject: {}
    }
  }



methods: {
    init() {
      getEchartsGroupsAndPersons().then(res => {
        if (res.code === 0) {
          const data = []
          this.dataSource = res.data || []
          this.buildTagTree(this.dataSource, data, '0')
          this.tagObjTagList = data
          this.getChartData()
          this.layerChange(3)
        }
      })
    },
    handleDistribution() {
      this.$refs.employeeListByGroupModal.open()
    },
    handleRouterHome() {
      this.$router.push({
        path: '/portalClient/index'
      })
    },
    buildTagTree(list, arr, parentId) {
      list.forEach(item => {
        if (item.parentId === parentId) {
          var child = {
            id: item.id,
            pid: item.parentId,
            name: item.name,
            groupName: item.groupName,
            type: item.type,
            childList: [],
            permission: item.permission
          }
          this.buildTagTree(list, child.childList, item.id)
          if (child.childList.length === 0) {
            delete child.childList
            child.isLeaf = true
          } else {
            child.isLeaf = false
          }
          arr.push(child)
        }
      })
    },
    // 层级改变
    layerChange(v) {
      const layer = v === 0 ? 999 : v
      this.layer = v
      this.showOrgChartData = base.deepClone(this.tagObjTagList)
      base.layerTree(this.showOrgChartData, 'childList', layer, 1)
      this.renderChart(this.direction)
      this.handleFit()
    },
    // 点击事件
    nodeClick(vm, nodeInfo) {
      const currentNode = this.dataSource.find(item => item.id === nodeInfo.node.id)
      if (currentNode.permission === '0') {
        this.$refs.marketingDetail.open(currentNode)
      } else if (currentNode.permission === '1') {
        this.$warning({
          title: '权限提示',
          content: '暂无权限!'
        })
      }
    },
    /** 思维导图函数 */
    // 机构图--获取机构图数据
    getChartData() {
      this.orgChartData = this.tagObjTagList
      this.showOrgChartData = base.deepClone(this.tagObjTagList)
      this.renderChart('top')
      this.handleFit()
    },
    // 方向变更重新渲染
    renderChart(direction) {
      this.orgChartObject = new OrgChart(this.$refs.orgChartDom, this.showOrgChartData, direction)
      this.orgChartObject.on('click', this.nodeClick)
    },
    // 放大
    handleEnlarge() {
      if (this.orgChartObject) {
        this.orgChartObject.zoom(true, undefined, true)
      }
    },
    handleTurnDown() {
      if (this.orgChartObject) {
        this.orgChartObject.zoom(false, undefined, true)
      }
    },
    handleFit() {
      if (this.orgChartObject) {
        this.orgChartObject.fit()
      }
    }
  }

 

posted @ 2021-09-13 14:06  小拐  阅读(172)  评论(0)    收藏  举报