项目中需要一个iview框架的树形控件,需要里面包含以下功能
- 1、控件宽度可展开,可缩小
- 2、树形控件可搜索,并且定位到搜索的节点
- 3、控件可以一键勾选,一键取消
- 4、控件图标自定义
- 5、 点击最后一个节点时可以进入到二级节点,点击上一节点可返回
- 完整代码:
- listToTree文件
 
效果图:
 
具体实现
1、控件宽度可展开,可缩小
这个比较简单,就是控制控件的宽度
    // 放大
    expansion() {
      this.isZhankai = true;
      this.width = "422";
      this.$store.commit("compration/saveLeftWidth", this.isZhankai);
    },
    // 缩小
    packUp() {
      this.isZhankai = false;
      this.width = "230";
      this.$store.commit("compration/saveLeftWidth", this.isZhankai);
    },
2、树形控件可搜索,并且定位到搜索的节点
    //输入节点名称后按回车健搜索
    inputChange() {
      let exist = false;
      if (this.isShowTwo) {
        // 二级树形控件搜索
        let data = JSON.parse(JSON.stringify(this.treeDataRowTwo));
        for (var i = 0; i < data.length; i++) {
          if (data[i].title.indexOf(this.value) !== -1) {
            //在树中存在
            exist = true;
            this.currentId = data[i].id;
            /*需要重新获取treeDataRowTwo,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            data = JSON.parse(JSON.stringify(this.treeDataRowTwo));
            this.treeDataTwo = listToTree(data);
            /*需要重新获取treeDataRowTwo,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeDataTwo = this.fineCurrentIdRecursive(this.treeDataTwo);
            break;
          } else if (!exist && i === data.length - 1) {
            //在树中不存在
            this.$Message.error("无搜索结果");
          }
        }
      } else {
        // 一级树形控件搜索
        for (var i = 0; i < this.treeRawData.length; i++) {
          if (this.treeRawData[i].title.indexOf(this.value) !== -1) {
            //在树中存在
            exist = true;
            this.currentId = this.treeRawData[i].id;
            /*需要重新获取treeRawData,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeRawData = JSON.parse(JSON.stringify(this.authTreeData));
            this.treeData = listToTree(this.treeRawData);
            /*需要重新获取treeRawData,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeData = this.fineCurrentIdRecursive(this.treeData);
            break;
          } else if (!exist && i === this.treeRawData.length - 1) {
            //在树中不存在
            this.$Message.error("无搜索结果");
          }
        }
      }
    },
    //通过节点id选中树中节点并展开它的父节点-递归方式
    fineCurrentIdRecursive(list) {
      for (var i = 0; i < list.length; i++) {
        if (list[i].id === this.currentId) {
          list[i].selected = true; //如果节点id等于currentId,则选中该节点
          break;
        } else {
          if (list[i].children && list[i].children.length > 0) {
            list[i].children = this.fineCurrentIdRecursive(list[i].children); //找不到想要的节点则继续找孩子的(递归)
            for (var j = 0; j < list[i].children.length; j++) {
              if (list[i].children[j].selected || list[i].children[j].expand) {
                list[i].expand = true; //如果子节点(末端节点)选中或者子节点(非末端节点)展开,则展开该子节点的父节点
                break;
              }
            }
          }
        }
      }
      return list;
    },
3、控件可以一键勾选,一键取消
  // 全选按钮
    handleCheckAll(val) {
      this.indeterminate = false;
      if (val) {
        let arr = this.treeData;
        const addKey = arr =>
          arr.map(item => ({
            ...item,
            checked: true,
            children: item.children ? addKey(item.children) : [] // 这里要判断原数据有没有子级如果没有判断会报错
          }));
        this.treeData = addKey(arr);
      } else {
        let arr = this.treeData;
        const addKey = arr =>
          arr.map(item => ({
            ...item,
            checked: false,
            children: item.children ? addKey(item.children) : [] // 这里要判断原数据有没有子级如果没有判断会报错
          }));
        this.treeData = addKey(arr);
      }
      // 全选的ids
      if (this.checkAll) {
        this.ids = [];
        this.authTreeData.forEach(k => {
          this.ids.push(k.id);
        });
        this.removeDuplicate(this.ids);
      } else {
        this.ids = [];
      }
      this.$emit("changePower", this.ids);
    },
  // 树形控件勾选多选框
    checkChange(data) {
      // 半选
      if (data.length === this.authTreeData.length) {
        this.indeterminate = false;
        this.checkAll = true;
      } else if (data.length > 0) {
        this.indeterminate = true;
        this.checkAll = false;
      } else {
        this.indeterminate = false;
        this.checkAll = false;
      }
      this.ids = [];
      data.forEach(k => {
        this.ids.push(k.id);
      });
      this.removeDuplicate(this.ids);
      this.$emit("changePower", this.ids);
    },
4、控件图标自定义
    // 自定义树结构图标
    renderContent(h, { root, node, data }) {
      return h("span", [
        h(
          "Tooltip",
          {
            props: {
              placement: "top",
              transfer: true
            }
          },
          [
            h(
              "span",
              {
                slot: "content",
                style: {
                  whiteSpace: "normal"
                }
              },
              data.title
            ),
            h("img", {
              attrs: {
                src:
                  data.parentId === 0
                    ? this.yiji
                    : data.children === undefined || data.children.length === 0
                    ? this.sanji
                    : this.erji
              },
              style: {
                marginRight: "8px",
                width: "16px",
                height: "16px"
              }
            }),
            h(
              "span",
              {
                style: {
                  fontSize: "14px",
                  width: this.width === "230" ? "89px" : "",
                  overflow: this.width === "230" ? "hidden" : "inherit",
                  textOverflow: this.width === "230" ? "ellipsis" : "inherit"
                }
              },
              data.title
            )
          ]
        )
      ]);
    },
    renderContentTwo(h, { root, node, data }) {
      return h("span", [
        h(
          "Tooltip",
          {
            props: {
              placement: "top",
              transfer: true
            }
          },
          [
            h(
              "span",
              {
                slot: "content",
                style: {
                  whiteSpace: "normal"
                }
              },
              data.title
            ),
            h("img", {
              attrs: {
                src:
                  data.parentId === this.powerId
                    ? this.one
                    : data.children === undefined || data.children.length === 0
                    ? this.three
                    : this.two
              },
              style: {
                marginRight: "8px",
                width: "16px",
                height: "16px",
                verticalAlign: "text-top"
              }
            }),
            h(
              "span",
              {
                style: {
                  fontSize: "14px",
                  width: this.width === "230" ? "89px" : "",
                  overflow: this.width === "230" ? "hidden" : "inherit",
                  textOverflow: this.width === "230" ? "ellipsis" : "inherit"
                }
              },
              data.title
            )
          ]
        )
      ]);
    },
5、 点击最后一个节点时可以进入到二级节点,点击上一节点可返回
    // 点击节点展开收缩
    selectChange(data, selectedNode) {
      this.$set(selectedNode, "expand", !selectedNode.expand);
        // 二级树形的标题
      this.twoTitle = data[0].title;
      // 获取选择节点的id
      this.powerId = data[0].id;
      this.$emit("domainId", this.powerId, this.twoTitle);
      if (this.isTwo) {
        if (data[0].children === undefined || data[0].children.length === 0) {
          this.isSearch = false;
          this.checkAll = false;
          this.value = "";
          this.isShowTwo = true;
          // 二级树形结构处理
          this.treeDataTwo = this.transitionToTree(
            JSON.parse(JSON.stringify(this.treeDataRowTwo)),
            1
          );
        } else {
          this.isShowTwo = false;
        }
      }
    },
    selectChangeTwo(data, selectedNode) {
      this.$set(selectedNode, "expand", !selectedNode.expand);
    },
完整代码:
父组件
      <leftTree
        @changePower="changePower"
        @domainId="domainId"
        :showCheckBox="true"
        :isCheckAll="true"
        :isTwo="true"
        :isExpand="true"
      ></leftTree>
子组件
<template>
  <div class="leftTree" :style="'width:' + width + 'px'">
    <div class="powerList">
      <div class="initPower" v-if="!isSearch">
        <div v-if="isShowTwo" class="twoDianZhan">
          <div style="margin-right:5px; cursor: pointer;" @click="back">
            <
          </div>
          <div>{{ twoTitle }}</div>
        </div>
        <div v-if="!isShowTwo" class="dianzhanliebiao">肖战影视作品</div>
        <div style="display: flex;justify-content: center;align-items: center;">
          <Tooltip content="搜索">
            <img
              class="img"
              @click="search"
              src="../../assets/images/overview/sousuo.svg"
              alt=""
            />
          </Tooltip>
          <Tooltip content="放大">
            <img
              class="img"
              @click="expansion"
              v-show="!isZhankai"
              src="../../assets/images/overview/zhankai.svg"
              alt=""
            />
          </Tooltip>
          <Tooltip content="缩小">
            <img
              class="img"
              @click="packUp"
              v-show="isZhankai"
              src="../../assets/images/overview/shouqi.svg"
              alt=""
            />
          </Tooltip>
          <Tooltip content="全选" v-if="isShowCheckAll">
            <Checkbox
              @on-change="handleCheckAll"
              v-model="checkAll"
              :indeterminate="indeterminate"
              style="margin-left: 10px;margin-right: 0;margin-bottom: 0;"
            ></Checkbox>
          </Tooltip>
        </div>
      </div>
      <div v-if="isSearch" class="searchPower">
        <Input
          ref="power"
          v-model="value"
          placeholder="请输入电站"
          style="width: 180px"
          @on-blur="inputBlur"
          @on-clear="inputClear"
          @on-enter="inputChange"
        />
      </div>
    </div>
    <div class="powerTree">
      <Tree
        v-if="isShowTwo"
        :data="treeDataTwo"
        :show-checkbox="true"
        :render="renderContentTwo"
        @on-select-change="selectChangeTwo"
        @on-check-change="checkChangeTwo"
      ></Tree>
      <Tree
        v-if="!isShowTwo"
        :data="treeData"
        :show-checkbox="showCheck"
        :render="renderContent"
        @on-select-change="selectChange"
        @on-check-change="checkChange"
      ></Tree>
    </div>
  </div>
</template>
<script>
import { listToTree } from "./../../utils/tree";
export default {
  name: "leftTree",
  components: {},
  props: {
    // 是否显示树形多选框
    showCheckBox: {
      type: Boolean,
      default: true
    },
    // 是否全选
    isCheckAll: {
      type: Boolean,
      default: true
    },
    // 集控中心是否展开
    isExpand: {
      type: Boolean,
      default: false
    },
    // 是否显示二级树形控件
    isTwo: {
      type: Boolean,
      default: false
    }
  },
  data() {
    return {
      // 是否全选
      isShowCheckAll: this.isCheckAll,
      // 是否显示树形多选框
      showCheck: this.showCheckBox,
      // 全选半选
      indeterminate: false,
      // 全选绑定数据
      checkAll: false,
      // 树形控件原始数据
      authTreeData: [
        {
          id: 1,
          title: "肖战",
          parentId: 0
        },
        {
          id: 2,
          title: "现代剧",
          parentId: 1
        },
        {
          id: 3,
          title: "古装剧",
          parentId: 1
        },
        {
          id: 4,
          title: "《余生,请多指教》",
          parentId: 2
        },
        {
          id: 5,
          title: "《梦中那片海》",
          parentId: 2
        },
        {
          id: 6,
          title: "《王牌部队》",
          parentId: 2
        },
        {
          id: 7,
          title: "《超星星学园》",
          parentId: 2
        },
        {
          id: 8,
          title: "《陈情令》",
          parentId: 3
        },
        {
          id: 9,
          title: "《狼殿下》",
          parentId: 3
        },
        {
          id: 10,
          title: "《玉骨遥》",
          parentId: 3
        },
        {
          id: 11,
          title: "《哦,我的皇帝陛下》",
          parentId: 3
        },
        {
          id: 12,
          title: "《斗罗大陆》",
          parentId: 3
        }
      ],
      // 电站搜索绑定数据
      value: "",
      // 展开缩小宽度
      width: "230",
      // 展开
      isZhankai: false,
      // 搜索
      isSearch: false,
      // 勾选的节点数据
      ids: [],
      currentId: "", //需要选中的节点id
      treeData: [], //前端处理后的数据
      // 树形控件过渡数据
      treeRawData: [],
      // 树形控件自定义图标
      yiji: require("../../assets/images/overview/yijitubiao.svg"),
      erji: require("../../assets/images/overview/erjitubiao.svg"),
      sanji: require("../../assets/images/overview/sanjitubiao.svg"),
      // 树形控件自定义图标
      // 二级树形控件数据
      isShowTwo: false,
      twoTitle: "",
      // 二级树形控件数据
      treeDataTwo: [],
      // 二级树形控件处理数据
      treeDataRowTwo: [
        {
          id: 2,
          title: "音乐",
          parentId: 1
        },
        {
          id: 3,
          title: "广告",
          parentId: 1
        },
        {
          id: 4,
          title: "光点",
          parentId: 2
        },
        {
          id: 5,
          title: "最幸运的幸运",
          parentId: 2
        },
        {
          id: 6,
          title: "余年",
          parentId: 2
        },
        {
          id: 7,
          title: "满足",
          parentId: 2
        },
        {
          id: 8,
          title: "余生,请多指教",
          parentId: 2
        },
        {
          id: 9,
          title: "问少年",
          parentId: 2
        },
        {
          id: 10,
          title: "等等",
          parentId: 2
        },
        {
          id: 11,
          title: "TOD‘S",
          parentId: 3
        },
        {
          id: 12,
          title: "GUCCI",
          parentId: 3
        },
        {
          id: 13,
          title: "真力时",
          parentId: 3
        },
        {
          id: 14,
          title: "石头科技",
          parentId: 3
        },
        {
          id: 15,
          title: "倍轻松",
          parentId: 3
        },
        {
          id: 16,
          title: "开小灶",
          parentId: 3
        },
        {
          id: 17,
          title: "等等",
          parentId: 3
        }
      ],
      one: require("../../assets/images/overview/one.svg"),
      two: require("../../assets/images/overview/two.svg"),
      three: require("../../assets/images/overview/three.svg"),
      powerId: ""
      // 二级树形控件数据
    };
  },
  created() {
    this.getData();
  },
  mounted() {
    this.$store.state.compration.isZhankai = this.isZhankai;
  },
  methods: {
    // 全选按钮
    handleCheckAll(val) {
      this.indeterminate = false;
      if (val) {
        let arr = this.treeData;
        const addKey = arr =>
          arr.map(item => ({
            ...item,
            checked: true,
            children: item.children ? addKey(item.children) : [] // 这里要判断原数据有没有子级如果没有判断会报错
          }));
        this.treeData = addKey(arr);
      } else {
        let arr = this.treeData;
        const addKey = arr =>
          arr.map(item => ({
            ...item,
            checked: false,
            children: item.children ? addKey(item.children) : [] // 这里要判断原数据有没有子级如果没有判断会报错
          }));
        this.treeData = addKey(arr);
      }
      // 全选的ids
      if (this.checkAll) {
        this.ids = [];
        this.authTreeData.forEach(k => {
          this.ids.push(k.id);
        });
        this.removeDuplicate(this.ids);
      } else {
        this.ids = [];
      }
      this.$emit("changePower", this.ids);
    },
    // tree树结构转换
    transitionToTree(data, rootValue) {
      // data是转换树形结构的数据源
      // rootValue是根节点的特征
      const parents = data.filter(item => item.parentId === rootValue); // 把所有顶级节点拆分出来
      const children = data.filter(item => item.parentId !== rootValue); // 把所有子级节点(无论多少级,二三四五六级..)拆分出来
      dataToTree(parents, children);
      function dataToTree(parents, children) {
        parents.map(p => {
          children.map((c, index) => {
            // 判断当前循环的子节点是否是当前循环父节点的子级
            if (c.parentId === p.id) {
              let newChildren = JSON.parse(JSON.stringify(children));
              newChildren.splice(index, 1);
              dataToTree([c], newChildren);
              // 如果是当前循环父节点的子级,那就看父节点有没有children属性,
              // 如果有就push到children属性的数组,
              // 如果没有就给父节点一个children属性并把当前循环的子级放进去
              if (p.children) {
                p.children.push(c);
              } else {
                p.children = [c];
              }
            }
          });
        });
      }
      return parents;
    },
    // 自定义树结构图标
    renderContent(h, { root, node, data }) {
      return h("span", [
        h(
          "Tooltip",
          {
            props: {
              placement: "top",
              transfer: true
            }
          },
          [
            h(
              "span",
              {
                slot: "content",
                style: {
                  whiteSpace: "normal"
                }
              },
              data.title
            ),
            h("img", {
              attrs: {
                src:
                  data.parentId === 0
                    ? this.yiji
                    : data.children === undefined || data.children.length === 0
                    ? this.sanji
                    : this.erji
              },
              style: {
                marginRight: "8px",
                width: "16px",
                height: "16px"
              }
            }),
            h(
              "span",
              {
                style: {
                  fontSize: "14px",
                  width: this.width === "230" ? "89px" : "",
                  overflow: this.width === "230" ? "hidden" : "inherit",
                  textOverflow: this.width === "230" ? "ellipsis" : "inherit"
                }
              },
              data.title
            )
          ]
        )
      ]);
    },
    renderContentTwo(h, { root, node, data }) {
      return h("span", [
        h(
          "Tooltip",
          {
            props: {
              placement: "top",
              transfer: true
            }
          },
          [
            h(
              "span",
              {
                slot: "content",
                style: {
                  whiteSpace: "normal"
                }
              },
              data.title
            ),
            h("img", {
              attrs: {
                src:
                  data.parentId === this.powerId
                    ? this.one
                    : data.children === undefined || data.children.length === 0
                    ? this.three
                    : this.two
              },
              style: {
                marginRight: "8px",
                width: "16px",
                height: "16px",
                verticalAlign: "text-top"
              }
            }),
            h(
              "span",
              {
                style: {
                  fontSize: "14px",
                  width: this.width === "230" ? "89px" : "",
                  overflow: this.width === "230" ? "hidden" : "inherit",
                  textOverflow: this.width === "230" ? "ellipsis" : "inherit"
                }
              },
              data.title
            )
          ]
        )
      ]);
    },
    back() {
      this.isShowTwo = false;
    },
    // 点击节点展开收缩
    selectChange(data, selectedNode) {
      this.$set(selectedNode, "expand", !selectedNode.expand);
      // 二级树形的标题
      this.twoTitle = data[0].title;
      // 获取选择节点的id
      this.powerId = data[0].id;
      this.$emit("domainId", this.powerId, this.twoTitle);
      if (this.isTwo) {
        if (data[0].children === undefined || data[0].children.length === 0) {
          //
          this.isSearch = false;
          this.checkAll = false;
          this.value = "";
          this.isShowTwo = true;
          // 二级树形结构处理
          this.treeDataTwo = this.transitionToTree(
            JSON.parse(JSON.stringify(this.treeDataRowTwo)),
            1
          );
        } else {
          this.isShowTwo = false;
        }
      }
    },
    selectChangeTwo(data, selectedNode) {
      this.$set(selectedNode, "expand", !selectedNode.expand);
    },
    checkChangeTwo(data) {
      this.ids = [];
      data.forEach(k => {
        if (k.name) {
          this.ids.push({
            unit: k.unit,
            name: k.name,
            title: k.title
          });
        }
      });
      this.$emit("changePower", this.ids);
    },
    // 树形控件勾选多选框
    checkChange(data) {
      // 半选
      if (data.length === this.authTreeData.length) {
        this.indeterminate = false;
        this.checkAll = true;
      } else if (data.length > 0) {
        this.indeterminate = true;
        this.checkAll = false;
      } else {
        this.indeterminate = false;
        this.checkAll = false;
      }
      this.ids = [];
      data.forEach(k => {
        this.ids.push(k.id);
      });
      this.removeDuplicate(this.ids);
      this.$emit("changePower", this.ids);
    },
    //输入节点名称后按回车健搜索
    inputChange() {
      let exist = false;
      if (this.isShowTwo) {
        // 二级树形控件搜索
        let data = JSON.parse(JSON.stringify(this.treeDataRowTwo));
        for (var i = 0; i < data.length; i++) {
          if (data[i].title.indexOf(this.value) !== -1) {
            //在树中存在
            exist = true;
            this.currentId = data[i].id;
            /*需要重新获取treeDataRowTwo,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            data = JSON.parse(JSON.stringify(this.treeDataRowTwo));
            this.treeDataTwo = listToTree(data);
            /*需要重新获取treeDataRowTwo,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeDataTwo = this.fineCurrentIdRecursive(this.treeDataTwo);
            break;
          } else if (!exist && i === data.length - 1) {
            //在树中不存在
            this.$Message.error("无搜索结果");
          }
        }
      } else {
        // 一级树形控件搜索
        for (var i = 0; i < this.treeRawData.length; i++) {
          if (this.treeRawData[i].title.indexOf(this.value) !== -1) {
            //在树中存在
            exist = true;
            this.currentId = this.treeRawData[i].id;
            /*需要重新获取treeRawData,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeRawData = JSON.parse(JSON.stringify(this.authTreeData));
            this.treeData = listToTree(this.treeRawData);
            /*需要重新获取treeRawData,不然会出现这种情况:数据是对的,但是视图渲染不出来,导致没有搜索结果*/
            this.treeData = this.fineCurrentIdRecursive(this.treeData);
            break;
          } else if (!exist && i === this.treeRawData.length - 1) {
            //在树中不存在
            this.$Message.error("无搜索结果");
          }
        }
      }
    },
    //通过节点id选中树中节点并展开它的父节点-递归方式
    fineCurrentIdRecursive(list) {
      for (var i = 0; i < list.length; i++) {
        if (list[i].id === this.currentId) {
          list[i].selected = true; //如果节点id等于currentId,则选中该节点
          break;
        } else {
          if (list[i].children && list[i].children.length > 0) {
            list[i].children = this.fineCurrentIdRecursive(list[i].children); //找不到想要的节点则继续找孩子的(递归)
            for (var j = 0; j < list[i].children.length; j++) {
              if (list[i].children[j].selected || list[i].children[j].expand) {
                list[i].expand = true; //如果子节点(末端节点)选中或者子节点(非末端节点)展开,则展开该子节点的父节点
                break;
              }
            }
          }
        }
      }
      return list;
    },
    // 电站获取数据
    getData() {
      this.treeRawData = JSON.parse(JSON.stringify(this.authTreeData));
      this.treeData = this.transitionToTree(this.treeRawData, 0);
      if (this.isExpand) {
        this.treeData.forEach(k => {
          if (k.title === "肖战") {
            k.expand = true;
          }
        });
      }
    },
    // 去重
    removeDuplicate(arr) {
      let len = arr.length;
      for (let i = 0; i < len; i++) {
        for (let j = i + 1; j < len; j++) {
          if (arr[i] === arr[j]) {
            arr.splice(j, 1);
            len--; // 减少循环次数提高性能
            j--; // 保证j的值自加后不变
          }
        }
      }
      return arr;
    },
    // 放大
    expansion() {
      this.isZhankai = true;
      this.width = "422";
      this.$store.commit("compration/saveLeftWidth", this.isZhankai);
    },
    // 缩小
    packUp() {
      this.isZhankai = false;
      this.width = "230";
      this.$store.commit("compration/saveLeftWidth", this.isZhankai);
    },
    // 列表搜索
    search() {
      this.isSearch = true;
      this.$nextTick(() => {
        this.$refs.power.focus();
      });
    },
    // 失去焦点显示
    inputBlur() {
      if (this.value === "") {
        this.isSearch = false;
      }
    },
    // 清除搜索框
    inputClear() {
      this.isSearch = false;
      this.value = "";
    }
  }
};
</script>
<style lang="scss" scoped>
::v-deep .ivu-input {
  width: 100% !important;
}
.leftTree {
  height: 100%;
  .powerList {
    height: 52px;
    background-color: #fff;
    margin-bottom: 1px;
    padding: 0 16px;
    display: flex;
    align-items: center;
    .initPower {
      width: 100%;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: space-between;
    }
    .img {
      cursor: pointer;
      margin-left: 10px;
    }
    .twoDianZhan {
      display: flex;
      font-family: PingFangSC-Medium;
      font-size: 14px;
      color: #3d3d3d;
    }
    .dianzhanliebiao {
      font-family: PingFangSC-Medium;
      font-size: 14px;
      color: #3d3d3d;
    }
  }
  .powerTree {
    height: calc(100% - 53px);
    background-color: #fff;
  }
}
::v-deep .ivu-tooltip-rel {
  display: flex;
  align-items: center;
}
::v-deep .ivu-tree {
  height: 100%;
  overflow-y: auto;
}
::v-deep .ivu-tree-children .ivu-checkbox-wrapper {
  position: absolute;
  right: 30px;
  top: 5px;
}
::v-deep .ivu-tree-children li {
  &::before {
    content: none !important;
  }
  &::after {
    content: none !important;
  }
}
::v-deep .ivu-tree .ivu-tree-children li .ivu-tree-arrow .ivu-icon {
  &::before {
    content: "\f11f" !important;
    border: none;
    top: 2px;
    transition: all 0.2s ease-in-out;
    -webkit-transition: all 0.2s ease-in-out;
  }
}
::v-deep .ivu-tree .ivu-tree-children li .ivu-tree-arrow-open .ivu-icon {
  &::before {
    -webkit-transform: rotate(90deg);
    transform: rotate(90deg);
    transition: all 0.2s ease-in-out;
    -webkit-transition: all 0.2s ease-in-out;
  }
}
</style>
listToTree文件
//将后端返回的list数据转化为树结构
export const listToTree = list => {
  var arr = [];
  let items = {};
  var idsStr = "";
  let array = [];
  // 获取每个节点的直属子节点(是直属,不是所有子节点)
  for (let i = 0; i < list.length; i++) {
    let key = list[i].parentId;
    if (items[key]) {
      items[key].push(list[i]);
    } else {
      items[key] = [];
      items[key].push(list[i]);
    }
    array.push(list[i].id);
    // idsStr += idsStr === "" ? list[i].id : "," + list[i].id;
  }
  for (var key in items) {
    if (array.indexOf(Number(key)) === -1) {
      //找到最大的父节点key
      arr = formatTree(items, Number(key));
    }
  }
  delete arr[0].parentId;
  return arr;
};
function formatTree(items, parentId) {
  let result = [];
  if (!items[parentId]) {
    return result;
  }
  for (let t of items[parentId]) {
    t.children = formatTree(items, t.id); //递归获取children
    result.push(t);
  }
  return result;
}



















