任何人只要在对的地方做对的事,就值得尊敬!
对于系统而言,管理员必须保证每一个用户只能做自己该做的事。所以任何一个项目,必然有一套权限管理策略。复杂的就很复杂了,我将一切从简。园子里有号称能将权限管理做的极致的,咱也没留意看过,谁知道呢。由于是实验型项目,我只是使用了单角色,具体业务大家可具体对待。
曾经我还是ASP.Net的初学者的时候,某一本从入门到精通类似的书上在介绍母板的时候,信口开河的预言:母板的出现将取代网页frameset的架构设计。当时我是深信不疑,把作者佩服的五体投地。但是,我一直怀疑母板(或者概念类似母板的一类)的作用,书上可能介绍说把若干个网页相同的部分提取为母板,这样直接引用即便于管理,又减少页面代码。问题就在这里,你需要在某一页面主动引用母板,母板就只能类似于#define,只能是在模板引擎在解析的时候将母板加以替换而已。这样,我们在访问引用同一母板的任何一个页面,母板都会被重新替换,重新解析和加载!当我们需要的众多页面的公用部分没必要甚至不可以重复加载的情况下,我们依然需要frameset/iframe。
下面,给出首页的frameset源码:
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/> <metahttp-equiv="X-UA-Compatible"content="IE=EmulateIE8"/> <title>蜜蜂的智慧</title> </head> <framesetstyle="border: 0"rows="92,*,24"frameborder="no"border="0"framespacing="0"> <framesrc="FrameWork_Top.action"name="topFrame"scrolling="No"noresize="noresize"id="topFrame"/> <framesrc="FrameWork_Middle.action"name="mainFrame"id="mainFrame"/> <framesrc="FrameWork_Bottom.action"name="bottomFrame"scrolling="No"noresize="noresize"id="bottomFrame"/> </frameset> <noframes> <body> </body> </noframes> </html>
以上,毫无疑问的吧。在mainFrame中,还有一个框架,代码如下:
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/> <title></title> <framesetrows="*"cols="200,4,*"border="0"framespacing="0"id="frame1"frameborder="no"> <framename="leftarea"id="leftarea"scrolling="auto"noresize="noresize"marginheight="0"src="FrameWork_Menu.action"frameborder="0"> <framename="middleframe"scrolling="no"noresize="noresize"src="FrameWork_MiddleLeft.action"frameborder="0"> <framesetrows="*"cols="*,4"frameborder="no"border="0"framespacing="0"id="frame2"> <framename="main"scrolling="auto"noresize="noresize"src="FrameWork_MainIndex.action"frameborder="0"id="mainindex"> <framename="rightframe"src="FrameWork_MiddleRight.action"frameborder="0"scrolling="no"noresize="noresize"> </frameset> </frameset> <noframes> </noframes> </html>
框架嵌套了,貌似有点点麻烦。现在找出来我们的关注点,leftarea是我们展现菜单的frame,mainindex是展现所有业务界面的地方。框架就是这样了,没有什么难度,也没有任何特别之处。现在信息技术高速发展,审美观点也是每天一个样,每天都会有更好看的框架和样式。但是,管理系统真的需要花哨吗?再怎么变真的能够摆脱查询列表吗?
还记得我们的约定吗?一个html页面一定会对应着一个同名的Action方法。下面给出需要用到的Action代码,记住不要引用layout:
public String Index() { returnSUCCESS; } public String Top() { returnSUCCESS; } public String Middle() { returnSUCCESS; } public String Bottom() { returnSUCCESS; } public String Menu() { try { String roleId = GlobalInfo.getValue("roleId"); if (roleId.equals("supper")) { setMenu(DBHelper .ExecuteResult("select * from sysmenu order by sort asc")); } else { setMenu(DBHelper .ExecuteResult("select * from sysmenu where id in (select menuid from roleMenu where roleId='" + roleId + "') order by sort asc")); } } catch (HibernateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } returnSUCCESS; } public String MiddleLeft() { returnSUCCESS; } public String MainIndex() { returnSUCCESS; } public String MiddleRight() { returnSUCCESS; }
框架基本上就是这个样子了,下面我们继续关注一下菜单的问题:
我们要获得当前登录用户的菜单,这当然必须在设计的时候考虑到,我这里使用roleMenu表,比较简单,可根据实际情况进行扩充,数据库导出文件可下载(最后给出连接)。
private Result menu; public Result getMenu() { returnmenu; } publicvoid setMenu(Result menu) { this.menu = menu; } public String Menu() { try { String roleId = GlobalInfo.getValue("roleId"); if (roleId.equals("supper")) { setMenu(DBHelper .ExecuteResult("select * from sysmenu order by sort asc")); } else { setMenu(DBHelper .ExecuteResult("select * from sysmenu where id in (select menuid from roleMenu where roleId='" + roleId + "') order by sort asc")); } } catch (HibernateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } returnSUCCESS; }
经过上一集的介绍,我相信大家对Result数据集都已经很熟悉了,这里就不多费手指了。我们使用先前在用户登录时保存的用户角色来验证用户,假如是特权用户就直接赋予全部菜单,如果不是就看运气了,有什么就是什么了!
setMenu(DBHelper
.ExecuteResult("select * from sysmenu where id in (select menuid from roleMenu where roleId='"
+ roleId + "') order by sort asc"));
大家肯定都知道自己的项目在设计之初的菜单层级是怎么设置的,我这里使用最简单的吧,只有两级菜单。原则上菜单是可以无限级别的,可惜我们的项目一直都没用的上这么多的菜单。虽然菜单可以开放给用户自行维护,用户甚至可以把现有的系统纳入进来,哎,谁让我们的用户都比较懒呢,你要是不给他们弄好了,他们才不会自己动手呢!除非遇上了检查!
针对我们的两级菜单,给出菜单页面的源代码:
<!DOCTYPEhtmlPUBLIC"-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <htmlxmlns="http://www.w3.org/1999/xhtml"> <head> <metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/> <metahttp-equiv="X-UA-Compatible"content="IE=EmulateIE8"/> <title>蜜蜂的智慧</title> <linkrel="stylesheet"type="text/css"href="../Theme/1/base/css/menu.css"/> <scripttype="text/javascript"src="../Content/javascript/jquery-1.6.2.min.js"></script> <scripttype="text/javascript"src="../Content/javascript/Framework/index.js"></script> </head> <bodystyle="background: url(../Theme/1/base/images/menu_bg.jpg) repeat-y;"> <divid="menu"style="height:100%;"> <divclass="content"> <divclass="menu_info"> <ulid="first_menu"> #foreach($item in $menu.rows) #if("$item.level"=="1") <liclass="L1"><ahref="javascript:c('$item.Id');"id="$item.Id"><span> <imgsrc="../Content/images/menu/$item.pic"align="absMiddle"/>$item.name</span></a></li> <ulid="${item.id}d"style="display: none;"class="U1"> #foreach($item2 in $menu.rows) #if("$item2.parent"=="$item.id") <liclass="L22"><ahref="javascript:;"id="$item2.Id"onclick="OpenUrl('$item2.id','/Wisdom/$item2.url');"> <span>$item2.name</span></a></li> #end #end </ul> #end #end </ul> </div> </div> </div> <divclass="key"onclick="initHidemenu(bottom);"> </div> <scriptlanguage="JavaScript"> function OpenUrl(id, url) { $("#mainindex", window.parent.document).attr("src", url); $(".L22 > a").removeClass("active"); $(id).addClass("active"); }; $("#first_menu > li > a > span").hover( function () { $(this).stop().animate({ paddingLeft: "15px" }, 200); }, function () { $(this).stop().animate({ paddingLeft: "5px" }); } ); </script> </body> </html>
需要注意的地方就是,菜单的双层循环,第一层循环是获得用户菜单的一级菜单,第二层循环是获得当前一级菜单的二级子菜单。
首页整体就这样了。很多人可能不是很熟悉velocity语法,百度吧,我也会整理一下我们经常用到的velocity语句。这一定是最简单的。
数据库文件下载:http://files.cnblogs.com/Bytime/120731233430.zip
下集预告:velocity常用基本语法。