jquery-easyui实现页面布局和增删改查操作(SSH2框架支持)
?前几天心血来潮用jquery-easyui+spring、struts2、hibernate实现了一个系统的一小部分功能,下面给大家分享一下。
?
首先看运行效果:【图一:登录页】
?
?
?
【图二:页面布局】
?
?
【图三:用户编辑层】
?
?
?
【图四:确认弹出框】
?
?
?
easyui插件简介在这就不赘述了,大家可以在iteye上找到很多该插件的相关消息。
如果页面需要使用easyui插件,需要引进一下js和css(使用的时候需要注意easyui版本依赖的jquery.js版本要对应):
<script type="text/javascript" src="<%=root%>/Web/common/js/jquery-1.4.4.min.js"></script>
<link rel="stylesheet" type="text/css" href="<%=root%>/Web/common/js/easyui/themes/default/easyui.css"><link rel="stylesheet" type="text/css" href="<%=root%>/Web/common/js/easyui/themes/icon.css"><script type="text/javascript" src="<%=root%>/Web/common/js/easyui/js/jquery.easyui.min.js"></script><script type="text/javascript" src="<%=root%>/Web/common/js/easyui/js/easyui-lang-zh_CN.js"></script>
?
布局为了让一个主页实现上下左右中的布局方式显示,这里就需要用到easyui一个叫layout的东西,通常有多种方式可以实现布局。
①使用js创建<div id="cc" style="width:600px;height:400px;"> <div region="north" title="North Title" split="true" style="height:100px;"></div> <div region="south" title="South Title" split="true" style="height:100px;"></div> <div region="east" iconCls="icon-reload" title="East" split="true" style="width:100px;"></div> <div region="west" split="true" title="West" style="width:100px;"></div> <div region="center" title="center title" style="padding:5px;background:#eee;"></div></div>
然后在js中指定id为cc的div为layout:
?
$('#cc').layout(options);
?简单介绍几个layout属性:
?
?
属性名数据类型功能默认值titlestring指定布局的标题名称无regionstring指定布局位置,分:东、西、南、北、中?borderboolean是否显示边界truesplitboolean是否显示分界线从而用户可以拖动改变其大小falseiconClsstring指定布局的图标样式无hrefstring指定该布局远程调用的html路径无?
②让整个body使用easyui的cssclass:name="code"><body style="height:100px;padding:10px;" href="<%=root%>/Web/common/page/top.html"></div> <!-- 正左边panel --> <div region="west" title="菜单栏" split="true" style="width:280px;padding1:1px;overflow:hidden;"> <div fit="true" border="false"> <!-- selected --><div title="用户权限管理" selected="true"><ul><li><a href="javascript:addTab('tabId_loginInfo','用户管理','<%=root%>/ospm/loginInfo/goLoginInfoMain.jhtml');">用户管理</a></li><li><a href="javascript:addTab('tabId_privilege','权限管理','<%=root%>/ospm/loginInfo/goPrivilegeMain.jhtml');">权限管理</a></li></ul></div></div> </div> <!-- 正中间panel --> <div region="center" title="功能区" > <div id="centerTab" fit="true" border="false"><div title="欢迎页" style="padding:20px;overflow:hidden;"> <div style="margin-top:20px;"><h3>你好,欢迎来到权限管理系统</h3></div></div></div> </div> <!-- 正下方panel --> <div region="south" style="height:50px;" align="center"> <label> 作者:白糖<br/> 时间:2011-5-17 </label> </div></body>
?运行效果如【图二:页面布局】
?
创建选项卡【图二:页面布局】上面标记了在菜单栏点击“用户管理”链接即可在功能区创建一个叫“用户管理”的选项卡并加载相应数据。注意:用户管理页面是另一个jsp,需要远程调用。
最初我使用tabs的href属性来远程调用用户管理jsp,发现页面会有js冲突,导致用户管理页面的添加、编辑等各种功能失效,我猜想可能是js冲突,因为布局页引用了easyui,而用户管理jsp也引用了同样的easyui。
后来看了下项目经理ext的布局代码,原来在点击链接的时候会创建一个tabs,只是tabs的内容是一个iframe分隔:
/** * 创建新选项卡 * @param tabId 选项卡id * @param title 选项卡标题 * @param url 选项卡远程调用路径 */function addTab(tabId,title,url){//如果当前id的tab不存在则创建一个tabif($("#"+tabId).html()==null){var name = 'iframe_'+tabId;$('#centerTab').tabs('add',{title: title, closable:true,cache : false,//注:使用iframe即可防止同一个页面出现js和css冲突的问题content : '<iframe name="'+name+'"id="'+tabId+'"src="'+url+'" width="100%" height="100%" frameborder="0" scrolling="auto" ></iframe>'});}}
?不过群里也有些大神提醒:如果大量使用iframe会使页面性能降低,所以使用iframe分隔tabs只适合小型项目使用。
?
datagrid表格easyui datagrid是争议最大的一个功能插件,很多人说它不开源,提供的api不全面,标题列内容可能不对齐,操作繁杂等等。其实个人觉得这个table的功能已经相当不错了,如果只需要做基本的显示则只需配很少的代码。
下面简单介绍下datagrid的使用:
①首先肯定需要有一个table标签,给它定义一个id,在js中通过id.datagrid方法即可创建表格
<!-- 表格 --><table id="loginInfoTable"title="用户信息一览" border="0"cellspacing="0"cellpadding="0"iconCls="icon-edit" width="98%" idField="loginId" pagination="true"remoteSort="false" singleSelect="false" showFooter="false"striped="true" url="<%=root%>/ospm/loginInfo/doLoginInfoSearch.jhtml"><thead><tr align="center"><th field="ck" width="20" checkbox="true" width="20"></th><th field="loginCode" width="200">用户名</th><th field="statuValue" width="100">状态</th><th field="opt" formatter='optFormater' width="150">操作</th></tr></thead></table>
?第二种方式如下:
columns:[[ {field:'itemid',title:'Item ID',rowspan:2,width:80,sortable:true}, {field:'productid',title:'Product ID',rowspan:2,width:80,sortable:true}, {title:'Item Details',colspan:4}],[ {field:'listprice',title:'List Price',width:80,align:'right',sortable:true}, {field:'unitcost',title:'Unit Cost',width:80,align:'right',sortable:true}, {field:'attr1',title:'Attribute',width:100}, {field:'status',title:'Status',width:60}]]
?③向后台请求数据
datagrid有一个属性叫url,在进入页面后,它会通过ajax方式向后台发送请求,后台封装相应数据(JSON格式)再返回给前台即可显示。注意:datagrid在回调函数中必须获得两项json数据:total表示查询出的总结过,rows表示显示在table中的数据集合。
/** * 封装Json数据 */long total = 0; // 符合查询的总条数List<LoginInfoTableDto> lstTable = null; // 查询结果total = (Long) mapLoginInfo.get(Constant4Ospm.TOTAL);if (mapLoginInfo.get(Constant4Ospm.SEARCH_RESULT) != null) {lstTable = (List<LoginInfoTableDto>) mapLoginInfo.get(Constant4Ospm.SEARCH_RESULT);} else {//注:如果从数据库查询不出数据,也必须封装一个空的json集合,不然页面就会报js错误lstTable = new ArrayList<LoginInfoTableDto>();}JSONObject datas = new JSONObject();// 设置总共有多少条记录datas.put(Constant4Ospm.TOTAL, total);// 设置当前页的数据datas.put(Constant4Ospm.PAGE_SIZE, lstTable);
?④后台数据与表格关联
后台过来的数据怎么与表格每一列对应呢?其实很简单:后台rows中包含了名叫LoginInfoTableDto的javabean-json集合,datagrid的field和idField对应LoginInfoTableDto中的一个属性(大体上是这样,当然field也可以不对应javabean的属性,你可以进行一些转换)。
⑤toolbar工具栏
【图二:页面布局】能够看到datagrid有“添加新用户”、“批量删除”等工具栏,这些工具栏的实现方式也很简单:
$('#loginInfoTable').datagrid({toolbar:[{//正上方工具栏text:'添加新用户',iconCls:'icon-add',handler:function(){//点击工具栏运行的js方法openDialog_add();}},'-',{text:'批量删除',iconCls:'icon-cancel',handler:function(){batch('delete');}...............
?
当然easyui datagrid还有很多其它的功能,网上有很多大神已经详细介绍过,这里就不赘述了。
?
dialog对话框的使用也很简单:你只需要定义一个带id的div,在div中填入你需要在对话框中显示的内容,然后调用一下方法即可变成easyui的dialog:
<div id="dd" title="My Dialog" style="width:400px;height:200px;"> Dialog Content.</div>
$('#dd').dialog(options);
?前面【图三:用户编辑层】就是一个dialog,大家看下代码:
jsp页面:
<!-- 编辑 --><div id="loginInfoEdit" icon="icon-save"style="padding: 5px; width: 500px; height: 300px;"><h5 id="loginInfoEdit_message" style="color: red;"></h5><div id="table_loginInfoEdit" onkeydown="if(event.keyCode==13){loginInfoEdit();}"><input type="hidden" id="loginInfoEdit_loginId"></input> <ul><li><label>用户名:</label><label id="loginInfoEdit_loginCode"></label></li><li><label>密码:</label><input type="password" id="loginInfoEdit_password" maxlength="20" required="true"></input></li><li><label>重复密码:</label><input type="password" id="loginInfoEdit_repassword" maxlength="20" required="true"></input></li><li><a href="#" icon="icon-ok" onclick="loginInfoEdit();">提交</a></li></ul></div></div>
?js代码:
//设置弹出框的属性function setDialog_edit(){$('#loginInfoEdit').dialog({title : '用户编辑',modal: true, //模式窗口:窗口背景不可操作collapsible : true, //可折叠,点击窗口右上角折叠图标将内容折叠起来resizable : true //可拖动边框大小});}//打开对话框function openDialog_edit(loginId,loginCode){loginInfoEditReset(loginId,loginCode);$('#loginInfoEdit').dialog('open');}//关闭对话框function closeDialog_edit(){$('#loginInfoEdit').dialog('close');}
?
?
messager消息框?【图四:确认弹出框】就是一个消息框,easyui它可以模仿html的alert()、confirm()等提示框,而且画面更美观。
图四批量禁用的代码如下:
//禁用操作$.messager.confirm('禁用提示', '你确定禁用下列用户吗?<br/>'+cods.join(','), function(r){if (r){var url = root+'/ospm/loginInfo/doLoginInfoInvalid.jhtml?loginId='+loginId;changeStatus(url);}});
?
?
?
很抱歉,只完成了用户管理一个模块的功能。
附件带项目源码,希望对大家有所帮助。(源码一包含项目源码和数据库,源码二包含项目jar包)
关键jar版本:hibernate3.3、spring2.6、struts2.1
数据库:mysql5.1
数据库连接池:bonecp 0.7
项目类型:eclipse - dynamic web project
?
????? 登录帐号:admin? 密码:admin
?
部署方式:
①下载“源码一”和“源码二”,然后分别解压
②源码一包含项目源码和部分jar包以及*.sql;源码二包含其余jar包,直接放入OSPM\WebRoot\WEB-INF\lib目录下即可
③使用eclipse打开,import导入项目
④修改OSPM/config/mysql-jdbc.properties数据库连接帐号密码
⑤使用eclipse自带插件:servers部署启动项目
⑥访问http://localhost:8080/OSPM即可
需要注意的是,这个项目是eclipse下创建的dynamic web project不是tomcat项目
另一种方案:
完成上面①~④步骤以后把项目export成war包,直接放到tomcat的webapps下然后启动
<result>/Web/ospm/loginInfo/page/LoginInfo{1}.jsp</result>
</action>
<action name="doLoginInfo*" method="doLoginInfo{1}">
<interceptor-ref name="jsonAjaxStack"></interceptor-ref>
</action>
</package>
注意上面goLoginInfo*使用了通配符,即如果是goLoginInfoMain,struts2会自动去寻找名为goLoginInfoMain的方法。package com.bless.ospm.model.base;import java.io.Serializable;/** * This is an object that contains data related to the login_info table. * Do not modify this class because it will be overwritten if the configuration file * related to this class is modified. * * @hibernate.class * table="login_info" */public abstract class BaseLoginInfo implements Serializable {private static final long serialVersionUID = -1290159826307427542L;public static String REF = "LoginInfo";public static String PROP_STATUS = "status";public static String PROP_CODE_NO = "codeNo";public static String PROP_LOGIN_CODE = "loginCode";public static String PROP_PASSWORD = "password";public static String PROP_ID = "id";// constructorspublic BaseLoginInfo () {initialize();}/** * Constructor for primary key */public BaseLoginInfo (java.lang.Integer id) {this.setId(id);initialize();}/** * Constructor for required fields */public BaseLoginInfo (java.lang.Integer id,java.lang.String loginCode,java.lang.String password,java.lang.Integer status) {this.setId(id);this.setLoginCode(loginCode);this.setPassword(password);this.setStatus(status);initialize();}public BaseLoginInfo(Integer id, String loginCode, Integer status) {super();this.id = id;this.loginCode = loginCode;this.status = status;}protected void initialize () {}private int hashCode = Integer.MIN_VALUE;// primary keyprivate java.lang.Integer id;// fieldsprivate java.lang.String codeNo;private java.lang.String loginCode;private java.lang.String password;private java.lang.Integer status;// collectionsprivate java.util.Set<com.bless.ospm.model.LoginXRole> loginXRoles;private java.util.Set<com.bless.ospm.model.LoginXOrg> loginXOrgs;private java.util.Set<com.bless.ospm.model.LoginXPriv> loginXPrivs;/** * Return the unique identifier of this class * @hibernate.id * generator-+ this.getId().hashCode();this.hashCode = hashStr.hashCode();}}return this.hashCode;}public String toString () {return super.toString();}}
还有登录这段,用了HashMap,好复杂啊,看不明
public void doLogin(LoginInfo loginInfo, HttpSession session) {//使用条件查询获取帐号密码Map<String, Object> proMap = new HashMap<String, Object>();proMap.put(LoginInfo.PROP_LOGIN_CODE, loginInfo.getLoginCode().trim());//密码需要MD5转换proMap.put(LoginInfo.PROP_PASSWORD, MD5.getMd5(loginInfo.getPassword()));//用户状态:启用proMap.put(LoginInfo.PROP_STATUS, LoginInfo.LOGIN_STATUS_AVAILABLE);List<LoginInfo> lstLoginInfo = (List<LoginInfo>) loginInfoDao.findByPropertiesEq(LoginInfo.class, proMap, null, 0, 0);//如果帐号不存在则抛出异常if(lstLoginInfo==null||lstLoginInfo.size()!=1){throw new LoginServiceException("帐号或密码错误");}//否则保存帐号信息到session中session.setAttribute(Constants.SESSION_LOGIN, lstLoginInfo.get(0));}
