我们的某个项目中,在设计报表时候,考虑到做报表的树型分类,同时考虑到分类下存在子分类和报表并存,使用原有项目中jtree功能已经达不到这要求,因此,考虑蛮久,还是自己写一个吧.
注意: 前提需知: 本项目所包含技术: j2ee,structs2.0,spring,ibatis,(数据库是oracle,这和数据库没关系)
为保密起见,本例只贴出关键位置,不会暴露完全的设计流程,朋友如果你看到这里,请原谅.但是完全不会影响到阅读理解.先发几张效果图,有兴趣就继续往下看
1.-----------------------------------------------
2.-----------------------------------------------3.----------------------------------------------(看到这里你就知道了,分类中有可能存在子分类,而同时又存在报表)好,废话少说,开始讲解步骤吧,<1> 首先,你要设计好数据库的结构,结构必须是合理的 ,下面发几张图,可以着图去理解,我也不会多说了,蝙蝠有限.
报表分类表(或者理解为"树"):大体说一下: ID:节点ID(唯一) , PARENT_ID:父级ID,NAME:节点文字,这三个必备,其他是无关紧要的. 报表表(关联到报表分类表,注意外键) : 关联两个表进行查询: 下面是ibatis的SQL语句(如果没有ibatis知识的朋友,请自行学习了再看,不然怎么也说不清楚):注意:唯一的参数 :=#parentId# <!-- 查询单个报表分类的子分类 --> <select id="loadSortTypeByParentId" parameterClass="java.lang.String" resultClass="java.util.HashMap"> select "text", "parentId", "nodeId", "count", case("parentId") when '-' then 'minus_m.gif' else 'plus_m.gif' end as "report_Icon", case("parentId") when '-' then 'hfile.gif' else 'fold.gif' end as "report_Img" from ( select a.NAME as "text", a.PARENT_ID AS "parentId", a.ID AS "nodeId", nvl(b.nodeCount, 0) AS "count" from RPT_CODE_REPORT_TYPE a Left Outer Join ( select PARENT_ID, count(ID) nodeCount from RPT_CODE_REPORT_TYPE where IS_VALID = 1 group by PARENT_ID) b On a.ID = b.PARENT_ID where a.PARENT_ID =#parentId# union select a.report_name as "text", '-' as "parentId", TO_CHAR(a.id) as "nodeId", 0 AS "count" from RPT_INFO_REPORT a Inner join RPT_CODE_REPORT_TYPE b On b.ID = a.REPORT_TYPE_CODE where b.ID =#parentId# ) order by "nodeId" desc</select>相关的JAVA部分就省略了,大体意思我可以说一下.我这里是在struct2.0的action (ReportInfoAction) 里定义一个方法 : public String reportListLoad()这个方法大体是这样:public String reportListLoad(){ //开始加载ibatis //************************** /*这是struts2.0的新特性,通过相关配置,它会自动找到相关JSP页面*/ return "loadNodeTree"; }因为java的技术太多,你可能是用一般的JSP编程,在这里你可以定义一个自己的javaBean来操作你的ibatis;你可能是用传统的servlet,同样你也可以在你所定义的servlet里加再你的ibatis(当然你也可以更完美的分离代码) ;或者你会使用的是webwork,总之,道理是一样的.如果你对这些技术半懂不懂,那以上等于我白说,如果你是JAVA开发者,我说了这些估计你认为是废话.嘿嘿.看看JSP页面吧:
首先一个ViewTree.jsp :这个是一个比较重要的JS定义函数(中间用到了ajax发送方式):<script type="text/javascript" src="/prototype/prototype.js"></script><script language="JavaScript">/** 创建树型类* 编写:莫小明* 时间:2008年7月9号* 实现:树型目录* 解决了:* 同以节点下即存在子节点,又存在报表*/var BuilderTree=function(){ //初始创建this.innitBuilder=function(){ //在加载完毕时创建 window.οnlοad=function(){ var id="divTrees_009.001"; var nodeTree=document.createElement("div"); nodeTree.setAttribute("id",id); nodeTree.style.display="none"; $("tree").appendChild(nodeTree); b.builderTree(id,id,id.replace("divTrees_",""));}}/* 创建子节点 * 参数 openCloseObj :关闭打开子节点 * 参数 loadObj:加载加载条的对象 * 参数 nodeId:子节点的编号 */this.builderTree=function(openCloseObj,loadObj,nodeId){ //判断是否是报表if($("type_"+nodeId)){ if($("type_"+nodeId).innerHTML.indexOf("hfile.gif")>0) { //alert("是报表,报表ID="+nodeId); //在右边打开报表 var url="ReportInfo.action?view=tree&id="+nodeId; //具体打开位置:从最上边查找,top下的mainFrame //mainFrame下的v_mainFrame top.mainFrame.v_mainFrame.location.replace(url); return; }}var url = 'ReportInfo!LoadNodeTrees.action';var id = nodeId;if(id=="") return ;var params = 'parentId=' + id;//如果当前的打开的if(Element.visible(openCloseObj)){ if($("icon_"+id)) { $("icon_"+id).innerHTML=$("icon_"+id).innerHTML.replace("minus_m.gif","plus_m.gif"); $("type_"+id).innerHTML=$("type_"+id).innerHTML.replace("folderopen.gif","fold.gif"); } Element.hide(openCloseObj); return ;}else{ Element.show(openCloseObj);} this.__loading(loadObj); //创建Aajx对象 var __ajax = new Ajax.Request(url,{ method: 'get', parameters: params, onComplete: function __callback(request) { /*执行具体的回调函数*/ var result=request.responseText; //判断是否有结果 if(result.length<5) { //确认没有子节点以及相关报表,关闭之 Element.hide(openCloseObj); $("icon_"+id).innerHTML=$("icon_"+id).innerHTML.replace("plus_m.gif","minus_m.gif"); return ; } else { if($("icon_"+id)) { //关闭图标设置为展开图标 $("icon_"+id).innerHTML=$("icon_"+id).innerHTML.replace("plus_m.gif","minus_m.gif"); $("type_"+id).innerHTML=$("type_"+id).innerHTML.replace("fold.gif","folderopen.gif"); // } } //存放结果 $("divTrees_"+id).innerHTML=result; }}); }//显示加载条this.__loading=function(obj){ //alert(obj);var img=" <img src=\"../resources/img/loading.gif\" border=\"0\" /> 加载中...";$(obj).style.display="";$(obj).innerHTML=img; } }var b=new BuilderTree();b.innitBuilder();</script> </head><body><div align="center"><img src="img/treeTile.gif" border="0" /></div><br/><div id="tree"></div>这里是ajax发送请求后在structs2.0的action里控制返回的JSP页面:该页面没什么特殊,除了自己定义的标签外,和其他的标签没什么两样,如果你觉得不舒服,完全可以改造成自己的普通JSP标签.(注意里面所调用的JS函数) <%@ page contentType="text/html;charset=utf-8" language="java"%><%@ taglib prefix="b" uri="/bonc-tags"%><b:gBody value="sortList"><table width="100%" border="0" cellspacing="0" cellpadding="0"><tr> <td width="2%" id="icon_<b:gd value='nodeId'/>" style="cursor:hand" onClick=b.builderTree("p_<b:gd value='nodeId'/>","divTrees_<b:gd value='nodeId'/>","<b:gd value='nodeId'/>") ><img src="../resources/img/alai_tree/<b:gd value='report_Icon'/>"></td> <td width="98%" id="type_<b:gd value='nodeId'/>"><img src="../resources/img/alai_tree/<b:gd value='report_Img'/>"> <a onClick=b.builderTree("p_<b:gd value='nodeId'/>","divTrees_<b:gd value='nodeId'/>","<b:gd value='nodeId'/>") href="javascript:void(0)" ><b:gd value="text"/></a> </td></tr><tr id="p_<b:gd value='nodeId'/>" style="display:none"> <td></td> <td id="divTrees_<b:gd value='nodeId'/>"> </td></tr></table></b:gBody>就这样完了........ 也许不能帮你什么忙,也许这方法你早用过.但是我还是发到blog上,因为我也要记录自己的知识,如果你反馈你有更好的解决方案,我会对比,进一步改造.嘿嘿.原帖地址: