el-tree指定节点禁用、节点删除、节点自定义图标

文章描述了如何使用ElementUI的el-tree组件,实现在两个树之间的数据同步,当右边的el-tree数据存在左边的节点时禁用对应节点,以及删除操作对左右树的影响和处理。还涉及到了复选框选择和AI智能标签的管理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目的

实现el-tree两个树,将左边的树数据添加到右边的树中,当右边存在左边el-tree数据,这个子节点禁用,当右边el-tree删除掉那个子节点,左边el-tree那个节点可以选择

展示

在这里插入图片描述

代码

<template>
  <div class="container">
    <div style="padding: 20px 0">
      <el-form :inline="true" :model="formInline">
        <el-col :span="22">
          <el-form-item label="品牌名称">
            <el-select
              v-model="formInline.brandCode"
              style="width: 300px"
              clearable
              filterable
              default-first-option
              placeholder="请选择"
            >
              <el-option
                v-for="(item, index) in brandNameArr"
                :key="item.brandCode + index"
                :label="item.brandName"
                :value="item.brandCode"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-form-item>
          <el-button type="primary" @click="onSubmit">查询</el-button>
        </el-form-item>
      </el-form>
    </div>
    <div>
      <div class="tree-drag">
        <el-col :span="10">
          <div class="tree">
            <h4>AI智能标签</h4>
            <el-tree
              ref="aiTree"
              :data="treeData2"
              default-expand-all
              show-checkbox
              node-key="id"
              :check-strictly="true"
              :disabled="checkDisabled"
              @check="checkSelect"
              :props="defaultProps"
            >
            </el-tree>
          </div>
        </el-col>
        <el-col :span="4">
          <div class="btn">
            <el-button
              type="primary"
              :disabled="chooseList.length > 0 ? false : true"
              @click="moveBtn"
            >
              添加映射到主标签</el-button
            >
            <!-- <el-button
            type="primary"
            :disabled="leftChooseTable.length > 0 ? false : true"
            @click="rightChangeTable('right')"
            >移动至AI标签<i class="el-icon-arrow-right el-icon--right" />
          </el-button> -->
          </div>
        </el-col>
        <el-col :span="10">
          <div class="tree">
            <h4>系统默认标签</h4>
            <!-- <el-tree
              ref="tree"
              :data="treeData1"
              default-expand-all
              node-key="id"
            >
            </el-tree> -->
            <el-tree
              ref="tree"
              :data="treeData1"
              default-expand-all
              node-key="id"
              :props="defaultProps"
            >
              <span class="custom-tree-node" slot-scope="{ node, data }">
                <span v-if="data.isAi">
                  <span
                    style="margin: 0 10px; font-size: 14px; color: deepskyblue"
                    class="iconfont icon-ai"
                    >{{ data.label }}</span
                  >
                  <el-button
                    type="text"
                    size="mini"
                    style="color: red; font-size: 14px"
                    @click="() => remove(node, data)"
                  >
                    删除
                  </el-button>
                </span>
                <span v-else>{{ node.label }}</span>
              </span>
            </el-tree>
          </div>
        </el-col>
      </div>
      <el-dialog
        title="请选择映射到主档标签"
        :visible.sync="dialogVisible"
        width="30%"
        :before-close="handleClose"
        center
      >
        <div>
          <el-tree
            :data="treeData1"
            show-checkbox
            default-expand-all
            @check-change="checkChange"
            ref="Tree"
            :check-strictly="true"
            node-key="id"
            :props="defaultProps"
          ></el-tree>
        </div>
        <span slot="footer" class="dialog-footer">
          <el-button @click="closeDialog">取 消</el-button>
          <el-button type="primary" @click="addBtn">确 定</el-button>
        </span>
      </el-dialog>
    </div>
  </div>
</template>
 <script>
import http from "@/utils/request";
export default {
  data() {
    return {
      dialogVisible: false,
      chooseList: [],
      rightChooseInfo: [],
      treeData1: [],
      treeData2: [],
      disabledNodes: [],
      value: "",
      idListArr: [],
      formInline: {
        brandCode: "",
      },
      defaultProps: {
        children: "children",
        label: "label",
      },
    };
  },
  computed: {
    checkDisabled() {
      return (node) => {
        return this.disabledNodes.includes(node.id);
      };
    },
  },
  created() {
    this.getAllBrand();

    // console.log(this.setDisabled(data));
  },
  methods: {
    // 查询
    onSubmit() {
        const data = [
          {
            id: 1,
            label: "标签主档",
            children: [
              {
                id: 2,
                label: "投诉",
                children: [
                  { id: 21, label: "催单" },
                  { id: 22, label: "提前关单" },
                ],
              },
              {
                id: 3,
                label: "错漏送",
                children: [
                  { id: 31, label: "漏配料" },
                  { id: 32, label: "漏餐具" },
                ],
              },
              {
                id: 4,
                label: "服务态度",
                children: [
                  {
                    id: 41,
                    label: "骑手服务态度",
                  },
                  { id: 42, label: "门店服务态度" },
                ],
              },
            ],
          },
        ];
        const data2 = [
          {
            id: 111,
            label: "AI标签分类",
            children: [
              {
                id: 211,
                label: "骑手未送达",
              },
              {
                id: 311,
                label: "漏番茄酱",
                isAll: true,
              },
              {
                id: 411,
                label: "漏料包",
              },
            ],
          },
        ];
        this.treeData1 = this.addDisabledToParentNodes(data);
        this.treeData2 = this.addDisabledToParentNodes(data2);
        console.log(this.treeData2);
      
    },

    // 获取所有品牌
  getAllBrand() {
     
    },

    // 关闭
    closeDialog() {
      this.dialogVisible = false;
    },
    // 提交
    addBtn() {
      if (this.value) {
        this.traverseTree(this.treeData1);
      }
    },
    traverseTree(treeData) {
      for (let i = 0; i < treeData.length; i++) {
        let node = treeData[i];
        console.log(node); // 打印当前节点
        if (node.children && node.children.length > 0) {
          this.traverseTree(node.children); // 递归遍历子节点
        }
        if (node.id == ~~this.value) {
          if (!node.children) {
            // 如果该节点没有children属性,则创建它
            node.children = [];
          }
          node.children.push(...this.chooseList);
          this.dialogVisible = false;
          // 取消勾选
          this.$refs.aiTree.setCheckedKeys([]);
        }
        this.treeData1 = JSON.parse(JSON.stringify(treeData));

        this.$nextTick(() => {
          this.chooseList = [];
          this.value = "";
        });
        
      }
 
    },
    moveBtn() {
      this.dialogVisible = true;
    },
    //  选中复选框触发
    checkChange(currObj, isChecked) {
      if (isChecked) {
        // 选中之后我们就重新设置下选中的节点(只设置当前选中的节点,即单选)
        this.$refs.Tree.setCheckedNodes([currObj]);
        this.value = currObj.id;
        console.log(111, this.value);
      }
    },
   

    addDisabledToParentNodes(data) {
      return data.map((node) => {
        // 如果当前节点有子节点,则递归处理子节点
        if (node.children && node.children.length > 0) {
          node.children = this.addDisabledToParentNodes(node.children);
          // 如果当前节点是父节点,则添加disabled属性
          node.disabled = true;
        }
        if (node.isAll) {
          node.disabled = true;
        }
        return node;
      });
    },
    checkSelect(select, val) {
      console.log(select, val);
      this.chooseList = val.checkedNodes.map((item) => {
        return { ...item, isAi: true };
      });
      this.idListArr = val.checkedKeys;
      console.log(1111111111, this.chooseList);
    },

    handleClose() {
      this.dialogVisible = false;
    },

    // 删除AI智能标签
    remove(node, data) {
      console.log("删除", node, data);
      const parent = node.parent;
      const children = parent.data.children || parent.data;
      const index = children.findIndex((d) => d.id === data.id);
      this.$confirm("此操作将永久删除该标签映射, 是否继续?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          children.splice(index, 1);

          this.$message({
            type: "success",
            message: "删除成功!",
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
  },
};
</script>

<style lang="scss" scoped>
@font-face {
  font-family: "iconfont"; /* Project id 4368207 */
  /* Color fonts */
  src: url("//at.alicdn.com/t/c/font_4368207_u2wqj9e0d6h.woff2?t=1702287717799")
      format("woff2"),
    url("//at.alicdn.com/t/c/font_4368207_u2wqj9e0d6h.woff?t=1702287717799")
      format("woff"),
    url("//at.alicdn.com/t/c/font_4368207_u2wqj9e0d6h.ttf?t=1702287717799")
      format("truetype");
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 14px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-ai:before {
  content: "\e68a";
  margin-right: 5px;
}

.container {
  display: flex;
  flex-direction: column;
  padding: 20px;
}
.tree-drag {
  display: flex;
  justify-content: space-between;
}
.tree {
  display: flex;
  flex-direction: column;
  align-items: center;
  overflow: auto;
  height: 500px;
  font-size: 14px;
  box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
  border: 1px solid #ccc;
}
.btn {
  height: 500px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .el-button {
    width: 150px;
    margin: 10px 0;
  }
}
/* 隐藏掉el-tree中有disabled属性的框框 */
.el-checkbox__input.is-disabled {
  display: none;
}
.custom-tree-node {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 14px;
  padding-right: 8px;
}
</style>

提示

移动的数据让后端添加上一个标识,删除的数据同样加上标识

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值