tree的自定义功能-重命名,添加,删除

<el-tree
            class="filter-tree"
            :data="treeList"
            :props="defaultProps"
            :filter-node-method="filterNode"
            :highlight-current="true"
            :expand-on-click-node="false"
            ref="tree"
            :key="reload"
            node-key="treeId"
            :draggable="true"
            :allow-drop="allowDrop"
            @node-drop="handleDrop"
            :default-expand-all="false"
            :default-expanded-keys="defaultExpandedKeys"
            @node-expand="getNodeExpand"
            @node-collapse="getNodeCollapse"
          >
            <template #default="{ node, data }">
              <div class="node-item">
                <span v-if="data.indexId == 0 || data.isRename">
                  <el-input
                    v-model.trim="data.label"
                    placeholder="请输入"
                    @blur="changeFolder(node, data)"
                    :disabled="!data.isRename && data.type == 2"
                    maxlength="30"
                  ></el-input>
                </span>
                <div v-else @click="handleNodeClick(data)" class="label-set">
                  <label>
                    <i v-if="data.type === 1" class="el-icon-folder-opened"></i>
                    <i
                      v-else-if="data.type === 2"
                      class="el-icon-notebook-2"
                    ></i>
                    <i v-else class="el-icon-document"></i
                  ></label>
                  <label v-if="!ifCollapse">{{ data.label }}</label>
                </div>

                <el-popover placement="bottom" width="200" trigger="click">
                  <div
                    style="
                      display: flex;
                      flex-direction: column;
                      align-items: baseline;
                    "
                  >
                    <el-button
                      v-if="data.type == 1"
                      type="text"
                      v-no-more-click
                      @click="addChildDirectory(node, data)"
                      >文件夹</el-button
                    >
                    <el-button
                      v-if="data.type == 1"
                      type="text"
                      v-no-more-click
                      @click="addChildrenForm(node, data)"
                      >表单</el-button
                    >
                    <el-button
                      type="text"
                      v-no-more-click
                      @click="handleRename(node, data, true)"
                      >重命名</el-button
                    >
                  </div>
                  <i
                    v-if="isUpdate"
                    slot="reference"
                    class="el-icon-circle-plus-outline show-btn"
                  ></i>
                </el-popover>
              </div>
            </template>
          </el-tree>
watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    }
  },

