一、引入相关css与js
<link rel="stylesheet" href="/plug-in/ips-ui/vendors/zTree_v3/css/zTreeStyle/zTreeStyle.css"/>
<script src="/plug-in/ips-ui/js/jquery.1.11.0.min.js"></script>
<script src="/plug-in/ips-ui/vendors/zTree_v3/js/jquery.ztree.core.min.js"></script>
<script src="/plug-in/ips-ui/vendors/layui/layui.all.js"></script>
二、zTree相关HTML
<!-- zTree -->
<div class="expansion-con animated bounceInLeft ">
<div class="content-con">
<p>根组件</p>
<div class="zTree-con">
<!-- 此处加载树形结构 -->
<ul id="tree" class="ztree"></ul>
</div>
<div class="btn-con">
<button class="btn btn-file btn-file-add active">新建</button>
<button class="btn btn-file btn-file-edit">编辑</button>
<button class="btn btn-file btn-file-delete">删除</button>
<button class="btn btn-file btn-file-close">关闭</button>
</div>
</div>
</div>
三、zTree配置设置以及初始化
// 初始化ztree
var zTreeObj;
var setting = {
data : {
simpleData : {
enable : true, // 设置启用简单数据格式[{id, pid, name}, {id, pid, name}]
idKey : "id", // 节点数据中保存唯一标识的属性名称
pIdKey : "pid", // 节点数据中保存其父节点唯一标识的属性名称
rootPId : "0" // 根节点id
}
},
async:{
enable: true, // 开启异步加载模式
url: "/ipsMaterialFolder/getChildNodes.do",
autoParam: ["id"], // 异步加载时需要自动提交父节点属性的参数
dataType:"json",
},
callback: {
onAsyncSuccess: function(event, treeId, treeNode, msg){ // 异步加载正常结束的事件回调函数,用于逐级展开子节点
if(treeNode.isParent == true && treeNode.children
&& treeNode.children.length > 0) {
var children = treeNode.children;
for(var i = 0, length = children.length; i < length; i++) {
zTreeObj.reAsyncChildNodes(children[i], "refresh", false);
}
zTreeObj.expandNode(treeNode, true);
}
}
}
};
$(document).ready(function(){
var url = "/ipsMaterialFolder/getAll.do";
$.getJSON(url, function(result){
if(result.code == '0'){
var zNodes = result.list;
zNodes.forEach(function(node){ // 添加自定义图标
node["icon"] = "/plug-in/ips-ui/img/icons/file.png";
})
//访问zTree方法通过数据初始化节点信息
zTreeObj = $.fn.zTree.init($("#tree"), setting, zNodes);
// 默认全部展开节点
zTreeObj.expandAll(true);
}else{
alert("初始化附件文件夹失败!");
}
});
});
四、树形节点数据结构
4.1、数据结构
4.2、数据样例
五、获取所有节点以及异步加载的java方法
@Controller
@RequestMapping("/ipsMaterialFolder")
public class IpsMaterialFolderController extends BaseController {
@Autowired
private IpsMaterialFolderServiceI folderService;
/**
* 获取所有文件夹数据
* @return
*/
@RequestMapping(value = "getAll")
@ResponseBody
public Map<String, Object> getAll(){
Map<String, Object> result = new HashMap<>();
int code = 0;
String msg = "数据获取成功";
try {
result.put("list", folderService.getList(IPSMaterialFolderEntity.class));
} catch (Exception e){
code = -1;
msg = "数据获取失败!" + e.getMessage();
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}
result.put("code", code);
result.put("msg", msg);
return result;
}
/**
* 异步刷新该节点下的节点
* @param id
* @return
*/
@RequestMapping(value = "getChildNodes")
@ResponseBody
public List<Map<String, Object>> getChildNodesByPid(String id) {
List<Map<String, Object>> list = null;
if(StringUtils.isNotBlank(id)){
String pids = null;
if(id.equals("0")){
pids = id + ",";
} else {
pids = "," + id + ",";
}
String sql = "select f.id, f.name, f.pid, f.pids, '/plug-in/ips-ui/img/icons/file.png' AS icon from ips_material_folder f where instr(f.pids, ?) > 0 ";
list = folderService.findForJdbc(sql, pids);
}
return list;
}
/**
* 新增文件夹
* @param folder
* @param request
* @return
*/
@RequestMapping(value = "doAdd")
@ResponseBody
public AjaxJson doAdd(IPSMaterialFolderEntity folder, HttpServletRequest request) {
String message = null;
AjaxJson result = new AjaxJson();
message = "新增文件夹成功!";
try {
// 判断兄弟节点中有无同名的
String query = "select id from ips_material_folder where pid = ? and name = ? ";
List<Map<String, Object>> list = folderService.findForJdbc(query, folder.getPid(), folder.getName());
if(list != null && list.size() > 0){
result.setSuccess(false);
message = "此父节点下已有该文件夹!";
} else {
folderService.save(folder);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
result.setSuccess(false);
message = "新增文件夹失败!";
throw new RuntimeException(e);
}
return result;
}
}
六、新增节点
/** 新增文件夹 */
var maxLevel = '${maxLevel}'; // 获取设定的最大层级
$(document).on('click', '.btn-file-add', function () {
$(this).addClass('active').siblings().removeClass('active');
// 1.获取选中的节点
var selectedNodes = zTreeObj.getSelectedNodes();
if(selectedNodes.length < 1){
layer.msg("请选择父文件夹!");
return;
}
var node = selectedNodes[0];
var parentNode = node.getParentNode();
var children = node.children;
layer.open({
type: 1,
title: "新增文件夹",
area: ['522px', '244px'],
closeBtn: 1,
shadeClose: false,
skin: 'layer-custom',
move: false,
content: '<form class="layui-form layui-form-file" action="" lay-filter="example">' +
'<div class="layui-form-item">' +
'<label class="layui-form-label">文件夹名称</label>' +
'<div class="layui-input-block">' +
'<input type="text" id="foldename" name="foldename" value="" lay-verify="" autocomplete="off" class="layui-input">' +
'</div>' +
'</div>' +
'</form>',
btn: ["提交", "取消"],
yes: function (index, layero) {
// 确认操作
var name = $.trim($("#foldename").val());
if(name == null || name == ''){
layer.msg("请填写文件夹名称之后再提交!");
return;
} else {
for(var i in children){
var thisNode = children[i];
if(name == thisNode.name){
layer.msg("该层级已有此文件夹,无需新增!");
return;
}
}
}
var pids = node.pids + node.id + ",";
if(parentNode == null){
pids = node.id + ",";
}
var level = node.level;
++level;
if(level > maxLevel - 1){
layer.msg("文件夹最多只能建" + maxLevel + "级, 请重新选择父节点!");
return;
}
var url = "/ipsMaterialFolder/doAdd.do";
var params = {
name: name,
pid: node.id,
pids: pids,
level: level
};
$.post(url, params, function(res){
res = JSON.parse(res);
if(res.success == true){
// reAsyncChildNodes第一个参数节点isParent=false时,不进行异步加载
if(node.id == '0' || node.isParent){
if(node.id == '0' && (children == null || children.length < 1)){
node.isParent = true;
}
zTreeObj.reAsyncChildNodes(node, "refresh", false);
} else {
zTreeObj.reAsyncChildNodes(parentNode, "refresh", false);
}
layer.msg("新增文件夹保存成功!");
layer.close(index);
} else {
layer.msg("新增文件夹保存失败!");
}
});
},
btn2: function (index, layero) {
// 取消操作
layer.close(index);
},
end: function () {
}
});
});
七、效果图
注:zTree官方API文档