vue+el-tree ----增加修改删除上下移动

<template>
  <div>
    <el-form :inline="true">
      <el-row>
        <el-col>
          <el-form-item>
            <el-input placeholder="输入关键字进行过滤" v-model="filterText">
            </el-input>
          </el-form-item>
          <el-form-item>
            <el-button
              type="primary"
              size="small"
              class="add_new_question"
              @click="add_new_question"
              ><i></i>新增父节点</el-button
            >
            <el-button type="primary" size="mini" @click="handleSave"
              >保存</el-button
            >
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>

    <div class="question_info_lists">
      <el-tree
        ref="tree"
        :key="tree_key"
        :data="treeData"
        node-key="id"
        :render-content="renderContent"
        :expand-on-click-node="false"
        :default-expanded-keys="defaultExpand"
       @node-expand="nodeExpand"
        @node-collapse="nodeCollapse"
        :filter-node-method="filterNode"
      ></el-tree>
      <!-- 添加父节点 -->
      <el-dialog
        title="新增节点"
        :visible.sync="add_question_flag"
        width="400px"
        append-to-body
      >
        <el-form label-width="100px">
          <el-row>
            <el-col>
              <el-form-item label="父节点">
                <el-input
                  v-model="new_question_name"
                  placeholder="请输入大题名称"
                ></el-input>
              </el-form-item>
            </el-col>
          </el-row>
        </el-form>
        <div slot="footer" class="dialog-footer">
          <el-button type="primary" @click="add_question_sure">确 定</el-button>
          <el-button @click="add_question_cancel">取 消</el-button>
        </div>
      </el-dialog>
      <el-dialog
        title="策划项"
        :visible.sync="openPlanning"
        width="900px"
        append-to-body
      >
        <inDustry :haveSingle="haveSingle" @selectRow="selectRow"></inDustry>
        <!--  -->
      </el-dialog>
    </div>
  </div>
</template>

<script>
import inDustry from "./industry";
export default {
  components: { inDustry },
  name: "treeList",
  watch: {
    filterText(val) {
      this.$refs.tree.filter(val);
    },
  },

  methods: {
// 比如点击操作的时候要保持展开状态   this.defaultExpand =  this.recordExpand;
 nodeExpand(row) {
      if(!this.recordExpand.includes(row.id)){
        this.recordExpand.push(row.id);
      }
    },
    nodeCollapse(row) {
      this.recordExpand = this.recordExpand.filter((item) => {
        return item !== row.id;
      });
    },
    renderContent(h, { node, data, store }) {
      const labelWidth = 300; // 设置节点内容的定宽
      return (
        <div class="box">
           <el-tooltip effect="dark" content={data.label}>
            <div  style={{ width: `${labelWidth}px`, flex:1, overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis' }} className="node_labe">{data.label}</div>
          </el-tooltip>
          {/* <span>{this.showOrEdit(data)}</span> */}

          <div class="tree_node_op" style="float: right, flex:1">
            <i
              class="el-icon-edit"
              on-click={(ev) => this.nodeEdit(ev, store, data)}
            ></i>

            <i
              class="el-icon-delete"
              on-click={() => this.nodeDelete(node, data)}
            ></i>

            <i
              class="el-icon-upload2"
              on-click={() => this.nodeUp(node, data)}
            ></i>

            <i
              class="el-icon-download"
              on-click={() => this.nodeDown(store, node, data)}
            ></i>
            <i
              class="el-icon-plus"
              on-click={() => this.append(store, node, data)}
            ></i>
            <el-dropdown
              class="my-dropdown"
              on-command={() => this.handleDropdownCommand(store, node, data)}
            >
            <span class="el-dropdown-link">
        下拉菜单<i class="el-icon-arrow-down el-icon--right"></i>
      </span>
              <el-dropdown-menu slot="dropdown">
                <el-dropdown-item>选项一</el-dropdown-item>
                <el-dropdown-item>选项二</el-dropdown-item>
                <el-dropdown-item>选项三</el-dropdown-item>
              </el-dropdown-menu>
            </el-dropdown>
          </div>
        </div>
      );
    },
    // 保存
    handleSave() {
      console.log(this.treeData, "数据");
    },
    filterNode(value, data) {
      if (!value) return true;
      return data.label.indexOf(value) !== -1;
    },
    // 添加新大题

    add_new_question() {
      this.filterText = "";
      this.add_question_flag = true;
    },

    add_question_sure() {
      //确定

      const nodeObj = {
        id: "",
        label: this.new_question_name,
        isEdit: false,
        children: [],
      };
      this.treeData.push(nodeObj);
      this.add_question_flag = false;
    },

    add_question_cancel() {
      //取消

      this.add_question_flag = false;

      this.new_question_name = "";
    },
    selectRow(row) {
      this.openPlanning = false;
      var maxid = "20";
      //新增数据
      const nodeapp = {
        id: ++maxid,
        label: row.nickname,
        isEdit: false,
        children: [],
      };
      this.newData.children.push(nodeapp);
      if (!this.nodeList.expanded) {
        this.nodeList.expanded = true;
      }
      const parent = node.parent;
      const children = parent.data;
      const cIndex = children.findIndex((d) => d.id === this.newData.id);
      const tempChildrenNodex2 = children[cIndex]; //拿到被添加的上一级
      console.log(tempChildrenNodex2.children[cIndex - 1], "添加父级");
    },
    handleDropdownCommand(store, node, data) {
      console.log(store, node, "执行命令");
    },
    // 增加
    append(store, node, data) {
      console.log(store, node, "cunxia");
      this.newData = data;
      this.nodeList = node;
      this.$nextTick(() => {
        this.haveSingle = true;
      });
      this.openPlanning = true;
    },
    handleOptionClick(data, option, dropdownId) {
      console.log(`点击了 ${option}`);
      console.log("当前节点数据:", data);
      this.$refs[dropdownId].hide(); // 点击后隐藏下拉菜单
    },
    // 修改

    nodeEdit(ev, store, data) {
      data.isEdit = true;

      this.$nextTick(() => {
        const $input =
          ev.target.parentNode.parentNode.querySelector("input") ||
          ev.target.parentElement.parentElement.querySelector("input");

        !$input ? "" : $input.focus();
      });
    },

    edit_sure(ev, data) {
      const $input =
        ev.target.parentNode.parentNode.querySelector("input") ||
        ev.target.parentElement.parentElement.querySelector("input");

      if (!$input) {
        return false;
      } else {
        data.label = $input.value;

        data.isEdit = false;
      }
    },

    // 节点删除

    nodeDelete(node, data) {
      const parent = node.parent;

      const children = parent.data.children || parent.data;

      const index = children.findIndex((d) => d.id === data.id);

      children.splice(index, 1);
    },

    // 节点上移

    nodeUp(node, data) {
      const parent = node.parent;

      const children = parent.data.children || parent.data;

      const cIndex = children.findIndex((d) => d.id === data.id);

      if (parent.level === 0 && cIndex === 0) {
        this.$message.error("一级节点不能移动");

        return;
      } else if (parent.level !== 0 && cIndex === 0) {
        //不同父节点中移动
        this.$message.error("不同父节点中移动");
      } else if (
        (parent.level === 0 && cIndex !== 0) ||
        (parent.level !== 0 && cIndex !== 0)
      ) {
        const tempChildrenNodex1 = children[cIndex - 1];

        const tempChildrenNodex2 = children[cIndex];

        this.$set(children, cIndex - 1, tempChildrenNodex2);

        this.$set(children, cIndex, tempChildrenNodex1);

        this.defaultExpand[0] = data.id;
      }

      this.tree_key++;
    },

    // 节点下移

    nodeDown(store, node, data) {
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const cIndex = children.findIndex((d) => d.id === data.id);
      const cLength = children.length - 1; // 最边上的节点
      const allLevel = store.data.length - 1; // 树的深度

      if (parent.level === allLevel && cIndex === cLength) {
        // 最最末的节点
        return;
      } else if (parent.level !== allLevel && cIndex === cLength) {
        //父节点不同
        this.$message.error("末级节点不能移动");
      } else if (
        (parent.level === allLevel && cIndex !== cLength) ||
        (parent.level !== allLevel && cIndex !== cLength)
      ) {
        // 父节点相同

        const tempChildrenNodex1 = children[cIndex + 1];

        const tempChildrenNodex2 = children[cIndex];

        this.$set(children, cIndex + 1, tempChildrenNodex2);

        this.$set(children, cIndex, tempChildrenNodex1);

        this.defaultExpand[0] = data.id;
      }

      this.tree_key++;
    },

    showOrEdit(data) {
      if (data.isEdit) {
        return (
          <input
            type="text"
            value={data.label}
            on-blur={(ev) => this.edit_sure(ev, data)}
          />
        );
      } else {
        
        return <span className="node_labe">{data.label}</span>;
      }
    },

    // 结构树操作group node,

    
  },
  data() {
    return {
      newData: {},
      nodeList: {},
      openPlanning: false,
      templateSelection: "",
      haveSingle: false,
      filterText: "",
      treeData: [
        {
          id: 1,

          label: "一级 1",

          isEdit: false,

          children: [
            {
              id: 4,

              label: "二级 1-1",

              isEdit: false,

              children: [
                { id: 9, label: "三级 1-1-1", isEdit: false, children: [] },
                {
                  id: 10,
                  label: "三级 1-1-2",
                  isEdit: false,
                  children: [],
                },
                {
                  id: 11,
                  label: "三级 1-1-3",
                  isEdit: false,
                  children: [],
                },
              ],
            },

            {
              id: 12,

              label: "二级 1-2",

              isEdit: false,

              children: [],
            },

            {
              id: 13,
              label: "二级 1-3",

              isEdit: false,

              children: [],
            },
          ],
        },

        {
          id: 2,

          label: "一级 2",

          isEdit: false,

          children: [
            { id: 5, label: "二级 2-1", isEdit: false, children: [] },
            {
              id: 6,
              label: "二级 2-2",
              isEdit: false,
              children: [],
            },
          ],
        },

        {
          id: 3,

          label: "一级 3",

          isEdit: false,

          children: [
            { id: 7, label: "二级 3-1", isEdit: false, children: [] },
            {
              id: 8,
              label: "二级 3-2",
              isEdit: false,
              children: [],
            },
          ],
        },
      ],

      add_question_flag: false,

      new_question_name: "",

      tree_key: 0,

      defaultExpand: [],
      recordExpand:[],
    };
  },
};
</script>

<style>
.box {
  display: flex;
  width: 300px;
}
i {
  margin: 0 5px;
}
.el-tree-node__content > .el-tree-node__expand-icon {
    padding: 6px;
    margin-top: -3px;
}
</style>

把renderContent 方法里面的el-dropdown-item按照循环的方式去写 修改如下

 renderContent(h, { node, data, store }) {
      const labelWidth = 300; // 设置节点内容的定宽
      // 生成下拉菜单选项数组
      const dropdownOptions = [
        { id: 1, label: "选项一" },
        { id: 2, label: "选项二" },
        { id: 3, label: "选项三" },
      ];

      const dropdownItems = dropdownOptions.map((option) =>
        h(
          "el-dropdown-item",
          {
            key: option.id,
            props: {
              command: option.id,
            },
          },
          option.label
        )
      );
      return (
        <div class="box">
          <el-tooltip effect="dark" content={data.label}>
            <div
              style={{
                width: `${labelWidth}px`,
                flex: 1,
                overflow: "hidden",
                whiteSpace: "nowrap",
                textOverflow: "ellipsis",
              }}
              className="node_labe"
            >
              {data.label}
            </div>
          </el-tooltip>
          {/* <span>{this.showOrEdit(data)}</span> */}

          <div class="tree_node_op" style="float: right, flex:1">
            {/* <i
              class="el-icon-edit"
              on-click={(ev) => this.nodeEdit(ev, store, data)}
            ></i> */}

            <i
              class="el-icon-delete"
              on-click={() => this.nodeDelete(node, data)}
            ></i>

            <i
              class="el-icon-upload2"
              on-click={() => this.nodeUp(node, data)}
            ></i>

            <i
              class="el-icon-download"
              on-click={() => this.nodeDown(store, node, data)}
            ></i>
            <i
              class="el-icon-plus"
              on-click={() => this.append(store, node, data)}
            ></i>
            <el-dropdown
              class="my-dropdown"
              on-command={() => this.handleDropdownCommand(store, node, data)}
            >
              <span class="el-dropdown-link">
                流程菜单<i class="el-icon-arrow-down el-icon--right"></i>
              </span>
              <el-dropdown-menu slot="dropdown">
                {dropdownItems}
              </el-dropdown-menu>
            </el-dropdown>
          </div>
        </div>
      );
    },

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值