java js 简单递归实现tree效果

因为业务要求做一个组织架构,就是理论上可以无限级的tree。第一次自己尝试写一棵树,分享一下过程。
解决这类不清楚有多少级节点的问题,用递归是最清爽的一个办法。


页面上最后展现的形式
<ul>
<li><div>一级节点</div>
  <ul>
    <li><div>二级节点</div>
        <ul>
          <li><div>三级节点</div></li>
        </ul>
    </li>
    <li><div>二级节点</div></li>   
</ul>


整理一下逻辑:前台需要的是一个List<HashMap>,list里每一个对象应该有一个key = "children" 对应的value 是List<HashMap>(子级节点数组),同理每一个子集节点还要有key="children"对应List<HashMap>,这样就形成了递归;

java后台:
首先根据我的一张组织架构的表如下



我们只需要关心 department_id 和 department_parent_id。
先把所有的department查询出来组成一个List<HashMap>,

下面我写了一个递归把没有层级结构的的List<HashMap>转化成前台需要的List<HashMap>
package com.asclepius.slhdt.uim.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;

public class TreeUtil {
	
	/**
	 * @param dataSource list数据源
	 * @param id	层级结构id	
	 * @param parentId	父级节点id
	 * @return	
	 */
	public static LinkedHashMap<String,HashMap> getTreeData(List<HashMap> dataSource,String id,String parentId)
	{
		LinkedHashMap returnMap = new LinkedHashMap();
		HashMap<String,String> root = new HashMap<String,String>();
		root.put(id, "");
		assembleTree(dataSource,root,id,parentId,1);
		returnMap.put("root",root);
		
		return returnMap;
	}
	
	public static void assembleTree(List<HashMap> dataSource,HashMap node ,String id,String parentId,Integer level)
	{
		List childList = getChildList(dataSource,node,id,parentId);
		node.put("children", childList);
		if(childList.size() > 0)
		{
			for(int i = 0 ; i<childList.size(); i++ )
			{
				HashMap child = (HashMap)childList.get(i);
				child.put("level", level);
				assembleTree(dataSource,child,id,parentId,level+1);
			}
		}
	}
	
	/**
	 * 得到子节点列表
	 */
	private static List getChildList(List<HashMap> dataSource,HashMap node,String id, String parentId )
	{
		List childList = new ArrayList();
		for (int i = 0; i < dataSource.size() ; i++) 
		{
			HashMap child = (HashMap)dataSource.get(i);
			String dictId = node.get(id).toString();
			String dictParentId = child.get(parentId).toString();
			if (dictId.equals(dictParentId))
			{
				childList.add(child);
				dataSource.remove(i);
				i--;
			}
		}
		return childList;
	}
}



返回给页面
LinkedHashMap<String,HashMap> hierarchyList = TreeUtil.getTreeData(departmentList,"departmentId","departmentParentId");
		List tree = (List)(hierarchyList.get("root").get("children"));
		
		return tree;




//组织架构树
	$.ajax({
		url:"/department/getdepartmentTree",
		type:"get",
		data:{hospitalId:hospital_id},
		success:function(data)
		{
			$(".subdivision").append(assembleTopTree(data));
		}
	});
/**
 * 组装一级节点
 */
function assembleTopTree(deptList)
{
	var $ul = $("<ul class='department-stair' id='deptTree' style='display:none' />");
	for(var i = 0; i<deptList.length; i++)
	{
		var $li=$("<li data-dept-id=" + deptList[i].departmentId + " >" +
				"<div class='department-name stair' >" +
				imgClick(deptList[i],true) +
				"</div>"+
				"<div class='subdivision-operate clearfix'>" +
				"<a href='javascript:void(0)' class='adddept'  data-dept-id="+deptList[i].departmentId + ">添加子部门</a>" +
				"<a href='javascript:void(0)' class='editdept' data-dept-id="+ deptList[i].departmentId + " >编辑</a><span>|</span>"+
				"<img class='delete' src='../../images/department/delete.png' data-dept-id="+ deptList[i].departmentId + " alt='删除' title='删除'/>" +
				mouseUpClass(i,deptList) + mouseDownClass(i,deptList) +
				"</div>" + assembleChildrenTree(deptList[i].children , deptList[i].departmentId)+"</li>");
		$ul.append($li);
	}
	return $ul;
}
/**
 * 组装子级节点
 */
