zTree 是一个依靠 jQuery 实现的多功能 “树插件”。优异的性能、灵活的配置、多种功能的组合是 zTree 最大优点。
API+Demo见zTree官网:http://www.treejs.cn/v3/main.php#_zTreeInfo
![这里写图片描述](https://img-blog.csdn.net/20180612102814212?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXN0aW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
<link rel="stylesheet" href="../../../css/demo.css" type="text/css">
<link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="../../../js/jquery-1.7.2.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.core.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.excheck.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.exedit.js">script>
/**
* zTree树
* id(节点id),pid(父节点id),name(节点名称)必须要有,
* 其他属性可以根据具体需求自行添加
* @author LiPing
* @create 2018-06-08-14:24
*/
public class ZTree {
private String id; //机构:机构id(orgId)、设备终端:设备id(deviceId)
private String pid;//机构:机构pid(superId)、设备终端:机构id(orgId)
private String name;//机构:机构name(orgName)、设备终端:设备No(deviceNo)
private boolean open;//机构:机构树节点打开open|关闭false,设备默认为false
private boolean isParent;//是否为父节点,设备默认为false
private boolean isDevice;//是否为设备终端
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPid() {
return pid;
}
public void setPid(String pid) {
this.pid = pid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isOpen() {
return open;
}
public void setOpen(boolean open) {
this.open = open;
}
public boolean isParent() {
return isParent;
}
public void setParent(boolean parent) {
isParent = parent;
}
public boolean isDevice() {
return isDevice;
}
public void setDevice(boolean device) {
isDevice = device;
}
//重写toString(),生成前台需要的JSON数据
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("{id:\"");
sb.append(id);
sb.append("\",pId:\"");
sb.append(pid);
sb.append("\",name:\"");
sb.append(name);
sb.append("\",open:\"");
sb.append(open);
sb.append("\",isParent:\"");
sb.append(isParent);
sb.append("\",isDevice:\"");
sb.append(isDevice);
sb.append("\"}");
return sb.toString();
}
/*
重写equals()和hashCode(),用于List的去重复对象:
根据id,pid,name,三者属性去重复
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ZTree zTree = (ZTree) o;
if (!id.equals(zTree.id)) return false;
if (!pid.equals(zTree.pid)) return false;
return name.equals(zTree.name) && id.equals(zTree.id) && pid.equals(zTree.pid) ;
}
@Override
public int hashCode() {
int result = id.hashCode();
result = 31 * result + pid.hashCode();
result = 31 * result + name.hashCode();
return result;
}
}
var nodes = [
{id:1, pId:0, name: "父节点1"},
{id:11, pId:1, name: "子节点1"},
{id:12, pId:1, name: "子节点2"}
];
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<HTML>
<HEAD>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link rel="stylesheet" href="../../../css/demo.css" type="text/css">
<link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="../../../js/jquery-1.7.2.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.core.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.excheck.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.exedit.js">script>
<SCRIPT type="text/javascript">
var zNodes = ${zTrees};
var setting = {
check: {
enable: true,
chkboxType: {"Y":"s", "N":"ps"}
},
data: {
simpleData: {
enable: true
}
}
};
$(document).ready(function(){
$.fn.zTree.init($("#treeDemo"), setting, zNodes);
});
function chooseSubmit() {
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
//获取勾选框选上的节点
var nodes = zTree.getCheckedNodes(true);
if (nodes.length == 0) {
// alert("请先选择一个节点");
alertMsg.error("请选择设备!");
return false;
}
var resultStr = "";
for (var i=0, l=nodes.length; iif (nodes[i].isDevice == "true"){
resultStr +=nodes[i].name + ",";
}
}
resultStr = resultStr.substring(0, resultStr.length - 1);
alert(resultStr);
if (resultStr == "") {
// alert("请先选择一个节点");
alertMsg.error("请选择设备!");
return false;
}
<%--$.ajax({--%>
<%--url : 'appInfo/appUpdateBatch',--%>
<%--type : "POST",--%>
<%--datatype : "json",--%>
<%--data : {--%>
<%--ids : resultStr,--%>
<%--server_id:'${server_id}',--%>
<%--server_version:'${server_version}'--%>
<%--},--%>
<%--success : function(data) {--%>
<%--if (data.statusCode=="200") {--%>
<%--alertMsg.correct(data.message);--%>
<%--$.pdialog.closeCurrent();--%>
<%--} else {--%>
<%--alertMsg.error(data.message);--%>
<%--$.pdialog.closeCurrent();--%>
<%--}--%>
<%--}--%>
<%--});--%>
}
SCRIPT>
HEAD>
<BODY>
<h1>同步加载(一次性加载)h1>
<div class="content_wrap">
<div class="zTreeDemoBackground left">
<ul id="treeDemo" class="ztree">ul>
div>
div>
BODY>
HTML>
获取ZTree数据,根据自身项目需求来,组装前端需要JSON数据,下面代码是我自身的业务需要:
//ZTree树List集合
List trees = new ArrayList<>();
@RequestMapping("/syncZTree")
public String syncZTree(HttpServletRequest request, HttpServletResponse response, Model model) {
try {
String server_id = request.getParameter("server_id");
String server_version = request.getParameter("server_version");
String orgId = CommonUtils.getOrgId(request);
List orgList = new ArrayList();
// 判断角色权限
if (CommonUtils.getOrgId(request) != null) {
Org org = new Org();
org.setOrgNo(CommonUtils.getOrgId(request));
org = orgService.queryOrgByOrgNo(org);
orgList.add(org);
} else {
orgList = orgService.queryOrgByDeep("0");// root权限进入则从此加载
}
List deviceList = deviceService.queryDeviceAll();
List tree = getRecursion(orgList);
String zTrees = getTree(tree, deviceList);
System.out.println("---------:"+zTrees);
model.addAttribute("server_id", server_id);
model.addAttribute("server_version", server_version);
//model.addAttribute("zTrees", zTrees);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return "business/application/syncZTree";
}
/**
* 获取zTree数据(机构):将org对象根据ZTree类来组装JSON数据
* 采用递归算法(我自身的业务需要,数据根据自身需求来组装)
* @param treeList
* @return
*/
private List getRecursion(List treeList) {
for (Org org : treeList) {
ZTree zTree1 = new ZTree();
zTree1.setId(org.getOrgId());
zTree1.setPid(org.getSuperId());
zTree1.setName(org.getOrgName());
zTree1.setOpen(true);
zTree1.setParent(true);
trees.add(zTree1);
List list = orgService.queryOrgByPId(org.getOrgId());
if (list.size() != 0) {
for (Org org1 : list){
ZTree zTree = new ZTree();
zTree.setId(org1.getOrgId());
zTree.setPid(org1.getSuperId());
zTree.setName(org1.getOrgName());
zTree.setOpen(true);
zTree.setParent(true);
trees.add(zTree);
}
getRecursion(list);
}
}
removeDuplicate(trees);
return trees;
}
/**
* 获取设备Tree数据,将Device对象根据ZTree类来组装JSON数据
* @param trees1 机构树
* @param deviceList 设备树
* @return
*/
public String getTree(List trees1, List deviceList){
for (Device device : deviceList) {
ZTree zTree = new ZTree();
zTree.setId(device.getDeviceId());
zTree.setPid(device.getOrgId());
zTree.setName(device.getDevNo());
zTree.setDevice(true);
trees1.add(zTree);
}
removeDuplicate(trees1);//去除重复的list
StringBuilder str = new StringBuilder();
for (ZTree tree2 : trees1){
str =str.append(tree2.toString()+",");
}
String s = str.toString().substring(0, str.toString().length()-1);
return "["+s+"]";
}
//List去重复
private static void removeDuplicate(List list) {
LinkedHashSet set = new LinkedHashSet(list.size());
set.addAll(list);
list.clear();
list.addAll(set);
}
<link rel="stylesheet" href="../../../css/demo.css" type="text/css">
<link rel="stylesheet" href="../../../css/zTreeStyle/zTreeStyle.css" type="text/css">
<script type="text/javascript" src="../../../js/jquery-1.7.2.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.core.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.excheck.js">script>
<script type="text/javascript" src="../../../js/jquery.ztree.exedit.js">script>
<script type="text/javascript">
var setting = {
//勾选框
check: {
enable: true,
chkboxType: {"Y":"s", "N":"ps"}
},
data : {
key:{
name:"name"
},
simpleData : {
enable : true,
idKey:"id",
pIdKey:"pid"
}
},
async: {
enable: true,
url:"appInfo/getNodesByAsync",
autoParam:["id"/*, "pid", "name"*/],//自动提交的参数(可提交多个)
// otherParam:{"otherParam":"zTreeAsyncTest"}
dataFilter: filter //异步返回后经过Filter
},
callback : {
onAsyncSuccess: zTreeOnAsyncSuccess,//异步加载完成调用
aOnAsyncError : zTreeOnAsyncError//加载错误的fun
}
};
/* 获取返回的数据,进行预操作,treeId是treeDemo,异步加载完之后走这个方法,responseData为后台返回数据 */
function filter(treeId, parentNode, responseData) {
// responseData = responseData.jsonArray;
if (!responseData){
return null;
}
return responseData;
}
//异步加载完成时运行
function zTreeOnAsyncSuccess(event, treeId, msg) {
}
//异步加载失败
function zTreeOnAsyncError(event, treeId, treeNode) {
alertMsg.error("异步加载节点失败!");
}
$(document).ready(function(){
$.fn.zTree.init($("#treeDemo"), setting);//异步获取json格式数据,第三个参数传null或者空着
});
function chooseSubmit() {
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = zTree.getCheckedNodes(true);
if (nodes.length == 0) {
alertMsg.error("请选择设备!");
return false;
}
var resultStr = "";
for (var i=0, l=nodes.length; iif (nodes[i].isDevice == "true"){
resultStr +=nodes[i].name + ",";
}
}
resultStr = resultStr.substring(0, resultStr.length - 1);
alert(resultStr);
if (resultStr == "") {
// alert("请先选择一个节点");
alertMsg.error("请选择设备!");
return false;
}
<%--$.ajax({--%>
<%--url : 'appInfo/appUpdateBatch',--%>
<%--type : "POST",--%>
<%--datatype : "json",--%>
<%--data : {--%>
<%--ids : resultStr,--%>
<%--server_id:'${server_id}',--%>
<%--server_version:'${server_version}'--%>
<%--},--%>
<%--success : function(data) {--%>
<%--if (data.statusCode=="200") {--%>
<%--alertMsg.correct(data.message);--%>
<%--$.pdialog.closeCurrent();--%>
<%--} else {--%>
<%--alertMsg.error(data.message);--%>
<%--$.pdialog.closeCurrent();--%>
<%--}--%>
<%--}--%>
<%--});--%>
}
script>
获取ZTree数据,根据自身项目需求来,组装前端需要JSON数据**
@RequestMapping("/getNodesByAsync")
public void getNodesByAsync(HttpServletRequest request, HttpServletResponse response, Model model) throws IOException {
List treeList = new ArrayList<>();
try {
String id = request.getParameter("id");
String pid = request.getParameter("pid");
String name = request.getParameter("name");
String orgId = CommonUtils.getOrgId(request);
List orgList = new ArrayList();
if (id == null) {//初始化加载root节点
判断角色权限
if (CommonUtils.getOrgId(request) != null) {
Org org = new Org();
org.setOrgNo(CommonUtils.getOrgId(request));
org = orgService.queryOrgByOrgNo(org);
orgList.add(org);
} else {
orgList = orgService.queryOrgByDeep("0");// root权限进入则从此加载
}
//装配成ZTree
for (Org orgs : orgList) {
ZTree zTree3 = new ZTree();
zTree3.setId(orgs.getOrgId());
zTree3.setPid(orgs.getSuperId());
zTree3.setName(orgs.getOrgName());
zTree3.setOpen(true);
zTree3.setParent(true);
treeList.add(zTree3);
}
} else {//异步加载子节点
List rogLists = orgService.queryOrgByPId(id);//根据id查找该id机构下的机构
//if (rogLists != null && rogLists.size() == 0) {//如果该机构下午机构,查找该机构下的设备,如果也没有设备,返回空
List deviceList = deviceService.queryDeviceByOrgID(id);//根据id查找该id机构下的设备
if (deviceList.size() != 0) {
for (Device device : deviceList) {
ZTree zTreeDev = new ZTree();
zTreeDev.setId(device.getDeviceId());
zTreeDev.setPid(device.getOrgId());
zTreeDev.setName(device.getDevNo());
zTreeDev.setDevice(true);
treeList.add(zTreeDev);
}
}
//} else {//有机构,返回机构list,组成List, 返回json
for (Org orgs : rogLists) {
ZTree zTree2 = new ZTree();
zTree2.setId(orgs.getOrgId());
zTree2.setPid(orgs.getSuperId());
zTree2.setName(orgs.getOrgName());
zTree2.setOpen(true);
zTree2.setParent(true);
treeList.add(zTree2);
}
}
//}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
PrintWriter out = response.getWriter();
StringBuilder str = new StringBuilder();
for (ZTree tree2 : treeList) {
str = str.append(tree2.toString() + ",");
}
String s = str.toString().substring(0, str.toString().length() - 1);
System.out.println("[" + s + "]");
out.print("[" + s + "]");
}
具体实现方法说明如下:
<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<form class="pageForm required-validate" method="post" action="">
<div class="pageFormContent" layoutH="65" id="assignModule">
<ul id="treeDemo" class="ztree">ul>
div>
<div class="formBar">
<ul>
<li><div class="buttonActive">
<div class="buttonContent">
<button type="button" onclick="chooseSubmit()">保存button>
div>
div>li>
<li><div class="buttonActive">
<div class="buttonContent">
<button type="button" onclick="expandAll()">全部展开button>
div>
div>li>
<li><div class="button">
<div class="buttonContent">
<button type="button" class="close">取消button>
div>
div>li>
ul>
div>
form>
<script type="text/javascript">
var setting = {
//勾选框
check: {
enable: true,
chkboxType: {"Y":"s", "N":"ps"}
},
data : {
key:{
name:"name"
},
simpleData : {
enable : true,//JSON格式采用简单数组格式
idKey:"id",
pIdKey:"pid"
}
},
async: {
enable: true,
url:"appInfo/getNodesByAsync",
autoParam:["id"/*, "pid", "name"*/],//自动提交的参数(可提交多个)
// otherParam:{"otherParam":"zTreeAsyncTest"}
dataFilter: filter //异步返回后经过Filter
},
callback : {
beforeAsync: beforeAsync,
onAsyncSuccess: zTreeOnAsyncSuccess,//异步加载完成调用
aOnAsyncError : zTreeOnAsyncError//加载错误的fun
}
};
/* 获取返回的数据,进行预操作,treeId是treeDemo,异步加载完之后走这个方法,responseData为后台返回数据 */
function filter(treeId, parentNode, responseData) {
// responseData = responseData.jsonArray;
if (!responseData){
return null;
}
return responseData;
}
function beforeAsync() {
curAsyncCount++;
}
//异步加载完成时运行
function zTreeOnAsyncSuccess(event, treeId, treeNode, msg) {
curAsyncCount--;
if (curStatus == "expand") {
expandNodes(treeNode.children);
} else if (curStatus == "async") {
asyncNodes(treeNode.children);
}
if (curAsyncCount <= 0) {
if (curStatus != "init" && curStatus != "") {
// $("#demoMsg").text((curStatus == "expand") ? demoMsg.expandAllOver : demoMsg.asyncAllOver);
asyncForAll = true;
}
curStatus = "";
}
}
//异步加载失败
function zTreeOnAsyncError(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {
// alertMsg.error("异步加载节点失败!");
curAsyncCount--;
if (curAsyncCount <= 0) {
curStatus = "";
if (treeNode!=null) asyncForAll = true;
}
}
var curStatus = "init", curAsyncCount = 0, asyncForAll = false,
goAsync = false;
function expandAll() {
if (!check()) {
return;
}
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
if (asyncForAll) {
// $("#demoMsg").text(demoMsg.expandAll);
// alertMsg.error("已全部展开");
zTree.expandAll(true);
} else {
expandNodes(zTree.getNodes());
if (!goAsync) {
// $("#demoMsg").text(demoMsg.expandAll);
// alertMsg.error("已全部展开");
curStatus = "";
}
}
}
function expandNodes(nodes) {
if (!nodes) return;
curStatus = "expand";
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
for (var i=0, l=nodes.length; itrue , false, false);
if (nodes[i].isParent && nodes[i].zAsync) {
expandNodes(nodes[i].children);
} else {
goAsync = true;
}
}
}
function asyncAll() {
if (!check()) {
return;
}
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
if (asyncForAll) {
// $("#demoMsg").text(demoMsg.asyncAll);
// alertMsg.error("已经异步加载完毕");
} else {
asyncNodes(zTree.getNodes());
if (!goAsync) {
// $("#demoMsg").text(demoMsg.asyncAll);
// alert("已经异步加载完毕");
curStatus = "";
}
}
}
function asyncNodes(nodes) {
if (!nodes) return;
curStatus = "async";
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
for (var i=0, l=nodes.length; iif (nodes[i].isParent && nodes[i].zAsync) {
asyncNodes(nodes[i].children);
} else {
goAsync = true;
zTree.reAsyncChildNodes(nodes[i], "refresh", true);
}
}
}
function check() {
if (curAsyncCount > 0) {
// $("#demoMsg").text(demoMsg.async);
return false;
}
return true;
}
$(document).ready(function(){
$.fn.zTree.init($("#treeDemo"), setting);//异步获取json格式数据,第三个参数传null或者空着
});
function chooseSubmit() {
var zTree = $.fn.zTree.getZTreeObj("treeDemo");
var nodes = zTree.getCheckedNodes(true);
if (nodes.length == 0) {
alertMsg.error("请选择设备!");
return false;
}
var resultStr = "";
for (var i=0, l=nodes.length; iif (nodes[i].isDevice == "true"){
resultStr +=nodes[i].name + ",";
}
}
resultStr = resultStr.substring(0, resultStr.length - 1);
// alert(resultStr);
if (resultStr == "") {
// alert("请先选择一个节点");
alertMsg.error("请选择设备!");
return false;
}
$.ajax({
url : 'appInfo/appUpdateBatch',
type : "POST",
datatype : "json",
data : {
ids : resultStr,
server_id:'${server_id}',
server_version:'${server_version}'
},
success : function(data) {
if (data.statusCode=="200") {
alertMsg.correct(data.message);
$.pdialog.closeCurrent();
} else {
alertMsg.error(data.message);
$.pdialog.closeCurrent();
}
}
});
}
script>
参考:
PS:service层,DAO层涉及公司机密,此处不予贴出,有问题可评论或私信