自定义横向思维导图,横向组织架构图,横向树图。可以自定义节点颜色,样式,还可以导出为图片

7 篇文章 0 订阅

最近公司设计要求根据目录结构,横向展示。所以做了一个横向的思维导图,横向的树结构,横向的组织架构图,可以自定义节点颜色,样式,还可以导出为图片

话不多说,直接上图片,这个就是一个小例子
在这里插入图片描述子组件,直接上代码,子组件的线条颜色,可以自己设置变量从父组件传入,我这里没写。
isUnfold 表示是否有下级

<template>
  <div class="my-self-tree" ref="my-tree">
    <div class="info-card">
      <div class="card-item" v-for="(item, index) in data" :key="index">
        <div
          class="vertical-line"
          :style="computedHeight(item.height, data.length, index)"
          v-if="item.level !== 0"
        ></div>
        <div class="horizontal-line" v-if="item.level !== 0"></div>
        <div class="tree-node" :class="{'tree-node-1': item.level == 0&&item.isUnfold != 0}">
          <div
            class="tree-node-content"
            :class="[handlItem(item)]"
            @click="clickTreeNode(item)"
          >
            {{ item.name }}
          </div>
        </div>
        <div
          class="horizontal-line"
          v-if="item.childNode && item.childNode.length !== 0"
        ></div>
        <mytree
          @nodeClick="clickTreeNode"
          :data="item.childNode"
          v-if="item.childNode && item.childNode.length !== 0"
        ></mytree>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "mytree",
  props: {
    data: Array,
  },
  data() {
    return {};
  },
  methods: {
    computedHeight(pheight, length, index) {
      if (length == 1 || length == 0) {
        return {
          height: "0px",
          display: "none",
        };
      } else {
        let height = 0;
        let marginTop = 0;
        let marginB = 0;
        if (index == 0) {
          height = pheight / 2;
          marginTop = height;
          return {
            height: height + "px",
            "margin-top": marginTop + "px",
          };
        }
        if (index == length - 1) {
          height = pheight / 2;
          marginB = height;
          return {
            height: height + "px",
            "margin-bottom": marginB + "px",
          };
        } else {
          height = pheight;
          return {
            height: height + "px",
          };
        }
      }
    },
    clickTreeNode(item) {
      this.$emit("nodeClick", item);
    },
    handlItem(item) {
      if (item.level == 0) {
        return 'has-background'
      }else {
        if (item.isUnfold == 1) {//中间节点
          let flag = this.hasZeroCountNode(item.childNode);
          console.log(flag, 'flag')
          if (item.level == 1) {
            return flag ? 'font-color-black border-black' : 'font-color-green border-green';
          } else {
            return flag ? 'font-color-black' : 'font-color-green';
          }
        } else if (item.isUnfold == 0) {//最后一个节点
          if (item.level == 1) {
            return item.count == 0 ? 'font-color-red border-red' : 'font-color-green border-green'
          } else {
            return item.count == 0 ? 'font-color-red' : 'font-color-green'
          }
        }
      }
    },
    hasZeroCountNode(nodes) {
      //不含当前节点的count判断,判断所有子节点
      for (let node of nodes) {
        if (node.count === 0) {
          return true;
        }
        if (node.childNode && this.hasZeroCountNode(node.childNode)) {
          return true;
        }
      }
      return false;
      //含当前节点的count判断
      // if (node.count === 0) {
      //   return true; // 如果找到节点的count为0,立即返回true
      // }
      // if (node.childNode && node.childNode.length > 0) {
      //   // 如果节点有子节点,则递归检查子节点
      //   return node.childNode.some(child => this.hasZeroCountNode(child));
      // }
      // return false; // 如果节点和其子节点都不满足条件,返回false
    }
  },
  components: {},
  mounted() {},
};
</script>