function assembleChildrenTree(deptList,departmentId)
{
	var $ul = $("<ul class='department-stair' style='display:none' id="+ departmentId +"/>");
	for(var i = 0; i<deptList.length; i++)
	{
		var $li=$("<li data-dept-id=" + deptList[i].departmentId + "  >" +
				"<div class='department-name stair' >" +
				imgClick(deptList[i],false) +
				"</div>"+
				"<div class='subdivision-operate clearfix'>" +
				"<a href='javascript:void(0)' class='adddept'  data-dept-id="+deptList[i].departmentId + ">添加子部门</a>" +
				"<a href='javascript:void(0)' class='editdept' data-dept-id="+ deptList[i].departmentId + " >编辑</a><span>|</span>"+
				"<img class='delete' src='../../images/department/delete.png' data-dept-id="+ deptList[i].departmentId + " alt='删除' title='删除'/>" +
				mouseUpClass(i,deptList) + mouseDownClass(i,deptList) +
				"</div>" + assembleChildrenTree(deptList[i].children,deptList[i].departmentId) + "</li>");
		$ul.append($li);
	}
	
	return $ul[0].outerHTML;
}
/**
 * 是否有鼠标经过class
 */
function mouseUpClass(index , list)
{
	if(index == 0)
		return "<img class='move-up' style='opacity:0.4' src='../../images/department/move_up.png'  alt=''/>";
	else 
		return "<img  class='move-up' src='../../images/department/move_up.png'  alt=''/>";
}
/**
 * 是否有鼠标经过class
 */
function mouseDownClass(index , list)
{
	if(index == list.length - 1)
		return "<img class='move-down' style='opacity:0.4' src='../../images/department/move_down.png'  alt=''/>";
	else 
		return "<img class='move-down' src='../../images/department/move_down.png'  alt=''/>";
}
/**
 * 是否有展开按钮图标
 */
function imgClick(item , topOrChild)
{
	if(topOrChild)
		if(item.children.length > 0)
			return "<img src='../../images/department/arrow_right.png' data-dept-id="+item.departmentId +" style='margin-left:"+ item.level*10 +"px' /><span>"+ item.departmentProp.departmentNameAlias +"</span>"+
			(item.departmentProp.departmentClinical == 1 ? "<span class='identifier'>临床</span>" : "");
		else
			return "<span style='margin-left:"+ (14 + item.level*10) +"px' >"+ item.departmentProp.departmentNameAlias +"</span>"+
			(item.departmentProp.departmentClinical == 1 ? "<span class='identifier'>临床</span>" : "");
	else
		if(item.children.length > 0)
			return "<img src='../../images/department/arrow_right.png' data-dept-id="+item.departmentId +" style='margin-left:"+ item.level*10 +"px' /><span>"+ item.departmentProp.departmentNameAlias+"</span>"
			+(item.departmentProp.departmentClinical == 1 ? "<span class='identifier'>临床</span>" : "");
		else
			return "<span style='margin-left:"+ (14 + item.level*10) +"px' >"+ item.departmentProp.departmentNameAlias +"</span>" +
			(item.departmentProp.departmentClinical == 1 ? "<span class='identifier'>临床</span>" : "");
}





assembleChildrenTree中判断如果children长度不为0,再次调用assembleChildrenTree传入chidlren对应的List。最后的成果(css不在这里给出)

猜你喜欢

转载自chenshangge.iteye.com/blog/2279284
今日推荐