el-tree addition, deletion and modification of secondary packaging

Recently, the company encountered adding, deleting, and modifying operations on the el-tree in element-ui. After returning the obtained data from the background, it was found that local changes cannot be made. Pay attention!!! After getting the data and performing a deep copy through the lodash plug-in, Operate the local data data, and transmit the local data data to the background after formatting.

component code

<template>
  <div class="lalala tree-container">
    <el-tree
      :data="treeData"
      node-key="id"
      default-expand-all
      @node-click="handleLeftclick"
      @node-drag-start="handleDragStart"
      @node-drag-enter="handleDragEnter"
      @node-drag-leave="handleDragLeave"
      @node-drag-over="handleDragOver"
      @node-drag-end="handleDragEnd"
      @node-drop="handleDrop"
      @node-contextmenu="rightClick"
      draggable
      :allow-drop="allowDrop"
      :allow-drag="allowDrag"
      ref="tree"
    >
      <span class="slot-t-node" slot-scope="{ node, data }">
        <span v-show="!data.isEdit">
          <span :class="[data.id >= 99 ? 'slot-t-node--label' : '']">{
    
    {
            node.label
          }}</span>
        </span>
        <span v-show="data.isEdit">
          <el-input
            class="slot-t-input"
            size="mini"
            autofocus
            v-model="data.label"
            :ref="'slotTreeInput' + data.id"
            @blur.stop="NodeBlur(node, data)"
            @keydown.native.enter="NodeBlur(node, data)"
          ></el-input>
        </span>
      </span>
    </el-tree>
    <el-card
      class="box-card"
      ref="card"
      v-show="menuVisible && dialogStatus != 'details'"
    >
      <div class="add" @click="addChildNode()" v-if="onlyShow">
        <i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;添加章节
      </div>

      <div @click="addSameLevelNode()" v-show="firstLevel">
        <i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;同级增加
      </div>
      <div class="add" @click="addChildNode()" v-if="firstLevel">
        <i class="el-icon-circle-plus-outline"></i>&nbsp;&nbsp;子级增加
      </div>
      <div class="upload" @click="uploadVideo" v-if="twoLevel">
        <i class="el-icon-upload2"></i>&nbsp;&nbsp;上传课程
      </div>
      <div class="delete" @click="deleteNode()" v-if="firstLevel || twoLevel">
        <i class="el-icon-remove-outline"></i>&nbsp;&nbsp;删除节点
      </div>
      <div class="edit" @click="editNode()" v-if="firstLevel">
        <i class="el-icon-edit"></i>&nbsp;&nbsp;修改节点
      </div>
    </el-card
    
  </div>
</template>
 