data() {
    return {
      ifCollapse: false,
      filterText: '',
      treeList: [],
      defaultProps: {
        children: 'children',
        id: 'treeId'
      },
      isUpdate: 0, //是否有权限,主要为管理员1,非管0
      isShow: false,
      reload: 0,
      folderId: null,
      defaultExpandedKeys: [],
      allCollectionInfo: []
    };
  },
 //节点被展开时触发的事件
    getNodeExpand(data, node, event) {
      let keyId = data.type + '' + data.indexId;
      this.defaultExpandedKeys.push(keyId);
    },
    getAllTreeId(data, treeIdArr) {
      treeIdArr.push(data.treeId);

      if (data.children && data.children.length > 0) {
        for (let n in data.children) {
          let item = data.children[n];
          this.getAllTreeId(item, treeIdArr);
        }
      }
    },
    getNodeCollapse(data, node, event) {
      let treeIdArr = [];
      this.getAllTreeId(data, treeIdArr);

      treeIdArr.forEach((treeId) => {
        let arr = JSON.parse(JSON.stringify(this.defaultExpandedKeys));
        this.defaultExpandedKeys = arr.filter((item) => item != treeId);
      });
    },
    // 筛选
    filterNode(value, data, node) {
      if (!value) return true;
      let _array = []; //这里使用数组存储 只是为了存储值。
      this.getReturnNode(node, _array, value);

      let result = false;
      _array.forEach((item) => {
        result = result || item;
      });

      return result;
    },
    getReturnNode(node, _array, value) {
      let isPass =
        node.data && node.data.label && node.data.label.indexOf(value) !== -1;
      isPass ? _array.push(isPass) : '';
      if (!isPass && node.level != 1 && node.parent) {
        this.getReturnNode(node.parent, _array, value);
      }
    },
    // 拖拽成功完成时触发的事件
    async handleDrop(draggingNode, dropNode, dropType, ev) {
      // 对treeData中的每一个节点调用上面的函数
      // for (let index in this.treeList) {
      //   let child = this.treeList[index];
      //   this.sortAllNode(child, index);
      // }
      let res = await reSort({ folderList: this.treeList });
      // 刷新目录
      this.configurationList();
    },
 allowDrop(draggingNode, dropNode, type) {
      // 当拖动类型为平级移动到前或者后
      if (this.isUpdate === 1) {
        if (type === 'prev' || type === 'next') {
          if (draggingNode.data.type === 1 || draggingNode.data.type === 2) {
            if (dropNode.data.type !== 3) {
              return true;
            }
          } else if (draggingNode.data.type === 3) {
            if (
              dropNode.data.type === 3 &&
              draggingNode.data.parentId === dropNode.data.parentId
            ) {
              return true;
            }
          }
          // 当拖动类型为拖入内部
        } else if (type === 'inner') {
          if (draggingNode.data.type === 1 || draggingNode.data.type === 2) {
            if (dropNode.data.type === 1) {
              return true;
            }
          }
        }
      }

      return false;
    },
    changeIsRename(data, keyStr, value) {
      let key = data.type + '' + data.indexId; // 当前点击的节点ID ,唯一标志

      // 检查当前节点的ID是否与目标ID匹配
      if (key === keyStr) {
        // 如果匹配,将新数据添加到该节点的children数组中
        this.$set(data, 'isRename', value);

        return;
      }

      // 如果当前节点有子节点,则递归遍历子节点
      if (data.children && data.children.length > 0) {
        for (let child of data.children) {
          this.changeIsRename(child, keyStr, value);
        }
      }
    },
    // 点击重命名按钮
    handleRename(node, data, value) {
      let keyStr = data.type + '' + data.indexId; // 当前点击的节点ID ,唯一标志

      // 对treeData中的每一个节点调用上面的函数
      for (let data of this.treeList) {
        this.changeIsRename(data, keyStr, value);
      }
      // 记录展开的节点

      // 改变数据时更新树
      this.reload = Math.random();
      let parentType = '';
      if (data.type === 1) {
        parentType = 1;
      } else if (data.type === 2) {
        parentType = 1;
      } else if (data.type === 3) {
        parentType = 2;
      }
      this.defaultExpandedKeys = [parentType + '' + data.parentId];
    },
    // 修改文件夹(名字)
    async rename(node, data) {
      let params = {
        indexId: data.indexId,
        label: data.label,
        type: data.type
      };
      let res = await rename(params);

      if (data.type != 1) {
        this.isShow = true;

        this.$nextTick(() => {
          // isShow控制了子组件的显示和隐藏,所以需要加一个nexttick
          this.$refs.rightCom.$emit('handleNodeClick', data); //调用子组件在点击目录时获取子组件的数据
        });
      }
    },
    // 添加文件夹
    async addFolder(node, data) {
      let params = {
        folderName: data.label,
        parentId: data.parentId,
        folderOrder: data.folderOrder
      };

      let res = await addFolder(params);
    },
    hasWhiteSpace(s) {
      return /\s/g.test(s);
    },
    // 输入框失焦
    async changeFolder(node, data) {
      if (!this.hasWhiteSpace(data.label)) {
        if (data.indexId) {
          await this.rename(node, data);
        } else {
          await this.addFolder(node, data);
        }
        await this.configurationList();
        await this.handleRename(node, data, false);
        // this.$nextTick(() => {
        //   // 新增时展开改文件夹
        //   this.$refs.tree.store.nodesMap[data.treeId].expanded = true;
        // });
      } else {
        this.$message.warning('不能输入空格');
      }
    },
    async configurationList(value) {
      const res = await configurationList();

      this.treeList = res.data.folderList;

      this.allCollectionInfo = JSON.parse(JSON.stringify(res.data.folderList));
      // isRename
      this.isUpdate = res.data.isUpdate;
      localStorage.setItem('isUpdate', this.isUpdate);
      function addIsRenameProperty(nodes) {
        nodes.forEach((node) => {
          node.isRename = false; // 初始化时设为false
          // 为每个节点做一个唯一值
          node.treeId = node.type + '' + node.indexId;
          if (node.children) {
            addIsRenameProperty(node.children); // 递归处理子节点
          }
        });
      }

      // 对初始数据执行添加isRename属性的操作
      addIsRenameProperty(this.treeList);

      this.$nextTick(() => {
        value && this.defaultExpandedKeys.push(value);
        this.defaultExpandedKeys = Array.from(
          new Set(this.defaultExpandedKeys)
        );
      });
    },

    // filterNode(value, data) {
    //   if (!value) return true;
    //   return data.label.indexOf(value) !== -1;
    // },
    handleCollapse() {
      this.ifCollapse = !this.ifCollapse;
    },
    handleNodeClick: debounce(function (data) {
      //默认展开的节点清空,当添加的时候才会赋值
      // this.defaultExpandedKeys = [];
      this.folderId = data.parentId ? data.parentId : 0;

      if (data.type != 1) {
        this.isShow = true;

        this.$nextTick(() => {
          // isShow控制了子组件的显示和隐藏,所以需要加一个nexttick

          this.$refs.rightCom.$emit('handleNodeClick', data); //调用子组件在点击目录时获取子组件的数据
        });
      }
    }, 1000),
