【zTree】节点添加不同操作按钮,点击后生成弹窗

news2025/1/15 16:45:55

zTree api 文档:https://www.treejs.cn/v3/api.php

1. 初始化树的配置项

const initZtreeSetting = () => {
  const setting = {
    view: {
      addHoverDom: addHoverDom, // 显示用户自定义控件
      selectedMulti: false,// 是否允许同时选中多个节点,默认为true
      showIcon: true,//是否显示节点的图标,默认为true
    },
    data: {
      simpleData: {// 使用用简单数据模式
        enable: true,
        idKey: 'id',
        pIdKey: 'parentId',
        rootPId: 0,
      },
    },
    callback: {
      onClick: handleNodeClick,// 节点被点击的回调函数
      beforeClick: handleNodeBeforeClick,//节点被点击前的回调函数,设置节点是否可以点击
    },
  };
  return setting;
};

2. 自定义操作按钮

在这里插入图片描述

const addHoverDom = (treeId, treeNode) => {
  let addStr = null;
  const add = `<span class='button add' id='btn_add_${treeNode.tId}' title='添加文件' οnfοcus='this.blur();'></span>`;
  const addSm = `<span class='button addSm' id='btn_addSm_${treeNode.tId}' title='添加节点' οnfοcus='this.blur();'></span>`;
  const edit = `<span class='button edit' id='btn_edit_${treeNode.tId}' title='编辑' οnfοcus='this.blur();'></span>`;
  const del = `<span class='button remove' id='btn_remove_${treeNode.tId}' title='删除' οnfοcus='this.blur();'></span>`;
  
  if (treeNode.id === '自定义') {
    // 自定义
    addStr = addSm; // 添加节点
  } else if (treeNode.code === 'custom') {
    // 自定义下的分类节点(二层)
    if (treeNode.pid === '自定义') {
      addStr = add + edit;
      if (_.isEmpty(treeNode.children)) {
        addStr += del; // 分类下子节点时,可删除该分类
      }
    } else {
      // 三层
      addStr = edit + del;
    }
    
  if (addStr) {
    const _id = `#${treeNode.tId}_span`;
    tippy(_id, {
      content: addStr,// 提示的内容
      trigger: 'mouseenter click',// 触发方式
      placement: 'right',// 出现位置
      interactive: true,// 是否可以交互
      theme: 'material',// 主题
      onMount: function () {// 挂载后执行
        $(`#btn_edit_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            editNode(treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_add_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            addNode(treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_addSm_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            saveSmNode('add', treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_remove_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            removeNode(treeId, treeNode);
            e.stopPropagation();
          });
      },
    });
  }
};

tippy api文档:https://atomiks.github.io/tippyjs/v6/all-props

3. 按钮绑定事件

// 添加、编辑节点(分类)
async function saveSmNode(type: 'add' | 'mod', treeId, treeNode) {
  const title = type === 'add' ? '新增节点' : '编辑节点';
  let { value } = await ElMessageBox.prompt(title, '', {
    confirmButtonText: '确认',
    cancelButtonText:'取消',
    inputPattern: /\S+/,// 输入框校验规则
    inputPlaceholder: type === 'add' ? '请输入节点名称' : null,// 占位符
    inputErrorMessage: '节点名不能为空!',// 校验不通过的信息
    inputValue: type === 'add' ? null : treeNode.name,// 输入框默认值
  });
  try {
   //case1: 在该节点下新增节点
    if (type === 'add') {
      const res = await $.ajax({
        url: `${window.__ctx}/report/module/addNode`,
        type: 'POST',
        dataType: 'json',
        data: {
          parentId:treeNode.id,
          name: value,// 获取到输入框的值
        },
      });
      if (!res.result) throw new Error(res?.message);
      ElMessage.success(res?.message || '提交成功');
      const zTreeObj = $.fn.zTree.getZTreeObj(treeId);
      zTreeObj.addNodes(treeNode , res?.object);// 更新树节点的显示
     //case2:对该节点进行编辑
    } else {
      const res = await $.ajax({
        url: `${window.__ctx}/report/module/rename`,
        type: 'POST',
        dataType: 'json',
        data: {
          id: treeNode.id,
          reName: value,
        },
      });
      if (!res.result) throw new Error(res?.message);
      ElMessage.success(res?.message || '提交成功');
      const zTreeObj = $.fn.zTree.getZTreeObj(treeId);
      treeNode.name = value;
      zTreeObj.updateNode(treeNode);
    }
  } catch (error) {
    if (error === 'cancel') return;
    ElMessage.error(error?.message ||'提交失败');
    console.log(`addSmNode - error`, error);
  }
}

// 删除
async function removeNode(treeId, treeNode) {
  try {
    const modId = treeNode.id;
    await ElMessageBox.confirm('是否要删除该节点?', '提示', {
   	  confirmButtonText: '确认',
 	  cancelButtonText:'取消',
      type: 'warning',
    });
    const res = await $.ajax({
      url: `${window.__ctx}/report/module/delete/${modId}`,
      type: 'GET',
      dataType: 'json',
    });
    if (!res.result) throw new Error(res?.message);
    ElMessage.success(res?.message || '提交成功');
    $.fn.zTree.getZTreeObj(treeId).removeNode(treeNode);//移除该节点
  } catch (error) {
    if (error === 'cancel') return;
    ElMessage.error(error?.message || '提交失败');
    console.log(`removeNode - error`, error);
  }
}
// 添加文件
function addNode(treeId, treeNode) {
  ...
}
// 编辑文件
function editNode(treeId, treeNode) {
  ...
}

4. 接口请求数据, 初始化zTree

async function initZtree() {
  const setting = initZtreeSetting ();
  try {
    isTreeLoading.value = true;
    const res = await $.ajax({
      url: `${window.__ctx}/report/tree`,
      type: 'POST',
      dataType: 'json',
    });
    if (!res?.result) return;
    const treeObj = $.fn.zTree.init($('#treeId'), setting, res?.object);
    if (treeObj.getNodes().length >= 1) {
      treeObj.expandNode(treeObj.getNodes()[0], true);// 展开第一个节点
    }
  } catch (err) {
    console.log(`[log] - initZtree- err`, err);
  } finally {
    isTreeLoading.value = false;
  }
}

5. 全部代码

<template>
    <div v-loading="isTreeLoading">
      <ul class="ztree" id="treeId"></ul>
    </div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const isTreeLoading = ref(false);

// 初始化树的配置项
const initZtreeSetting = () => {
  const setting = {
    view: {
      addHoverDom: addHoverDom, // 显示用户自定义控件
      selectedMulti: false,// 是否允许同时选中多个节点,默认为true
      showIcon: true,//是否显示节点的图标,默认为true
    },
    data: {
      simpleData: {// 使用用简单数据模式
        enable: true,
        idKey: 'id',
        pIdKey: 'parentId',
        rootPId: 0,
      },
    },
    callback: {
      onClick: handleNodeClick,// 节点被点击的回调函数
      beforeClick: handleNodeBeforeClick,//节点被点击前的回调函数,设置节点是否可以点击
    },
  };
  return setting;
};
// 节点前点击事件
const handleNodeBeforeClick = (treeId, treeNode, clickFlag) => {
  return treeNode.reportType !== 'Node';// 返回 false,无法点击
};
// 节点点击事件
const handleNodeClick = (event, treeId, treeNode) => {
  console.log(`treeNode->`, treeNode);
};
// 初始化树
async function initZtree() {
  const setting = initZtreeSetting ();
  try {
    isTreeLoading.value = true;
    const res = await $.ajax({
      url: `${window.__ctx}/report/tree`,
      type: 'POST',
      dataType: 'json',
    });
    if (!res?.result) return;
    const treeObj = $.fn.zTree.init($('#treeId'), setting, res?.object);
    if (treeObj.getNodes().length >= 1) {
      treeObj.expandNode(treeObj.getNodes()[0], true);// 展开第一个节点
    }
  } catch (err) {
    console.log(`[log] - initZtree- err`, err);
  } finally {
    isTreeLoading.value = false;
  }
}
onMounted(() => {
  initZtree();
});

//自定义操作按钮
const addHoverDom = (treeId, treeNode) => {
  let addStr = null;
  const add = `<span class='button add' id='btn_add_${treeNode.tId}' title='添加文件' οnfοcus='this.blur();'></span>`;
  const addSm = `<span class='button addSm' id='btn_addSm_${treeNode.tId}' title='添加节点' οnfοcus='this.blur();'></span>`;
  const edit = `<span class='button edit' id='btn_edit_${treeNode.tId}' title='编辑' οnfοcus='this.blur();'></span>`;
  const del = `<span class='button remove' id='btn_remove_${treeNode.tId}' title='删除' οnfοcus='this.blur();'></span>`;
  
  if (treeNode.id === '自定义') {
    // 自定义
    addStr = addSm; // 添加节点
  } else if (treeNode.code === 'custom') {
    // 自定义下的分类节点(二层)
    if (treeNode.pid === '自定义') {
      addStr = add + edit;
      if (_.isEmpty(treeNode.children)) {
        addStr += del; // 分类下子节点时,可删除该分类
      }
    } else {
      // 三层
      addStr = edit + del;
    }
    
  if (addStr) {
    const _id = `#${treeNode.tId}_span`;
    tippy(_id, {
      content: addStr,// 提示的内容
      trigger: 'mouseenter click',// 触发方式
      placement: 'right',// 出现位置
      interactive: true,// 是否可以交互
      theme: 'material',// 主题
      onMount: function () {// 挂载后执行
        $(`#btn_edit_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            editNode(treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_add_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            addNode(treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_addSm_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            saveSmNode('add', treeId, treeNode);
            e.stopPropagation();
          });
        $(`#btn_remove_${treeNode.tId}`)
          ?.off('click')
          ?.on('click', (e) => {
            removeNode(treeId, treeNode);
            e.stopPropagation();
          });
      },
    });
  }
};

// 添加、编辑节点(分类)
async function saveSmNode(type: 'add' | 'mod', treeId, treeNode) {
  const title = type === 'add' ? '新增节点' : '编辑节点';
  let { value } = await ElMessageBox.prompt(title, '', {
    confirmButtonText: '确认',
    cancelButtonText:'取消',
    inputPattern: /\S+/,// 输入框校验规则
    inputPlaceholder: type === 'add' ? '请输入节点名称' : null,// 占位符
    inputErrorMessage: '节点名不能为空!',// 校验不通过的信息
    inputValue: type === 'add' ? null : treeNode.name,// 输入框默认值
  });
  try {
   //case1: 在该节点下新增节点
    if (type === 'add') {
      const res = await $.ajax({
        url: `${window.__ctx}/report/module/addNode`,
        type: 'POST',
        dataType: 'json',
        data: {
          parentId:treeNode.id,
          name: value,// 获取到输入框的值
        },
      });
      if (!res.result) throw new Error(res?.message);
      ElMessage.success(res?.message || '提交成功');
      const zTreeObj = $.fn.zTree.getZTreeObj(treeId);
      zTreeObj.addNodes(treeNode , res?.object);// 更新树节点的显示
     //case2:对该节点进行编辑
    } else {
      const res = await $.ajax({
        url: `${window.__ctx}/report/module/rename`,
        type: 'POST',
        dataType: 'json',
        data: {
          id: treeNode.id,
          reName: value,
        },
      });
      if (!res.result) throw new Error(res?.message);
      ElMessage.success(res?.message || '提交成功');
      const zTreeObj = $.fn.zTree.getZTreeObj(treeId);
      treeNode.name = value;
      zTreeObj.updateNode(treeNode);
    }
  } catch (error) {
    if (error === 'cancel') return;
    ElMessage.error(error?.message ||'提交失败');
    console.log(`addSmNode - error`, error);
  }
}

// 删除
async function removeNode(treeId, treeNode) {
  try {
    const modId = treeNode.id;
    await ElMessageBox.confirm('是否要删除该节点?', '提示', {
   	  confirmButtonText: '确认',
 	  cancelButtonText:'取消',
      type: 'warning',
    });
    const res = await $.ajax({
      url: `${window.__ctx}/report/module/delete/${modId}`,
      type: 'GET',
      dataType: 'json',
    });
    if (!res.result) throw new Error(res?.message);
    ElMessage.success(res?.message || '提交成功');
    $.fn.zTree.getZTreeObj(treeId).removeNode(treeNode);//移除该节点
  } catch (error) {
    if (error === 'cancel') return;
    ElMessage.error(error?.message || '提交失败');
    console.log(`removeNode - error`, error);
  }
}
// 添加文件
function addNode(treeId, treeNode) {
  ...
}
// 编辑文件
function editNode(treeId, treeNode) {
  ...
}

</script >

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1154662.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HarmonyOS鸿蒙原生应用开发设计- 隐私声明

HarmonyOS设计文档中&#xff0c;为大家提供了独特的隐私声明&#xff0c;开发者可以根据需要直接引用。 开发者直接使用官方提供的隐私声明内容&#xff0c;既可以符合HarmonyOS原生应用的开发上架运营规范&#xff0c;又可以防止使用别人的内容产生的侵权意外情况等&#xff…

程序开发官网地址汇总

这里写目录标题 官网地址汇总开发环境开发工具数据库驱动包其他 官网地址汇总 开发环境 1 JDK &#xff1a;https://www.oracle.com/java/technologies/java-se-glance.html 2 Maven&#xff1a;https://maven.apache.org/download.cgi 3 Maven Repository: https://mvnrep…

启动U盘制作工具------------Ventoy 最新版 v1.0.96

Ventoy最新版是一款功能强大的启动U盘制作工具,Ventoy最新版支持多系统启动盘的制作功能,Ventoy最新版一次还可以拷贝很多个不同类型的ISO文件,软件支持自动安装部署、支持超过4GB的ISO文件、支持大部分常见操作系统和无差异支持Legacy+UEFI模式。软件能够直接启动WIM文件。…

搜索语法备忘

搜索途径 传统搜索引擎&#xff1a;Goolge、Bing、Sogou、Baidu微信搜一搜视频内容&#xff1a;哔哩哔哩、抖音AI&#xff1a;文言一心、ChatGPT 传统搜索引擎中&#xff0c;Goolge 和 Sogou 可以搜索到微信公众号的内容。这很重要&#xff0c;根据我的主观感受&#xff0c;微…

PSP - 蛋白质复合物 AlphaFold2 Multimer MSA Pairing 逻辑与优化

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/134144591 在蛋白质复合物结构预测中&#xff0c;当序列 (Sequence) 是异源多链时&#xff0c;无论是AB&#xff0c;还是AABB&#xff0c;都需要 …

Python实现hellokitty

目录 系列文章 前言 绘图基础 HelloKitty 尾声 系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.n…

山西电力市场日前价格预测【2023-11-01】

日前价格预测 预测说明&#xff1a; 如上图所示&#xff0c;预测明日&#xff08;2023-11-01&#xff09;山西电力市场全天平均日前电价为280.90元/MWh。其中&#xff0c;最高日前电价为420.61元/MWh&#xff0c;预计出现在18:00。最低日前电价为0.00元/MWh&#xff0c;预计出…

LIS系统解决了实验室的哪些问题?

LIS实验室管理系统源码 LIS系统全套源码 LIS系统解决了实验室的哪些问题&#xff1f; 1、普遍存在的标本送错及标本不合格问题 现状&#xff1a;实验室标本的分送由护工完成&#xff0c;通常会由于疏忽等原因导致标本与原来裹在外面的申请单搞错&#xff0c;有时还会送错标本…

一篇文章入门KNN算法

文章目录 KNNKNN算法KNN in practice推荐系统我们想回答什么问题&#xff1f;探索、清理和准备数据使用算法 Summary 参考文献 KNN 监督学习是一种依赖输入数据来学习函数的算法&#xff0c;该函数在给定新的未标记数据时可以产生适当的输出。 监督学习用于解决分类或回归问题…

手机型号抓取

Code处理结果&#xff1a;DataFrame 及 流程 方式①&#xff1a;每个页面的数据处理成df, 然后再合并df , pd.concat()/ df.append() 循环合并 方式②&#xff1a;原始数据中&#xff0c;每个页面的数据存储在一个列表中&#xff0c;然后页面中的每条数据以字典单元形式盛放在列…

数据查找(search)-----线性表查找

目录 前言 线性表查找 1.无序表查找 2.无序表查找 3.分块查找 前言 前面我们已经学习过了相关数据结构的知识&#xff0c;那么今天我们就开始去学习数据的查找&#xff0c;在不同的数据结构里面去查找目标数据&#xff0c;这就是数据的查找算法。今天就从线性结构的表去查…

QMS质量检验管理|攻克制造企业质量检验难题,助力企业提质增效

在日益激烈的市场竞争中&#xff0c;对产品质量严格把关&#xff0c;是制造企业提高核心竞争力与品牌价值的关键因素。那如何高效、高质地完成产品质检工作&#xff1f;这就需要企业在工业质检中引进数字化技术加以辅助&#xff0c;进而推动智能制造高质量发展。 蓝库云QMS质量…

VR全景对比在行业中如何呈现优势?功能有多强大?

我们在买车、买房或者是挑选旅游景区的时候&#xff0c;总是拿不定注意&#xff0c;彼此之间差异化细节处展现的并不明显&#xff0c;往往一个细节需要翻来覆去好几遍才能看懂。现在VR全景对比打破传统图片对比方式&#xff0c;让差异化效果更快展现&#xff01; VR全景对比是通…

Simulink查表法实现NTC温度计算模型

目录 前言 把NTC数据导入到excel 把excel数据导入Matlab 拟合NTC温度曲线 查表实现温度计算 总结 前言 在实际项目中需要对NTC对某些区域进行温度采样和做一些系统层面的保护等等&#xff0c;比如过温降载&#xff0c;过温保护&#xff0c;这时就需要对NTC或者其他的温度传…

Docker之docker-compose(介绍,安装及入门示例)

文章目录 一、docker-compose介绍Compose 中有两个重要的概念&#xff1a; 二、docker-compose安装三、docker-compose简单示例参考网址&#xff1a; 一、docker-compose介绍 Compose 项目是 Docker 官方的开源项目&#xff0c;负责实现对 Docker 容器集群的快速编排。 Compo…

第7讲:VBA中利用FIND的代码实现多值查找实例

《VBA代码解决方案》(10028096)这套教程是我最早推出的教程&#xff0c;目前已经是第三版修订了。这套教程定位于入门后的提高&#xff0c;在学习这套教程过程中&#xff0c;侧重点是要理解及掌握我的“积木编程”思想。要灵活运用教程中的实例像搭积木一样把自己喜欢的代码摆好…

diffusers-AutoPipline

https://huggingface.co/docs/diffusers/tutorials/autopipelinehttps://huggingface.co/docs/diffusers/tutorials/autopipelineAutoPipeline会自动检测要使用的正确流程类&#xff0c;这样可以更轻松地加载与任务相对应的检查点&#xff0c;而无需知道具体的流程类名称。 1.…

.net core iis 发布后登入的时候请求不到方法报错502

.net core iis 发布后登入的时候请求不到方法报错502 502 bad gateway 502 - Web 服务器在作为网关或代理服务器时收到了无效响应。 您要查找的页面有问题&#xff0c;无法显示。当 Web 服务器(作为网关或代理)与上游内容服务器联系时&#xff0c;收到来自内容服务器的无效…

配置管理工具-Confd

1 简介 1.1 Confd介绍 Confd是一个轻量级的配置管理工具。通过查询后端存储&#xff0c;结合配置模板引擎&#xff0c;保持本地配置最新&#xff0c;同时具备定期探测机制&#xff0c;配置变更自动reload。对应的后端存储可以是etcd&#xff0c;redis、zookeeper等。[1] 通过…

2024年湖北黄冈建安ABC建筑企业专职安全员报名事项

2024年湖北黄冈建安ABC建筑企业专职安全员报名事项 专职安全员一般是指从事安全管理方面的工作&#xff0c;普遍的是建筑施工行业&#xff0c;建筑工地安全员&#xff0c;专职安全员C证&#xff0c;黄冈建筑安全员ABC-建筑单位在黄冈&#xff0c;只能在黄冈报考建筑安全员ABC。…