<script>
import _ from "lodash";
import { uploadFile } from "@/api/corres";
export default {
  props: {
    chapters: {
      type: Array,
      default: [],
    },
    dialogStatus: {
      type: String,
    },
  },
  watch: {
    chapters() {
      this.initTreeData();
    },
    treeData: {
      handler() {
        console.log(this.treeData);
        this.$emit("getTreeData", this.treeData[0].children);
      },
      deep: true,
    },
  },
  name: "tree",
  data() {
    return {
      rulesTree: {
        lessonName: [
          { required: true, message: "请输入课程名称", trigger: "blur" },
        ],
        lessonTime: [
          { required: true, message: "请输入课程时长", trigger: "blur" },
        ],
        lessonUrl: [{ required: true, message: "请上传视频", trigger: "blur" }],
      },
      entity: {
        lessonName: "",
        lessonTime: "",
      },
      dialogFormVisibleTree: false,
      onlyShow: false,
      eleId: "",
      isShow: false,
      currentData: "",
      currentNode: "",
      menuVisible: false,
      firstLevel: false,
      twoLevel: false,
      maxexpandId: 4,
      treeData: [
        {
          id: 0,
          label: "课程目录",
          children: [],
        },
      ],
      defaultProps: {
        children: "children",
        label: "label",
      },
    };
  },
  methods: {
    initTreeData() {
      let chapters = _.cloneDeep(this.chapters);
      chapters.forEach((item) => {
        item.label = item.chapterName;
        item.firstLevel = true;
        item.isEdit = false;
        item.lessons.forEach((i) => {
          i.label = i.lessonName;
          i.twoLevel = false;
          i.fileName = i.lessonName;
          i.lessonTime = +i.lessonTime.slice(0, i.lessonTime.indexOf("分钟"));
        });
        item.children = item.lessons;
      });
      this.$set(this.treeData[0], "children", chapters);
    },
    forceUpdate() {
      this.$forceUpdate();
    },
    // 上传视频
    async uploadLessonTree(file, type) {
      const qq = new FormData();
      qq.append("file", file.file);
      qq.append("type", 1);
      const res = await uploadFile(qq);
      console.log(res, "上传");
      // this.entity.url = res.fileUrl;
      this.$set(this.entity, "lessonUrl", res.fileUrl);
      this.$set(this.entity, "fileName", res.fileName);
      console.log(this.entity);
    },
    // 上传视频之前校验类型
    beforeUploadTree(file) {
      let FileExt = file.name.replace(/.+\./, "");
      let flag = ["mp4"].includes(FileExt);
      if (!flag) this.$message.error("文件格式错误请重新上传!");
      return flag;
    },
    // dialog 确定
    sureClickTree() {
      this.$refs.ruleForm.validate((valid) => {
        if (valid) {
          this.entity.isEdit = false;
          this.$set(this.currentData, "label", this.entity.lessonName);
          this.$set(this.currentData, "lessonUrl", this.entity.lessonUrl);
          this.$set(this.currentData, "lessonTime", this.entity.lessonTime);
          this.$set(this.currentData, "fileName", this.entity.lessonName);
          this.treeData[0].children.forEach((item) => {
            item.children.forEach((i) => {
              if (i.label == this.currentData.label) {
                i.lessonName = this.currentData.label;
                i.lessonUrl = this.currentData.lessonUrl;
                i.lessonTime = this.currentData.lessonTime;
                i.fileName = this.currentData.fileName;
                i.label = this.currentData.label;
              }
            });
          });
          console.log(this.treeData);
          this.dialogFormVisibleTree = false;
        }
      });
    },
    // 关闭dialog
    handleCloseTree() {
      this.dialogFormVisibleTree = false;
      this.entity = this.$options.data().entity;
    },
    NodeBlur(Node, data) {
      console.log(Node, data);
      if (data.label.length === 0) {
        this.$message.error("菜单名不可为空!");
        return false;
      } else {
        if (data.isEdit) {
          this.$set(data, "isEdit", false);
          console.log(data.isEdit);
        }
        this.$nextTick(() => {
          this.$refs["slotTreeInput" + data.id].$refs.input.focus();
        });
      }
    },

    allowDrop(draggingNode, dropNode, type) {
      console.log(draggingNode, dropNode);
      if (
        (draggingNode.level == 2 && dropNode.level == 1) ||
        (draggingNode.level == 2 && dropNode.level == 3) ||
        (draggingNode.level == 1 && dropNode.level == 2) ||
        (draggingNode.level == 3 && dropNode.level == 2) ||
        (draggingNode.level == 3 && dropNode.level == 4) ||
        (draggingNode.level == 3 && dropNode.level == 1)
      ) {
        return false;
      } else {
        return type === "prev" || type === "next";
      }
    },
    allowDrag(draggingNode) {
      return draggingNode.data.label.indexOf("三级 3-2-2") === -1;
    },
    // 鼠标右击事件
    rightClick(event, object, Node, element) {
      this.currentData = object;
      this.currentNode = Node;
      if (Node.level === 1) {
        this.onlyShow = true;
      } else {
        this.onlyShow = false;
      }
      if (Node.level === 2) {
        this.firstLevel = true;
      } else {
        this.firstLevel = false;
      }
      if (Node.level == 3) {
        this.twoLevel = true;
      } else {
        this.twoLevel = false;
      }
      this.menuVisible = true;
      // let menu = document.querySelector('#card')
      // /* 菜单定位基于鼠标点击位置 */
      // menu.style.left = event.clientX + 'px'
      // menu.style.top = event.clientY + 'px'
      document.addEventListener("click", this.foo);
      this.$refs.card.$el.style.left = event.clientX - 80 + "px";
      console.log(event.clientY + 400);
      this.$refs.card.$el.style.top = event.clientY - 600 + "px";
    },
    // 鼠标左击事件
    handleLeftclick(data, node) {
      this.foo();
    },
    //  取消鼠标监听事件 菜单栏
    foo() {
      this.menuVisible = false;
      //  要及时关掉监听,不关掉的是一个坑,不信你试试,虽然前台显示的时候没有啥毛病,加一个alert你就知道了
      document.removeEventListener("click", this.foo);
    },
    // 增加同级节点事件
    addSameLevelNode() {
      let id = Math.ceil(Math.random() * 100);
      var data = { id: id, label: "新增节点" };
      this.$refs.tree.append(data, this.currentNode.parent);
    },
    // 增加子级节点事件
    addChildNode() {
      console.log(this.currentData);
      console.log(this.currentNode);
      if (this.currentNode.level >= 3) {
        this.$message.error("最多只支持三级!");
        return false;
      }
      let id = Math.ceil(Math.random() * 100);
      var data = { id: id, label: "新增节点", children: [] };
      this.$refs.tree.append(data, this.currentNode);
    },
    // 删除节点
    deleteNode() {
      this.$refs.tree.remove(this.currentNode);
    },
    // 编辑节点
    editNode(data) {
      this.currentData = data ? data : this.currentData;
      if (!this.currentData.isEdit) {
        this.$set(this.currentData, "isEdit", true);
      }
      // 获取焦点
      this.$nextTick(() => {
        this.$refs["slotTreeInput" + this.currentData.id].focus();
      });
    },
    handleDragStart(node, ev) {
      // console.log("drag start", node);
    },
    handleDragEnter(draggingNode, dropNode, ev) {
      // console.log("tree drag enter: ", dropNode.label);
    },
    handleDragLeave(draggingNode, dropNode, ev) {
      // console.log("tree drag leave: ", dropNode.label);
    },
    handleDragOver(draggingNode, dropNode, ev) {
      // console.log("tree drag over: ", dropNode);
    },
    handleDragEnd(draggingNode, dropNode, dropType, ev) {
      // console.log("tree drag end: ", dropNode && dropNode.label, dropType);
    },
    handleDrop(draggingNode, dropNode, dropType, ev) {
      // console.log("tree drop: ", dropNode.label, dropType);
    },
  },
};
</script>
<style lang="scss" scope>
</style>

Pay attention to getting data from the page, and monitor the data passed in from the page through the watch attribute, otherwise the mounted data of the page and component will conflict.

Guess you like

Origin blog.csdn.net/m0_71349739/article/details/129664882