<style lang="scss" scoped>
:root .my-self-tree {
  // height: 100%;
  // width: 100%;
  .vertical-line {
    position: relative;
    // display: inline-block;
    width: 0.5px;
    background: #009694;
    transform:scale(2, 1);
  }
  .card-item {
    margin:0;padding:0;
    display: flex;
    align-items: center;
    .horizontal-line {
      min-width: 30px !important;
      //   display: inline-block;
      height: 0.5px;
      background: #009694;
      transform:scale(1 , 2);
      position: relative;
    }
    .horizontal-line::before {
      content:'';
      position:absolute;
      height: 1px;
      width:2px;
      right:-1px;
      background: #009694;
    }
    .horizontal-line::after {
      content:'';
      position:absolute;
      height: 1px;
      width:2px;
      left:-1px;
      background: #009694;
    }
  }
  .tree-node {
    cursor: pointer;
    height: 30px;
    position: relative;
    &:nth-child(1)::after {
      display: none;
    }
    // &:nth-child(1)::before {
    //   position: absolute;
    //   content: "";
    //   width: 8px;
    //   display: inline-block;
    //   height: 8px;
    //   border-radius: 4px;
    //   top: 50%;
    //   right: -4px;
    //   transform: translateY(-50%);
    //   background: #009694;
    // }
    .tree-node-content {
      display: flex;
      position: relative;
      justify-content: center;
      align-items: center;
      width: auto;
      height: 100%;
      border: none;
      border-radius: 4px;
      color: #000;
      white-space: nowrap !important;
      padding: 0 10px;
    }
    .has-background {
      color: white;
      background: #009694;
    }
    .border-green {
      border: 1px solid #009694;
    }
    .border-black {
      border: 1px solid #000;
    }
    .border-red {
      border: 1px solid #FF6767;
    }
    .font-color-green {
      color: #009694;
    }
    .font-color-black {
      color: #000;
    }
    .font-color-red {
      color: #FF6767;
    }
  }
  .tree-node::after {
    position: absolute;
    content: "";
    width: 8px;
    display: inline-block;
    height: 8px;
    border-radius: 4px;
    top: 50%;
    left: -4px;
    transform: translateY(-50%);
    background: #009694;
  }
  .tree-node-1::before {
      position: absolute;
      content: "";
      width: 8px;
      display: inline-block;
      height: 8px;
      border-radius: 4px;
      top: 50%;
      right: -4px;
      transform: translateY(-50%);
      background: #009694;
    }
}
</style>

这里是父组件

<el-popconfirm
          placement="top-end"
          title="是否需要导出为图片?"
          @confirm="exportFn"
          >
          <el-button
            slot="reference"
            style="margin-left: 10px"
            type="primary"
            class="fliter-btn icons-btn"
            size="mini"
            ><i class="qhFileManage icon-daochu" style="font-size: 14px;"></i> 导出
          </el-button>
          </el-popconfirm>
<tree :data="dataInfo" @nodeClick="nodeClick" id="mytree" style="height: 100%;"></tree>

//处理数据
//temporaryData 为实际获取的数据 ,temporaryData1 是做例子写的数据
    handleData(temporaryData) {
      //自行调试测试数据,后面换成正式数据
      let temporaryData1 = [
        {
          id: 1,
          level: 0,
          name: "部门名称啊",
          childNode: [
            {
              id: 11,
              level: 1,
              name: "自己测试数据",
              isUnfold: 1,
              childNode: [
                {
                  id: 1111111,
                  level: 2,
                  name: "所有下级节点count>0",
                  isUnfold: 1,
                  childNode: [
                    {
                      id: 1111111,
                      level: 3,
                      name: "2ge",
                      count: 2,
                      isUnfold: 0,
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: 1,
                      isUnfold: 1,
                      childNode: [
                        {
                          id: 1111111,
                          level: 4,
                          name: "2",
                          isUnfold: 1,
                          childNode: [
                            {
                              id: 1111111,
                              level: 4,
                              name: "1ge",
                              count: 1,
                              isUnfold: 0,
                            },
                          ],
                        },
                      ],
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: "2ge",
                      count: 2,
                      isUnfold: 0,
                    },
                  ],
                },
                {
                  id: 1111111,
                  level: 2,
                  name: "所有下级节点count=0",
                  isUnfold: 1,
                  childNode: [
                    {
                      id: 1111111,
                      level: 3,
                      name: "0ge",
                      count: 0,
                      isUnfold: 0,
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: 1,
                      isUnfold: 1,
                      childNode: [
                        {
                          id: 1111111,
                          level: 4,
                          name: "0ge",
                          count: 0,
                          isUnfold: 0,
                        },
                      ],
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: "0ge",
                      count: 0,
                      isUnfold: 0,
                    },
                  ],
                },
                {
                  id: 1111111,
                  level: 2,
                  name: "所有下级节点存count=0,>0",
                  isUnfold: 1,
                  childNode: [
                    {
                      id: 1111111,
                      level: 3,
                      name: "0ge",
                      count: 0,
                      isUnfold: 0,
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: 1,
                      isUnfold: 1,
                      childNode: [
                        {
                          id: 1111111,
                          level: 4,
                          name: "1ge",
                          count: 1,
                          isUnfold: 0,
                        },
                      ],
                    },
                    {
                      id: 1111111,
                      level: 3,
                      name: "1ge",
                      count: 1,
                      isUnfold: 0,
                    },
                  ],
                },
              ],
            },
          ],
          isUnfold: 1,
        },
      ];
      let fixedData = temporaryData.map((item) => {
        return this.traveTree(item);
      });
      console.log(fixedData, "fixedData");
      this.dataInfo = fixedData;
    },
// traveTree这里是给每个节点设置高度,
    traveTree(nodeInfo) {
      let childrenInfo = nodeInfo.childNode;
      if (!childrenInfo || childrenInfo.length == 0) {
        nodeInfo.height = 40;
      } else {
        childrenInfo.map((item) => {
          this.traveTree(item);
        });

        nodeInfo.height = childrenInfo.reduce((preV, n) => {
          return preV + n.height;
        }, 0);
      }
      return nodeInfo;
    },
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值