// 点击左侧加号添加表单,
    addForm() {
      // 左侧出现输入框文件夹
      this.folderId = null;

      const newNode = {
        id: '',
        folderName: '',
        type: 2,
        order: '',
        label: '未命名表单',
        indexId: 0,
        parentId: '',
        children: [],
        folderOrder: this.treeList.length
      }; // 创建新节点对象
      this.treeList.unshift(newNode);
      // 右侧表单界面出现
      this.addRightForm();
    },
    // 右侧表单界面出现
    addRightForm() {
      this.isShow = true;
      this.$nextTick(() => {
        this.$refs.rightCom.addForm(); // 调用子组件在新建时清理子组件的数据
      });
    },

    addDirectory() {
      this.folderId = null;
      const newNode = {
        id: '',
        folderName: '',
        type: 1,
        order: '',
        label: '未命名文件夹',
        indexId: 0,
        parentId: '',
        children: [],
        folderOrder: this.treeList.length
      }; // 创建新节点对象
      this.treeList.unshift(newNode);
    },
    addNode(parentNode, data) {
      const childNodes = parentNode.data.children;
      childNodes.push(data);
      // this.$forceUpdate(); // 强制重新渲染组件,使新节点生效
    },
    // 目录内部添加表单
    addChildrenForm(node, data) {
      this.folderId = data.id ? data.id : 0;

      // 右侧出现新表单页面相关代码
      this.addRightForm();
      // 左侧出现输入框相关代码
      let keyStr = data.type + '' + data.indexId; // 当前点击的节点ID ,唯一标志
      const newNode = {
        // id: Date.now(),
        folderName: '',
        type: 2,
        order: '',
        label: '未命名表单',
        indexId: 0,
        children: []
      }; // 创建新节点对象 // 新的子节点数据

      // 对treeData中的每一个节点调用上面的函数
      for (let data of this.treeList) {
        this.findNodeAndAddChild(data, keyStr, newNode);
      }
      this.$nextTick(() => {
        //   // 新增时展开改文件夹

        this.$refs.tree.store.nodesMap[data.treeId].expanded = true;
      });
    },
    expandTreeNode(node, resolve) {
      // if (node.level === 0) {
      // return resolve(node.data);
      // }
      // if (node.data.childGetFlag === 0) {
      //   // 未取得子节点
      //   // 此处自定义取得方法;
      // } else {
      //   // 已取得子节点
      //   return resolve(node.data.children);
      // }
    },
    expandNode(node) {
      if (node.data.children.length === 0) {
        node.isLeaf = true; // 对于叶子节点,点击小三角后,小三角会消失。
      }
      node.expanded = true; // 展开节点
      node.loaded = true; // 标识:已加载
    },
    // 目录内部添加文件夹

    addChildDirectory(node, data) {
      // 展开当前节点

      let keyStr = data.type + '' + data.indexId; // 当前点击的节点ID ,唯一标志
      let newNode = {
        id: '',
        folderName: '',
        type: 1,
        order: '',
        label: '未命名文件夹',
        indexId: 0,
        parentId: data.id,
        children: [],
        folderOrder:
          data.children && data.children.length ? data.children.length : 0
      }; // 创建新节点对象 // 新的子节点数据

      // 对treeData中的每一个节点调用上面的函数
      for (let itemData of this.treeList) {
        this.findNodeAndAddChild(itemData, keyStr, newNode);
      }
      // this.expandNode(node);
      this.$nextTick(() => {
        // 重命名时展开改文件夹
        this.$refs.tree.store.nodesMap[data.treeId].expanded = true;
      });

      // this.reload = Math.random();
    },
    findNodeAndAddChild(data, keyStr, newNode) {
      let key = data.type + '' + data.indexId; // 当前点击的节点ID ,唯一标志

      // 检查当前节点的ID是否与目标ID匹配
      if (key === keyStr) {
        // 如果匹配,将新数据添加到该节点的children数组中
        data.children = data.children ? data.children : [];
        data.children.push(newNode);
        return;
      }

      // 如果当前节点有子节点,则递归遍历子节点
      if (data.children && data.children.length > 0) {
        for (let child of data.children) {
          this.findNodeAndAddChild(child, keyStr, newNode);
        }
      }
    }
posted @ 2024-04-09 16:32  sinceForever  阅读(386)  评论(0编辑  收藏  举报