注意: 前提需知: 本项目所包含技术: 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.onload=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上,因为我也要记录自己的知识,如果你反馈你有更好的解决方案,我会对比,进一步改造.嘿嘿.
原帖地址:http://hi.baidu.com/518bc/item/c7e21a4baf806d0a6dc2f089