前端ztree部分:
写了个右键菜单div,div详细见之前博客
/**
* 零件程序js
*
* @author ChengXY
* @since 2021-07-27 15:40
*/
/**
* 产品信息
* @type {{proName: null, proId: null}}
*/
var product = {
proName: null,
proId: null
};
/**
* 工艺信息
* @type {{processName: null, processId: null}}
*/
var process = {
processName : null,
processId: null
};
/**
* 工件信息
* @type {{wpName: null, wpId: null}}
*/
var workpiece = {
wpName: null,
wpId: null
};
layui.use(['layer', 'form', 'laydate', 'admin', 'ax', 'treeTable', 'func','element'], function () {
var $ = layui.jquery;
var layer = layui.layer;
// 定义被右键选中的节点
var selectedNode = null;
var zTreeObj;
// zTree 的参数配置,深入使用请参考 API 文档(setting 配置详解)
var setting = {
callback: {
onRightClick: zTreeOnRightClick,
beforeRename: zTreeBeforeRename,
onClick: zTreeClick,
onCollapse: zTreeOnCollapse,
onExpand: zTreeOnExpand,
beforeRemove: zTreeBeforeRemove
},
edit: {
enable: true
}
};
/**
* before 移除 监听
*/
function zTreeBeforeRemove(treeId,treeNode) {
if (zTreeObj.getNodesByParam("parentTId",treeNode.tId,null).length>0){
return confirmM();
} else{
$.ajax({
url: '/programTree/deleteByid?id='+treeNode.id,
async: false,
success: function () {
return true;
},error: function () {
Feng.error("删除失败,请刷新重试!");
return false;
}
});
}
}
function confirmM() {
return layer.open({
content: '删除该节点会将全部子节点相关信息删除,是否仍执行删除操作?',
btn:['确定','取消'],
btn1: function () {
console.log(true);
$.ajax({
url: '/programTree/deleteByid?id='+treeNode.id,
async: false,
success: function () {
return true;
},error: function () {
return false;
}
});
},
btn2: function () {
console.log(false);
return false;
}
})
}
/**
* 父节点 展开监听
*/
function zTreeOnExpand(event,treeId,treeNode) {
$.ajax({url: '/programTree/update?id='+treeNode.id+'&value=1&type=1'})
}
/**
* 父节点折叠监听
*/
function zTreeOnCollapse(event,treeId,treeNode) {
$.ajax({url: '/programTree/update?id='+treeNode.id+'&value=0&type=1'})
}
/**
* click监听
* @param event
* @param treeId
* @param treeNode
* @param clickFlag
*/
function zTreeClick(event,treeId,treeNode,clickFlag) {
// 监听程序
if (treeNode.grade == 3){
console.log("右侧展示");
}
}
/**
* 修改名字前置
* @param treeId
* @param treeNode
* @param newName
* @param isCancel
*/
function zTreeBeforeRename(treeId,treeNode,newName,isCancel) {
if (treeNode.name != newName && isCancel != true){
$.ajax({url:'/programTree/update?id='+treeNode.id+'&value='+newName+'&type=0'})
}
}
/**
* ztree 右键监听事件
* @param event
* @param treeId
* @param treeNode
*/
function zTreeOnRightClick(event,treeId,treeNode) {
selectedNode = null;
if (treeNode== null){
// 点击空白区域
// 初始化内容
$("#rightClickUl>li").removeClass("dLi").addClass("liHover");
// 最外层 更改内容 点击空白页面
$("#rightClickUl>li:not(.createLi)").removeClass("liHover").addClass("dLi");
} else{
// 点击节点
// 判断点击级别
if (treeNode.grade === 0 ){
// 显示 文件夹和产品
// 初始化内容
$("#rightClickUl>li").removeClass("dLi").addClass("liHover");
// 最外层 更改内容 点击空白页面
$("#rightClickUl>li:not(.createLi):not(.addProduct)").removeClass("liHover").addClass("dLi");
} else if (treeNode.grade === 1){
// 显示 文件夹、产品、零件
// 初始化内容
$("#rightClickUl>li").removeClass("dLi").addClass("liHover");
$("#rightClickUl>li:not(.addWp):not(.addProduct)").removeClass("liHover").addClass("dLi");
} else if (treeNode.grade ===2){
$("#rightClickUl>li").removeClass("dLi").addClass("liHover");
$("#rightClickUl>li:not(.addWp):not(.addPg)").removeClass("liHover").addClass("dLi");
} else if (treeNode.grade ===3) {
$("#rightClickUl>li").removeClass("liHover").addClass("dLi");
}
selectedNode = treeNode;
}
// 显示菜单栏
var x = event.clientX-event.offsetX;
var y = event.clientY-event.offsetY;
// 如果点击位置在div右侧,调整显示位置
if (x + $("#rightClickDiv").width() > $(this)[0].clientWidth) {
x = $(this)[0].clientWidth - $("#rightClickDiv").width();
}
if (y + $("#rightClickDiv").height() > $(this)[0].clientHeight) {
y = $(this)[0].clientHeight - $("#rightClickDiv").height();
}
//改变菜单的位置到事件发生的位置
$('#rightClickDiv').css({'top': y,'left': x,'display': 'block'});
}
// zTree 的数据属性,深入使用请参考 API 文档(zTreeNode 节点数据详解)
var zNodes = [];
/**
* 页面加载事件
*/
$(document).ready(function(){
zTreeObj = $.fn.zTree.init($("#folderDiv"), setting, zNodes);
// 查询节点信息
$.ajax({
url: '/programTree/findAllOrderByGroup',
async: false,
success: function (data) {
zTreeObj.addNodes(null,data);
},error: function () {
Feng.error("获取树信息异常,请刷新重试!");
}
});
});
/**
* 菜单栏点击事件
*/
$("#rightClickDiv").click(function (event) {
// 判断子元素
if ((event.target.className.indexOf('addProductSpan') >-1 || event.target.className.indexOf('addProduct')>-1) && $(".addProduct").hasClass("liHover")) {
// 添加产品
layer.open({
type: 2,
title: '添加产品',
area: ['50%', '90%'],
content: Feng.ctxPath + '/program/workpiece_pro_manage/addProduct',
end: function () {
if (product.proName != null){
addNode(product.proName,'/assets/program/img/product.png',1,'productId',product.proId);
}
}
});
} else if ((event.target.className.indexOf('addWpSpan') >-1 || event.target.className.indexOf('addWp')>-1) && $(".addWp").hasClass("liHover")){
// 添加零件
layer.open({
type: 2,
title: '添加零件',
area: ['50%', '90%'],
content: Feng.ctxPath + '/program/workpiece_pro_manage/addWorkpiece',
end: function () {
if (workpiece.wpName != null){
addNode(workpiece.wpName,'/assets/program/img/workpiece.png',2,'workpieceId',workpiece.wpId);
}
}
});
} else if ((event.target.className.indexOf('addPgSpan') >-1 || event.target.className.indexOf('addPg')>-1) && $(".addPg").hasClass("liHover")){
// 添加程序工艺
layer.open({
type: 2,
title: '添加程序工艺',
area: ['50%', '90%'],
content: Feng.ctxPath + '/program/workpiece_pro_manage/addProcess',
end: function () {
if (process.processName != null){
addNode(process.processName,'/assets/program/img/program.png',3,'processId',process.processId);
}
}
});
} else if ((event.target.className.indexOf('createLi') >-1 || event.target.className.indexOf('createSpan')>-1) && $(".createLi").hasClass("liHover")) {
// 添加文件夹
addNode("新建文件夹",'/assets/program/img/folder.png',0,null,null);
} else if (event.target.className.indexOf('ztree') > -1){
$('#rightClickDiv').hide();
}
});
/**
* 添加节点
* @param nodeName
* @param iconUrl
* @param grade
*/
function addNode(nodeName,iconUrl,grade,key,value){
var level = 0 ;
var parentId = null;
if (selectedNode != null){
level = selectedNode.level+1;
parentId = selectedNode.id==''?null:selectedNode.id;
}
var nodes = zTreeObj.getNodesByParamFuzzy("name",nodeName, selectedNode);
var name = '';
if (nodes.length === 0) {
name = nodeName;
} else {
name = nodeName + nodes.length;
}
var newNodes = {
name: name,
open: true,
icon: iconUrl,
grade: grade,
level: level,
parentId: parentId
};
if (key != null){
newNodes[key] = value;
}
// 新增节点
$.ajax({
url: '/programTree/addItem',
data: newNodes,
async: false,
success:function (data) {
console.log("data",data.data);
newNodes['id'] = data.data;
},error: function () {
Feng.error("新增失败,请刷新后重试!");
}
});
console.log("newNode",newNodes);
zTreeObj.addNodes(selectedNode, newNodes);
// 隐藏
$('#rightClickDiv').hide();
}
/**
* 点击空白
*/
$("#folderDiv:not(li):not(span)").click(function () {
$('#rightClickDiv').hide();
});
/**
* 禁用鼠标右键
*/
$('.rightDiv').on('contextmenu', function () {
return false;
});
/**
* 目标区域点击事件
*/
$('.rightDiv').on('mousedown', function (event) {
var code = event.which;
switch (code) {
case 1:
break;
case 2:
break;
case 3:
break;
default: break;
}
})
});
html:
<!--左侧程序目录-->
<div class="leftDiv">
<!--右键div-->
<div id="rightClickDiv">
<ul id="rightClickUl">
<li class="createLi rightClickLi liHover"><span class="liContent createSpan">新建文件夹</span></li>
<li class="addProduct rightClickLi liHover"><span class="liContent addProductSpan">添加产品</span></li>
<li class="addWp rightClickLi liHover"><span class="liContent addWpSpan">添加零件</span></li>
<li class="addPg rightClickLi liHover"><span class="liContent addPgSpan">添加程序</span></li>
</ul>
</div>
<!--文件夹区域-->
<div id="folderDiv" class="ztree">
</div>
</div>
<!--右侧详情div-->
<div class="rightDiv">
<div class="contentDiv">
<div class="layui-tab">
<ul class="layui-tab-title">
<li class="layui-this">程序卡片</li>
<li>Nc程序</li>
<li>文档</li>
</ul>
<div class="layui-tab-content">
</div>
</div>
</div>
</div>
ztree树的对应controller:
/**
* 新增节点接口
*
* @author ChengXY
* @Date 2021-08-06
*/
@RequestMapping("/addItem")
@ResponseBody
public ResponseData addItem(ProgramTreeParam programTreeParam) {
Long id = this.programTreeService.add(programTreeParam);
return ResponseData.success(200,"success",id);
}
/**
* 查询全部节点信息 按父子顺序
* @return
*/
@ResponseBody
@RequestMapping("/findAllOrderByGroup")
public List<ProgramTreeResult> findAll(){
return this.programTreeService.findAllOrderByZtree();;
}
直接上impl:
@Override
public List<ProgramTreeResult> findAllOrderByZtree() {
Date date1 = new Date();
try{
List<ProgramTreeResult> results = this.baseMapper.findAllOrderByZtree();
List<ProgramTreeResult> nodes = new ArrayList<>();
// 定义一个组的node list
List<ProgramTreeResult> toFindParentList = new ArrayList<>();
String groupId = null;
for (int i = 0; i<results.size(); i++){
ProgramTreeResult result = results.get(i);
if (i == 0) {
groupId = result.getGroupId();
// group里放了一个最小的子节点
toFindParentList.add(result);
} else{
// 查询是否在一个组
if (groupId.equals(result.getGroupId()) && toFindParentList.size()>0){
List<ProgramTreeResult> toRemove = new ArrayList<>();
// 循环遍历待找到父节点的子节点
for (ProgramTreeResult toFind:toFindParentList) {
// 如果子节点是当前节点的子元素
if (toFind.getParentId()!=null && toFind.getParentId().equals(result.getId())){
// 赋值到当前节点的children中
List<ProgramTreeResult> children = result.getChildren();
if (children == null){
children = new ArrayList<>();
}
children.add(toFind);
result.setChildren(children);
// list中移除元素
//toFindParentList.remove(toFind);
toRemove.add(toFind);
}
}
toFindParentList.removeAll(toRemove);
// 找完无子节点或子节点已经全部加载完成
// 查询是否有父节点
if (result.getParentId() != null){
// 加入toFInd
toFindParentList.add(result);
} else{
// 加入节点
nodes.add(result);
}
} else{
// 不在一个组
groupId = result.getGroupId();
if (toFindParentList.size()>0){
nodes.addAll(toFindParentList);
}
toFindParentList.clear();
// group里放了一个最小的子节点
toFindParentList.add(result);
}
}
}
Date date2 = new Date();
System.out.println("时间差");
System.out.println(date2.getTime()-date1.getTime());
return nodes;
}catch (Exception e){
e.printStackTrace();
return null;
}
}
查询树节点的sql:
select *,if(pids is null,id,SUBSTRING_INDEX(pids,',',1))as groupId from tl_program_tree
ORDER BY groupId,CHAR_LENGTH(pids) desc
mysql表结构:
查询结果:
已经按组分好顺序,25条数据,查询+遍历分组耗时4ms。
前端显示: