自定义树Tree

本例是jQueryEasyUi中datagrid的树形展示,包含上下移动,编辑等。

可以主要看树形的部分。

 

Bean:

package com.zte.soa.demo.model;

import java.util.List;

public class Tree {
	
	private Long id;
	private Long pid;
	private List<Tree> children;

	private String attribute1;
	private String attribute2;
	private String attribute3;
	private String attribute4;
	private String attribute5;
	private String attribute6;
	private String attribute7;
	private String attribute8;
	private String attribute9;  //serviceId
	
	private Long treeIndex;  //treeIndex
	
	//临时Id、Pid,操作时取该字段
	private String idStr;
	private String pidStr;
	
	...
	
}

 

package com.zte.soa.demo.model;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import com.zte.soa.util.JsonDateSerializer;

/**
 * 类 编 号:
 * 类 名 称: EipServiceParameter
 * 内容摘要: 
 * 完成日期: 
 * 编码作者:
*/
@Entity
@Table(name = "eip_service_parameter")
public class EipServiceParameter  implements Serializable
{

	/**
	 * 
	 */
	private static final long serialVersionUID = -3159405932590138034L;

	@Id
	@SequenceGenerator(name = "EIP_SERVICE_PARAMETER_S", sequenceName = "EIP_SERVICE_PARAMETER_S", initialValue = 1, allocationSize = 1)
	@GeneratedValue(strategy = GenerationType.SEQUENCE, generator="EIP_SERVICE_PARAMETER_S")
	@Column(name = "ID", nullable = false)
	protected java.lang.Long  id;
	
	@Column(name = "SERVICE_VERSION_ID")
	protected Long serviceId;
	
	@Column(name = "PARAMETER_NAME_CH", nullable = false)
	protected java.lang.String  parameterNameCh;
	
	@Column(name = "PARAMETER_NAME_EN", nullable = false)
	protected java.lang.String  parameterNameEn;
	
	@Column(name = "REMARK", nullable = true)
	protected java.lang.String  remark;
	
	@Column(name = "PARAMETER_TYPE", nullable = true)
	protected java.lang.String  parameterType;
	
	@Column(name = "DATA_TYPE", nullable = false)
	protected java.lang.String  dataType;
	@Column(name = "DATA_TYPE_LENGTH")
	protected java.lang.Long  dataTypeLength;
	@Column(name = "BELONG_FLAG", nullable = false)
	protected java.lang.String  belongFlag;
	@Column(name = "PARAM_CONSTRAINT", nullable = true)
	protected java.lang.String  constraint;
	
	@Column(name = "PARENT_PARAMETER_ID")
	protected java.lang.Long  parentParameterId;
   
	@Column(name = "CREATED_BY")
	protected java.lang.Long  createdBy;
	
	@Column(name = "CREATION_DATE")
	@Temporal(TemporalType.DATE)
	@JsonSerialize(using=JsonDateSerializer.class)
	protected java.util.Date  creationDate;

    @Column(name = "LAST_UPDATED_BY", nullable = false)
    protected java.lang.Long lastUpdateBy;

    @Column(name = "LAST_UPDATE_LOGIN", nullable = false)
    protected java.lang.Long lastUpdateLogin;

    @Column(name = "LAST_UPDATE_DATE", nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    @JsonSerialize(using = JsonDateSerializer.class, include = JsonSerialize.Inclusion.NON_NULL)
    protected java.util.Date lastUpdateDate;

    @Column(name = "ENABLED_FLAG", length = 1)
    protected java.lang.String enabledFlag;
    
    @Column(name = "TREE_INDEX")
	protected java.lang.Long  treeIndex;
    ...	
}

 

Java:

package com.zte.soa.demo.controller.json;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.map.ObjectMapper;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import com.zte.soa.demo.model.EipServiceParameter;
import com.zte.soa.demo.model.EipUser;
import com.zte.soa.demo.model.Tree;
import com.zte.soa.demo.model.User;
import com.zte.soa.demo.service.EipServiceParmService;
import com.zte.soa.demo.service.EipServiceService;
import com.zte.soa.demo.service.EipUserService;
import com.zte.soa.demo.service.UserService;

@Controller
public class UserController {

