本例是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
根据递归高效的生成树: