zTree api 文档:https://www.treejs.cn/v3/api.php
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 addHoverDom = (treeId, treeNode) => {
let addStr = null;
const add = ``;
const addSm = ``;
const edit = ``;
const del = ``;
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
// 添加、编辑节点(分类)
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) {
...
}
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;
}
}
<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 = ``;
const addSm = ``;
const edit = ``;
const del = ``;
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 >