	@Autowired
	protected EipServiceParmService eipServiceParmService;
	
	
	public static <T> T fromJson(String json, Class<T> valueType){
		ObjectMapper mapper = new ObjectMapper();
		try {
			return mapper.readValue(json, valueType);
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	public static String toJson(Object obj){
		String json = "";
		ObjectMapper mapper = new ObjectMapper();
		try {
			StringWriter writer = new StringWriter();
			JsonGenerator generator = mapper.getJsonFactory().createJsonGenerator(writer);
			mapper.writeValue(generator, obj);
			json = writer.toString();
			generator.close();
			writer.close();			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return json;
	}
	
	
	public EipServiceParameter getOriginalData(Tree t1){
		EipServiceParameter p = new EipServiceParameter();
		p.setParentParameterId(Long.parseLong(t1.getPidStr()));
		p.setParameterNameCh(t1.getAttribute1());
		p.setParameterNameEn(t1.getAttribute2());
		p.setDataType(t1.getAttribute3());
		Long dataTypeLen = StringUtils.isBlank(t1.getAttribute4()) || t1.getAttribute4().equals("null") ? 0 : Long.parseLong(t1.getAttribute4());
		p.setDataTypeLength(dataTypeLen);
		p.setBelongFlag(t1.getAttribute5());
		p.setConstraint(t1.getAttribute6());
		p.setParameterType(t1.getAttribute7());
		p.setRemark(t1.getAttribute8());
		p.setServiceId(Long.parseLong(t1.getAttribute9()));
		p.setTreeIndex(t1.getTreeIndex());
		
		p.setCreatedBy(1l);
		p.setCreationDate(new Date());
		p.setLastUpdateBy(1l);
		p.setLastUpdateDate(new Date());
		p.setLastUpdateLogin(1L);
		p.setEnabledFlag("Y");
		p = eipServiceParmService.save(p);
		return p;
	}
	
	public Boolean checkIsBlankAppend(Map map ){
		if(StringUtils.isBlank(String.valueOf(map.get("attribute1"))) &&
				StringUtils.isBlank(String.valueOf(map.get("attribute2"))) &&	
				StringUtils.isBlank(String.valueOf(map.get("attribute3"))) &&	
				StringUtils.isBlank(String.valueOf(map.get("attribute4"))) &&	
				StringUtils.isBlank(String.valueOf(map.get("attribute5")))		
			)
			return true;
		
		return false;
	}
	
	public List<Tree> changeDataType(List<HashMap> list){
		List<Tree> treeList = new ArrayList<Tree>();
		for(Map map : list){
			if(checkIsBlankAppend(map)) continue; //忽略空白添加
			Tree t = new Tree();
			String idStr = String.valueOf(map.get("id"));
			String pidStr = String.valueOf(map.get("pid"));
			//t.setId(idStr.startsWith("copy") ? 0l : Long.parseLong(idStr));
			//t.setPid(pidStr.startsWith("copy") ? 0l : Long.parseLong(pidStr));
			t.setAttribute1(String.valueOf(map.get("attribute1")));
			t.setAttribute2(String.valueOf(map.get("attribute2")));
			t.setAttribute3(String.valueOf(map.get("attribute3")));
			t.setAttribute4(String.valueOf(map.get("attribute4")));
			t.setAttribute5(String.valueOf(map.get("attribute5")));
			t.setAttribute6(String.valueOf(map.get("attribute6")));
			t.setAttribute7(String.valueOf(map.get("attribute7")));
			t.setAttribute8(String.valueOf(map.get("attribute8")));
			t.setAttribute9(String.valueOf(map.get("attribute9")));
			t.setIdStr(idStr);
			t.setPidStr(pidStr);
			t.setTreeIndex(Long.parseLong(String.valueOf(map.get("treeIndex"))));
			treeList.add(t);
		}
		return treeList;
	}
	
	/*
	 * 需要添加的都为新增节点,id都是如copy1000这种临时Id
	 * 添加需要一个一个保存到数据库,因为可能新增的节点他的父节点也是新增的,需要得到真实的父节点Id
	 */
	public void insertData(List<Tree> insertedList , Map<String,Long> copyIdsMap){
		System.out.println();
		//先保存父节点是真实节点的数据,保存后从List中删除
		for(int i = insertedList.size() - 1 ; i >= 0 ;i--){
			Tree t1 = insertedList.get(i);
			String copyId = t1.getIdStr();
			String pid = t1.getPidStr();
			//父节点也是新增的
			if(pid.startsWith("copy")) continue; 
			EipServiceParameter p = getOriginalData(t1);
			insertedList.remove(t1);
			copyIdsMap.put(copyId, p.getId());  //收集新增节点的真实Id,以备其他父节点是临时Id的节点使用
		}
		//再递归保存父节点是临时节点的数据
		for(int i = insertedList.size() - 1 ; i >= 0 ;i--){
			Tree t = insertedList.get(i);
			String copyId = t.getIdStr();
			String pid = t.getPidStr();
			if(copyIdsMap.containsKey(pid)){
				Long id = copyIdsMap.get(pid); //获取真实Id
				t.setPidStr(String.valueOf(id));
				EipServiceParameter p = getOriginalData(t);
				insertedList.remove(t);
				copyIdsMap.put(copyId, p.getId()); 
			}else{
				insertData(insertedList,copyIdsMap); //递归获取id
			}
		}
		
	}
	
	
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/json/saveTreeGridData.json")
	@ResponseBody
	public Map<String, Object> saveTreeGridData(@RequestParam String treeGridData) {
		Map map = fromJson(treeGridData,Map.class);
		List<HashMap> insertedList = (List<HashMap>) map.get("inserted"); 
		List<HashMap> updatedList = (List<HashMap>) map.get("updated"); 
		List<HashMap> deletedList = (List<HashMap>) map.get("deleted"); 
		
		List<EipServiceParameter> updList = new ArrayList<EipServiceParameter>();
		List<EipServiceParameter> delList = new ArrayList<EipServiceParameter>();
		
		//添加
		Map<String,Long> copyIdsMap = new HashMap<String,Long>();
		insertData(changeDataType(insertedList),copyIdsMap);
		
		System.out.println();
		//更新
		for(Tree t : changeDataType(updatedList)){
			Long id = Long.parseLong(t.getIdStr());
			EipServiceParameter p = eipServiceParmService.getById(id);
			p.setParentParameterId(Long.parseLong(t.getPidStr()));
			p.setParameterNameCh(t.getAttribute1());
			p.setParameterNameEn(t.getAttribute2());
			p.setDataType(t.getAttribute3());
			Long dataTypeLen = StringUtils.isBlank(t.getAttribute4()) || t.getAttribute4().equals("null") ? 0 : Long.parseLong(t.getAttribute4());
			p.setDataTypeLength(dataTypeLen);
			p.setBelongFlag(t.getAttribute5());
			p.setConstraint(t.getAttribute6());
			p.setParameterType(t.getAttribute7());
			p.setRemark(t.getAttribute8());
			p.setServiceId(Long.parseLong(t.getAttribute9()));
			p.setTreeIndex(t.getTreeIndex());
			updList.add(p);
		}	
		eipServiceParmService.batchUpdate(updList);
		//删除
		for(Tree t : changeDataType(deletedList)){
			Long id = Long.parseLong(t.getIdStr());
			EipServiceParameter p = eipServiceParmService.getById(id);
			delList.add(p);
		}
		eipServiceParmService.batchDelete(delList);
		
		return null;
	}
	

	//入口方法
	@RequestMapping(value = "/json/getTreeGridData.json")
	@ResponseBody
	public Map<String, Object> getTreeGridData() {
	
		List<Tree> lt = new ArrayList<Tree>();
		String paramHql = " from EipServiceParameter pt where 1 = 1 and pt.serviceId = 492 order by pt.treeIndex desc";
		List<EipServiceParameter> paramList = eipServiceParmService.findByHql(paramHql);
		buildTreeData(paramList,lt);
		//展示树
		List<Tree> topTree = buildTree(lt);
		Map<String,Object> map = new HashMap<String,Object>();
		map.put("total", topTree.size());
		map.put("rows", topTree);
		
		return map;
	}
	
	
	//转换树数据
	private void buildTreeData(List<EipServiceParameter> paramList, List<Tree> lt) {
		long i = 0;
		if(paramList.get(0).getTreeIndex() == null){ //首次进入初始化更新全部TreeIndex
			for(EipServiceParameter p : paramList){
				p.setTreeIndex(i);
				i++;
			}
			eipServiceParmService.batchUpdate(paramList); 
		}
		
		
		for(EipServiceParameter p : paramList){
			Tree t = new Tree();
			t.setId(p.getId());
			t.setPid(p.getParentParameterId());
			t.setAttribute1(p.getParameterNameCh());
			t.setAttribute2(p.getParameterNameEn());
			t.setAttribute3(p.getDataType());
			t.setAttribute4(String.valueOf(p.getDataTypeLength()));
			t.setAttribute5(p.getBelongFlag());
			t.setAttribute6(p.getConstraint());
			t.setAttribute7(p.getParameterType());
			t.setAttribute8(p.getRemark());
			t.setAttribute9(String.valueOf(p.getServiceId()));
			t.setTreeIndex(p.getTreeIndex());
			lt.add(t);
		}
	}

	//构建树根
	public List<Tree> buildTree(List<Tree> data){
		List<Tree> topTree = new ArrayList<Tree>();
		for(int i = data.size() - 1 ; i >= 0 ;i--){
			Tree t = data.get(i);
			
			Long pid = t.getPid();
			if(pid == -1){
				topTree.add(t);
				data.remove(t);
			}
		}
		
		for(Tree top : topTree){
			buildBranchTree(top, data);
		}
		
		return topTree;
	}
	
	//构建树的子节点
	public void buildBranchTree(Tree parent , List<Tree> data){
		for(int i = data.size() - 1 ; i >= 0 ;i--){  //倒叙,否则remove后List会有问题
			Tree t = data.get(i);
			if(parent.getId() - 544  == 0 && t.getId() - 545 == 0){
				System.out.println();
			}
			if(parent.getId() - t.getPid() == 0){
				if(null == parent.getChildren())
					parent.setChildren(new ArrayList<Tree>());
				
				parent.getChildren().add(t);
				data.remove(t);
			}
		}
		
		if(data.size() == 0) return;
		if(null != parent.getChildren()){
			for(Tree branch : parent.getChildren()){
				buildBranchTree(branch, data);
			}
		}
		
	}	
	
	
	
}

 JSP:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
		<title>表格查询</title>
		<%@include file="/taglibs.jsp"%>
		<script type="text/javascript" src="treegrid_data.json"></script>
		<style>
			.tree-collapsed {
			    margin-left: 12px;
			}
			
			.tree-collapsed-hover {
			    background: url("js/jquery-easyui/themes/default/images/tree_arrows.gif") no-repeat scroll 0 0 transparent;
			}
			
			.tree-expanded {
			    margin-left: 12px;
			}
			.tree-expanded-hover {
			    background: url("js/jquery-easyui/themes/default/images/tree_arrows.gif") no-repeat scroll -18px 0 transparent;
			}
			
			.tree-folder-open {
			    background: none;
			}
			.tree-folder {
			    background: none;
			    width: 4px;
			}
		</style>
		
		<script type="text/javascript">
		
		var lastIndex;  //结束编辑的上一行用到
		var codeIndex = 1000;  //临时Id起始值
		
		var insertRows = [];
		var updateRows = [];
		var deleteRows = [];
		
		//编辑时选项下拉框数据
		var belongFlag = [
		      {type:'Y',typeName:'是'},
		      {type:'N',typeName:'否'}
		  ];
		  
		var dataType = [
			{type:'VARCHAR2'},
			{type:'TIMESTAMP'},
			{type:'NVARCHAR2'},
			{type:'NUMBER'},
			{type:'LONG'},
			{type:'BLOB'},
			{type:'CLOB'},
			{type:'DATE'}
		]; 
		
	(function($) {  
        $.extend($, {  
            //获取下标,删除时使用
            getArrayIndex :  function (array,value) {
				var index = -1;
				var length = array.length;
				for (var i = 0; i < length; i++) {
					if (array[i].id == value.id) {
						index = i;
						break;
					}
				}
				return index;
			} ,
			removeValue : function (array,value){
				var index = $.getArrayIndex(array,value);
				if(index < 0) return array;
				array.splice(index,1);
				return array;
			}
        });  
    })(jQuery); 
		
	$(function() {	
		$('#test').treegrid({   
		    url:"json/getTreeGridData.json", 
		    idField:'id',
            treeField:'id',
            animate: true,  
            checkbox:true,
            singleSelect:true,		
            checkOnSelect:true,  
            selectOnCheck:true,  
            toolbar: '#toolbar',
           /* frozenColumns: [[{
	            title: '参数中文名',
	            field: 'attribute1',
	            width: 200,
	            align:'left',
	            editor:'text'
	        }]],*/
		    columns:[[    
		        {field:'id',title:'id',width:300},   
		        {field:'pid',title:'pid',width:100,align:'right'},  
		        {field:'treeIndex',title:'行位置标记',hidden:false},  
		        {field:'attribute1',title:'参数中文名',width:200,align:'left',editor:'text'},   
		        {field:'attribute2',title:'参数英文名',width:200,align:'right',editor:'text'},   
		        {field:'attribute3',title:'数据类型',width:200,align:'right',
		        	formatter:function(value){  
	                    for(var i=0; i<dataType.length; i++){  
	                        if (dataType[i].type == value) return dataType[i].type;  
	                    }  
	                    return value;  
	                },  
	                editor:{  
	                    type:'combobox',  
	                    options:{  
	                        valueField:'type',  
	                        textField:'type',  
	                        data:dataType,  
	                        required:true
	                    }  
	                } 
		        },   
		        {field:'attribute4',title:'数据长度',width:200,align:'right',editor:'text'},   
		        {field:'attribute5',title:'是否必填',width:200,align:'right',
		        	formatter:function(value){  
	                    for(var i=0; i<belongFlag.length; i++){  
	                        if (belongFlag[i].type == value) return belongFlag[i].typeName;  
	                    }  
	                    return value;  
	                },  
	                editor:{  
	                    type:'combobox',  
	                    options:{  
	                        valueField:'type',  
	                        textField:'typeName',  
	                        data:belongFlag,  
	                        required:true 
	                    }  
	                }  
		        
		        },   
		        {field:'attribute6',title:'约束',width:200,align:'right',editor:'text'},  
		        {field:'attribute7',title:'参数类型',width:200,align:'right',editor:'text',hidden:true},  
		        {field:'attribute8',title:'备注',width:200,align:'right',editor:'text'},  
		        {field:'attribute9',title:'服务Id',width:200,align:'right',editor:'text',hidden:true}
		    ]],
		    onLoadSuccess:function(data){
            	//alert(data);
            	//drag();
        	},
		    onLoadError:function(data){
            	alert("1:"+data);
        	},
        	onClickRow: function(row) { //运用单击事件实现一行的编辑结束,在该事件触发前会先执行onAfterEdit事件
	            var rowIndex = row.id;
	            if (lastIndex != rowIndex) {
	                $('#test').treegrid('endEdit', lastIndex);
	            }
	        },
	        onDblClickRow: function(row) { //运用双击事件实现对一行的编辑
	            var rowIndex = row.id;
	            if (lastIndex != rowIndex) {
	                $('#test').treegrid('endEdit', lastIndex);
	                $('#test').treegrid('beginEdit', rowIndex);
	                lastIndex = rowIndex;
	            }else{
	            	$('#test').treegrid('beginEdit', lastIndex);
	            }
	        },
	        onBeforeEdit: function(row) {
	           // beforEditRow(row); //这里是功能实现的主要步骤和代码
	        },
	        onAfterEdit: function(row, changes) {
	        	if(!checkExist(updateRows,row)){
		        	updateRows[updateRows.length] = row;
	        	}
	            var rowId = row.id;
	            $.ajax({
	                url: "",
	                data: row,
	                success: function(text) {
	                    //$.messager.alert('提示信息', text, 'info');
	                }
	            });
	        }
		});  
		setTimeout(collapseAll,1000);
		setTimeout(toolbar,1000);
	});
	
	//将工具条从默认位置移到下方
	function toolbar(){
		var bar = $("#toolbar").html();
		var toolbarTitle = "<div id='toolbar' class='datagrid-toolbar'>";
		var toolbar = toolbarTitle + bar + "</div>";
		$(".datagrid-view").prev().remove();
		$(".datagrid-view").parent().append(toolbar);
	}
	
	//拖动drag和drop都是datagrid的头的datagrid-cell
    function drag() {
        $('.datagrid-row').draggable({
            revert: true,
            proxy: 'clone'
        }).droppable({
            accept: '.datagrid-row',
            onDrop: function (e, source) {
                //取得拖动源的html值
                var src = $(e.currentTarget.innerHTML).html();
                //取得拖动目标的html值
                var sou = $(source.innerHTML).html();
                var tempcolsrc;//拖动后源和目标列交换
                var tempcolsou;
                var tempcols=[];
                for (var i = 0; i < cols.length; i++) {
                    if (cols[i].title == sou) {
                        tempcolsrc = cols[i];//循环读一遍列把源和目标列都记下来
                    }
                    else if (cols[i].title == src) {
                        tempcolsou = cols[i];
                    }
                }
                for (var i = 0; i < cols.length; i++) {
                    //再循环一遍,把源和目标的列对换
                    var col = {
                        field: cols[i].field,
                        title: cols[i].title,
                        align: cols[i].align,
                        width: cols[i].width
                    };
                    if (cols[i].title == sou) {
                        col = tempcolsou;
                    }
                    else if (cols[i].title == src) {
                        col = tempcolsrc;
                    }
                     tempcols.push(col);  
                }
                 cols = tempcols;
                 //1秒后执行重绑定datagrid操作。可能是revert需要时间,这边如果没有做延时就直接重绑 就会出错。
                 //我目前的水平就想到这个笨办法,各位如果有好的想法建议可以提出来讨论下。
                timeid = setTimeout("init()", 1000);
            }
        });
    }
		
	
	function beforEditRow(row){
	     
    }
	
	
	
	function checkExist(array,node){
		var id = node.id;
		var flag = false;
		for(var i = 0;i<array.length; i++){
			var row = array[i];
			if(row.id == id){
				flag = true;
				break; //中断循环
			}
		}
		return flag;
	}
	/*
	function checkInsertExist(array,node){
		return checkExist(insertRows,node);
	}
	function checkUpdateExist(node){
		return checkExist(updateRows,node);
	}*/
	
	function saveChanges(){
		if (lastIndex != undefined) {
			$('#test').treegrid('endEdit', lastIndex);
		}
	
		var s = $('#test').treegrid('getChanges');
       	/*var insertRows = $('#test').datagrid('getChanges','inserted');
		var updateRows = $('#test').datagrid('getChanges','updated');
		var deleteRows = $('#test').datagrid('getChanges','deleted');
		*/
		//updateRows = $('#test').treegrid('getChanges','updated');
		for(var i = updateRows.length - 1 ;i>=0 ;i--){
			var nod = updateRows[i];
			if(checkExist(insertRows,nod)){ //该项是新增的,删除更新组数据和新增组中老数据,将新数据添加到新增组中
				//$.removeValue(insertRows,nod); //删除添加组中老数据,替换新数据
				$.removeValue(updateRows,nod);  //新增组中会自动获取到最新数据,因此不用删除老数据即可。
				//insertRows[insertRows.length] = nod;
			}
		}

		
		var changesRows = {
  				inserted : [],
  				updated : [],
  				deleted : [],
   		};
		if (insertRows.length>0) {
			for (var i=0;i<insertRows.length;i++) {
				changesRows.inserted.push(insertRows[i]);
			}
		}

		if (updateRows.length>0) {
			for (var k=0;k<updateRows.length;k++) {
				changesRows.updated.push(updateRows[k]);
			}
		}
		
		if (deleteRows.length>0) {
			for (var j=0;j<deleteRows.length;j++) {
				changesRows.deleted.push(deleteRows[j]);
			}
		}

		//alert(JSON.stringify(changesRows));

				// 保存成功后,可以刷新页面,也可以:
		//$('#test').treegrid('acceptChanges');
		var json = JSON.stringify(changesRows);
		$.post('json/saveTreeGridData.json', {"treeGridData": json}, function(data){
			/*if(data == 'success'){
				alert(1);
			}else{
				alert(2);
			}*/
			reload();
		});
	}
	
	
	function reload(){
		//var node = $('#test').treegrid('getSelected');
		//if (node){
		//	$('#test').treegrid('reload', node.id);
		//} else {
			$('#test').treegrid('reload');
		//}
		insertRows = [];
		updateRows = [];
		deleteRows = [];
		setTimeout(collapseAll,1000);
	}
	function getChildren(){
		var node = $('#test').treegrid('getSelected');
		if (node){
			var nodes = $('#test').treegrid('getChildren', node.id);
		} else {
			var nodes = $('#test').treegrid('getChildren');
		}
		var s = '';
		for(var i=0; i<nodes.length; i++){
			s += nodes[i].id + ',';
		}
		alert(s);
	}
	function getSelected(){
		var node = $('#test').treegrid('getSelected');
		if (node){
			alert(node.id);
		}
		return false;
	}
	function collapse(){
		var node = $('#test').treegrid('getSelected');
		if (node){
			$('#test').treegrid('collapse', node.id);
		}
	}
	function expand(){
		var node = $('#test').treegrid('getSelected');
		if (node){
			$('#test').treegrid('expand', node.id);
		}
	}
	function collapseAll(){
		$('#test').treegrid('collapseAll');
	}
	function expandAll(){
		$('#test').treegrid('expandAll');
	}
	
	
	function commonDataCopy(pid){
		codeIndex++;   
		var copyId = 'copy'+codeIndex;
		var node = $('#test').treegrid('getSelected');
		var data = [{
			id: copyId,
			pid: pid,
			treeIndex:new Date().getTime(),
			attribute1: node.attribute1,
			attribute2: node.attribute2,
			attribute3: node.attribute3,
			attribute4: node.attribute4,
			attribute5: node.attribute5,
			attribute6: node.attribute6,
			attribute7: node.attribute7,
			attribute8: node.attribute8,
			attribute9: node.attribute9
		}];
		$('#test').treegrid('append', {
			parent: (node?pid:null),
			data: data
		});
		
		var node = $('#test').treegrid('find', copyId);
		insertRows[insertRows.length] = node;
	}
	
	function commonBlankCopy(pid){
		codeIndex++;   
		var node = $('#test').treegrid('getSelected');
		var copyId = 'copy'+codeIndex;
		var data = [{
			id: copyId,
			pid: pid,
			treeIndex:new Date().getTime(),
			attribute1: '',
			attribute2: '',
			attribute3: '',
			attribute4: '',
			attribute5: '',
			attribute6: '',
			attribute7: '',
			attribute8: '',
			attribute9: ''
		}];
		$('#test').treegrid('append', {
			parent: pid,
			data: data
		});
		
		var node = $('#test').treegrid('find', copyId);
		insertRows[insertRows.length] = node;
	}
		
	//添加平行节点		        
	function copy(){	   
		var node = $('#test').treegrid('getSelected');
		if(!node) alert("Please one row !");
		commonDataCopy(node.pid);
		return false;
	}
	
	//添加子节点
	function appendCopy(){		
		var node = $('#test').treegrid('getSelected');
		if(!node) alert("Please one row !");
		commonDataCopy(node.id);
		return false;
	}
	
	function appendBlank(){
		var node = $('#test').treegrid('getSelected');
		commonBlankCopy(node ? node.id : -1);
		return false;
	}
	function blank(){
		var node = $('#test').treegrid('getSelected');
		commonBlankCopy(node ? node.pid : -1);
		return false;
	}
	function remove(){
		$.messager.confirm('确认','是否真的删除?',function(r){
               if (r){
                   var node = $('#test').treegrid('getSelected');
					if (node){
						deleteNode(node);						
						$('#test').treegrid('remove', node.id);
					}
               }
           });
	}
	
	function removeMulSelected(){
		$.messager.confirm('确认','是否真的删除?',function(r){
               if (r){
                   var nodes = $('#test').treegrid('getSelections');
                   for(var i = 0;i<nodes.length;i++){
                   	  var node = nodes[i];
                   	  if (node){
						  deleteNode(node);						
						  $('#test').treegrid('remove', node.id);
					  }
                   }
					
               }
           });
	}
	
	
	function commonDelete(node){
		if(checkExist(insertRows,node)){
			$.removeValue(insertRows,node);
		}else{//添加组中没有,说明不是新增的,需要加入删除组
			deleteRows[deleteRows.length] = node;
		}
		if(checkExist(updateRows,node)){
			$.removeValue(updateRows,node);
		}
	}
	
	function deleteNode(node){
		var children = $('#test').treegrid('getChildren', node.id);
		//删除添加组和更新组中的子数据
		if(children != null && children.length > 0){
			for(var i = 0 ; i < children.length ; i++){
				var child = children[i];
				commonDelete(child);
			}
		}
		//删除添加组和更新组中的当前节点数据
		commonDelete(node);
	}
	
	
	function toggle(){
		var node = $('#test').treegrid('getSelected');
		if (node){
			$('#test').treegrid('toggle', node.id);
		}
	}
	
	function moveUp(){
		var node = $('#test').treegrid('getSelected');
		var selectRow = $('#datagrid-row-r2-2-'+node.id);
		var pre = selectRow.prev();
		var next = selectRow.next();
		
		//处理新增行的移动
		//var i = node.id.indexOf("copy");
		var preLen = selectRow.parent().parent().prev().length; 
		var flag = typeof node.id == 'string'; 
		//只有新增的未移动的行才需要重新设置pre
		//pre.length == 0 判断是否是新增的未移动的行(新增的移动过的行和数字行一样)
		//preLen > 0 判断是否已移动到同级第一行
		if(flag && pre.length == 0 && preLen > 0){
			var tmpTable = selectRow.parent().parent().prev();
			var ran = new Date().getTime();
			tmpTable.attr("id","id"+ran);
			
			var _tr = $("#id"+ran+">tbody>tr");
			var tmpLast = _tr[_tr.length-1];
			var last = $(tmpLast);
			if(last.hasClass('treegrid-tr-tree')){
				pre = last.prev();
			}else{
				pre = last;
			}
			selectRow.parent().parent().remove();//删除新增行所在的table
			//pre = tmp.find("tr[class!='treegrid-tr-tree'] :last");
			//selectRow.parent().parent().remove(); //删掉新增行的Table
		}
		
		var preId;
		var preTreeIndex;
		if(pre.hasClass('treegrid-tr-tree')){  //前面节点含有子节点
			var child = pre;
			var treeprev = child.prev();
			preHtml = treeprev;
		}else{
			preHtml = pre;
		}
		
		//获取pre的Id
		preId = preHtml.find("td:eq(0)").text();
		selectRow.insertBefore(preHtml);
			
		if(next.hasClass('treegrid-tr-tree')){ //自己含有子节点
			var child = next;
			selectRow.after(child);
		}
		
		
		//交换treeIndex
		var selectTreeIndex = node.treeIndex;
		var prenode = $('#test').treegrid('find',preId);
		node.treeIndex = prenode.treeIndex;
		prenode.treeIndex = selectTreeIndex;
		$('#test').treegrid('refresh',node.id);
		$('#test').treegrid('refresh',preId);
						
		updateTreeIndex(node);
		updateTreeIndex(prenode);
		var i ;
	}
	
	
	function updateTreeIndex(node){
		if(checkExist(insertRows,node)){ 
			$.removeValue(insertRows,node); 
			$.removeValue(updateRows,node);  
			insertRows[insertRows.length] = node;
		}else{
			//将换了treeIndex的行加入更新组
			updateRows[updateRows.length] = node;
		}
	}
	
</script>
	</head>
	<body>
		<table id="test" class="easyui-treegrid" style="width: 1200px; height: 400px" data-options="rownumbers:true,pagination:false,fitColumns:true,autoRowHeight:false"></table>

		<div id="toolbar">     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-save" plain="true" onclick="saveChanges()">保存</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-reload" plain="true" onclick="reload()">重置</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-expand" plain="true" onclick="expandAll()">全部展开</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-collapse" plain="true" onclick="collapseAll()">全部收缩</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-appendBlank" plain="true" onclick="appendBlank()">添加子节点</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-appendCopy" plain="true" onclick="appendCopy()">复制子节点</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-blank" plain="true" onclick="blank()">添加节点</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-copy" plain="true" onclick="copy()">复制节点</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-remove" plain="true" onclick="remove()">删除节点</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-moveUp" plain="true" onclick="moveUp()">同级上移</a>     
		    <a href="javascript:void(0);" class="easyui-linkbutton" iconCls="icon-tree-moveDown" plain="true" onclick="javascript:alert('Save')">同级下移</a>     
		</div>  
	</body>
</html>

 

。。

 

 java 递归读取数据库生成tree的结构

 http://bbs.csdn.net/topics/320094100

 根据递归高效的生成树:

http://jsf.iteye.com/blog/124799

你可能感兴趣的:(tree)