ztree 的构建

需求:在项目下有许多个模块,需要在 树形菜单中对模块进行管理(包括增加删除节点,以及修改节点文本信息)

寻找解决方法:打算用网上的插件,找了多个,觉得 ZTREE 插件比较符合我的要求,随即下载了源码包,当中有许多例子,

官方有文档和预览效果,最终 async_edit.html  这个例子作为模板。

解决过程:后台使用的springmvc ,数据库mysql ,前台jsp 

在数据库中 的  module数据表 字段有  id, prarentid,name  属性

TreeNode.java 是用来传递数据的实体类,代码如下

import java.util.List;

public class TreeNode{  
    private Integer id;  
    private String name;  
    private Integer parentid;  
    private List<TreeNode> children;
	
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	
	public Integer getParentid() {
		return parentid;
	}
	public void setParentid(Integer parentid) {
		this.parentid = parentid;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	
	public List<TreeNode> getChildren() {
		return children;
	}
	public void setChildren(List<TreeNode> children) {
		this.children = children;
	}  
      
}  
</pre>将数据库 module 数据表的数据通过 treenode 包装成 json数据 返回给前台,代码如下<pre name="code" class="html">/**
	 * 显示模块树形列表
	 * @param projectid
	 * @return
	 */
	@RequestMapping("/findlist")
	 public @ResponseBody List<TreeNode> findlist(@RequestParam(value = "projectid", required = false) Integer projectid,Model model) {
		 List<TreeNode> nodeList = new ArrayList<TreeNode>();
		 TreeNode rootnode = new TreeNode();
		 rootnode.setId(0);
		 rootnode.setName("项目模块");
		 rootnode.setChildren(new ArrayList<TreeNode>());
		if(projectid==null){
			nodeList.add(rootnode);
			return nodeList;
		}
		 List<Module> modules = moduleService.selectByProjectId(projectid);
		 List<TreeNode> treelist = new ArrayList<TreeNode>();  
		
		 for (Module module : modules) {
			TreeNode treeNode = new TreeNode();
			treeNode.setId(module.getId());
			treeNode.setName(module.getName());
			if(module.getParentid()!=null){
				treeNode.setParentid(module.getParentid());
			}
			treelist.add(treeNode);
		}
		 if(!treelist.isEmpty()){
			 for(TreeNode node1 : treelist){  
			     boolean mark = false;  
			     for(TreeNode node2 : treelist){  
			         if(node1.getParentid()!=null && node1.getParentid().equals(node2.getId())){  
			             mark = true;  
			             if(node2.getChildren() == null)  
			                 node2.setChildren(new ArrayList<TreeNode>());  
			             node2.getChildren().add(node1);   
			             break;  
			         }  
			     }  
			     if(!mark){
			    	 rootnode.getChildren().add(node1);;
			     }  
			 }
			 nodeList.add(rootnode);  
		 }
		 //转为json格式        
		return nodeList;
	}
	
	/**
	 * 获取项目中模块的最大id
	 * @param projectid
	 * @return
	 */
	public int getMaxModuleId(){
		 List<Module> modules = moduleService.selectList();
		 int max=0;
		 for (Module module : modules) {
				if(max<module.getId()){
					 max=module.getId();
				}
		}
		 return max;
	}

由于没有将整个项目作为根节点保存进数据库,所以这里手动指定 rootnode 为根节点,并做了相应逻辑判断,当该项目下没有模块是,仍然显示根节点的数据(不参与数据库读写,后边存数据的时候做了剔除)


前台 js 

 function init() {
		$('.easy-tree').EasyTree({
			addable: true,
			editable: true,
			deletable: true
		});
	}
	
	var setting = {
			async: {
				enable: true,
				url:"project/findlist?projectid="+$("#projectid").val()+"",
				autoParam:["id", "name=n", "level=lv"],
				otherParam:{"otherParam":"zTreeAsyncTest"},
				dataFilter: filter
			},
			view: {expandSpeed:"",
				addHoverDom: addHoverDom,
				removeHoverDom: removeHoverDom,
				selectedMulti: false
			},
			edit: {
				enable: true,
				showRemoveBtn: setRemoveBtn,
			    showRenameBtn: setRemoveBtn
			},
			data: {
				simpleData: {
					enable: true
				}
			},
			callback: {
				beforeAsync: beforeAsync,
				onAsyncSuccess: onAsyncSuccess,
				onAsyncError: onAsyncError,
				beforeRemove: beforeRemove,
				beforeRename: beforeRename,
			}
		};

		function setRemoveBtn(treeId, treeNode) {
		 if(treeNode.level == 0)
				return false;
			else
				return true;
		};
	
		function filter(treeId, parentNode, childNodes) {
			if (!childNodes) return null;
			for (var i=0, l=childNodes.length; i<l; i++) {
				childNodes[i].name = childNodes[i].name.replace(/\.n/g, '.');
			}
			return childNodes;
		}
		function beforeRemove(treeId, treeNode) {
			var zTree = $.fn.zTree.getZTreeObj("treeDemo");
			zTree.selectNode(treeNode);
			return confirm("确认删除 模块 -- " + treeNode.name + " 吗?");
		}		
		function beforeRename(treeId, treeNode, newName) {
			if (newName.length == 0) {
				alert("模块名称不能为空.");
				return false;
			}
			return true;
		}

		var newCount = 1;
		function addHoverDom(treeId, treeNode) {
			var sObj = $("#" + treeNode.tId + "_span");
			if (treeNode.editNameFlag || $("#addBtn_"+treeNode.tId).length>0) return;
			var addStr = "<span class='button add' id='addBtn_" + treeNode.tId
				+ "' title='add node' οnfοcus='this.blur();'></span>";
			sObj.after(addStr);
			var btn = $("#addBtn_"+treeNode.tId);
			if (btn) btn.bind("click", function(){
				var zTree = $.fn.zTree.getZTreeObj("treeDemo");
				zTree.addNodes(treeNode, {id:(parseInt("${maxnode}") + newCount), pId:treeNode.id, name:"new node" + (newCount++)});
				return false;
			});
		};
		function removeHoverDom(treeId, treeNode) {
			$("#addBtn_"+treeNode.tId).unbind().remove();
		};
		function beforeAsync() {
			curAsyncCount++;
		}
		
		function onAsyncSuccess(event, treeId, treeNode, msg) {
		
				var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
				treeObj.expandAll(true);
				
		}

		function onAsyncError(event, treeId, treeNode, XMLHttpRequest, textStatus, errorThrown) {
			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);
				zTree.expandAll(true);
			} else {
				expandNodes(zTree.getNodes());
				if (!goAsync) {
					$("#demoMsg").text(demoMsg.expandAll);
					curStatus = "";
				}
			}
		}
		function expandNodes(nodes) {
			if (!nodes) return;
			curStatus = "expand";
			var zTree = $.fn.zTree.getZTreeObj("treeDemo");
			for (var i=0, l=nodes.length; i<l; i++) {
				zTree.expandNode(nodes[i], true, false, false);
				if (nodes[i].isParent && nodes[i].zAsync) {
					expandNodes(nodes[i].children);
				} else {
					goAsync = true;
				}
			}
		}
		function check() {
			if (curAsyncCount > 0) {
				$("#demoMsg").text(demoMsg.async);
				return false;
			}
			return true;
		}
		function treenodeClick() {
			zTree = $.fn.zTree.getZTreeObj("treeDemo");
			var nodes=zTree.getNodes();
			var	nodes_array = zTree.transformToArray (nodes);
			var tempResult = [];
			var str = "";
 			for(var i=0;i<nodes_array.length;i++){
				str = '{"id":'+nodes_array[i].id+',"name":"'+nodes_array[i].name.replace(/\s+/g,"")+'","parentid":'+nodes_array[i].pId+'}';
				tempResult.push(str);
 			} 
			var treelist =eval(tempResult);
 			treelist = "["+treelist+"]";
 			$("#treejson").val(treelist);
	  }


大体和示例中一致,做了部分改变,比如
edit: {
				enable: true,
				showRemoveBtn: setRemoveBtn,
			    showRenameBtn: setRemoveBtn
			},
中移除了根节点的修改和删除图标,防止删除所有节点后,不能再添加新的节点。

treenodeClick()
方法中返回了修改后的 ztree,将所有节点的数据转换成了 json数据,这里碰到了些问题,最后自己拼的数据,直接用 JSON.stringify 的时候,生成的json 字符串老是多引号,像这样 ["{}","{}","{}"]  并列的对象之间多了 双引号 ,正常应该是 [{},{},{}] , 这里应该是  push进数组的时候被加上的,后来 改成了用 eval 转化成json对象,再在外边套上了 中括号,对于节点文本中的空格 在 
addHoverDom 

方法中做了去空格处理,然后通过表单的隐藏域将json 传回了后台,这里不去空格的话,会出现错误,空格后的字符会消失

后台代码如下

/**
	 * 根据属性菜单值更新模块数据
	 * @param projectid
	 * @param request
	 */
	public void updateModules(Integer projectid,HttpServletRequest request){
			List<Module> modulelist =  moduleService.selectByProjectId(projectid);
			boolean flag = false;
			String newtree = request.getParameter("treejson");
			List<TreeNode> treelist = JSON.parseArray(newtree,TreeNode.class); 
			for (TreeNode node : treelist) {
				if(node.getId()!=0){
				for (Module m : modulelist){
					if(node.getId()==m.getId()){
						m.setName(node.getName());
						if(node.getParentid()!=0){
							m.setParentid(node.getParentid());
						}
						m.setProjectid(projectid);
						moduleService.update(m);
						flag=true;
						break;
					}
				}
				if(flag==false){
					Module newmodule =new Module();
					newmodule.setName(node.getName());
					if(node.getParentid()!=0){
						newmodule.setParentid(node.getParentid());
					}
					newmodule.setProjectid(projectid);
					moduleService.insert(newmodule);
				}
	            flag=false;
				}
			} 
			
			for (Module m : modulelist){
				for (TreeNode bar : treelist) { 
					if(m.getId()==bar.getId()){
						flag=true;
						break;
					}
				}
				if (flag==false) {
					moduleService.deleteById(m.getId());
				}
				flag=false;
			}
	}


将新的模块数据与数据库数据进行比较,并更新到数据库中。


整过过程中遇到了不少问题,最后算是大部分都解决了,特此记录一下




  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值