zoukankan      html  css  js  c++  java
  • 利用ajax,巧妙的sql语句组合,轻松做出不错的树型菜单

    我们的某个项目中,在设计报表时候,考虑到做报表的树型分类,同时考虑到分类下存在子分类和报表并存,使用原有项目中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.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="&nbsp;&nbsp;<img src=\"../resources/img/loading.gif\" border=\"0\" />&nbsp;加载中...";
    $(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'/>">&nbsp;
        <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'/>">&nbsp;</td>
    </tr>
    </table>
    </b:gBody>

    就这样完了........ 也许不能帮你什么忙,也许这方法你早用过.但是我还是发到blog上,因为我也要记录自己的知识,如果你反馈你有更好的解决方案,我会对比,进一步改造.嘿嘿.

    原帖地址:http://hi.baidu.com/518bc/item/c7e21a4baf806d0a6dc2f089

  • 相关阅读:
    迭代器模式-Iterator
    kubernetes之一 k8s基本概念
    多线程中的异常处理
    MySQL高可用集群方案
    RabbitMQ的集群模式
    多线程中如何取消任务
    公钥、私钥、摘要、数字签名、证书
    将Ubuntu系统迁移到SSD固态操作
    Java线程的状态和状态转换
    Ubuntu18.04系统和软件安装记录
  • 原文地址:https://www.cnblogs.com/Overbord/p/2630315.html
Copyright © 2011-2022 走看看