本实例通过国内比较流行的MVC框架-Nutz,前台使用jquery EasyUI,其中表格使用的Datagrid实现数据员工管理,其中涉及增加、删除、修改、分页效果。
本实例在开发中涉及的的问题有:
1、如何共用添加、修改页面,并方便数据填充到表单。
2、jquery EasyUI的datagrid组件中、分页组件默认是10条,其中我最初设置想显示15条,但是遇到一个情况,页面加载时,依然是10条,只有通过点击分页组件的刷新
按钮或点击分页按钮才显示15条,最后通过研究,详见Pager.js源码。
3、由于员工表中职务是引用职务表的id,因此在datagrid数据展示,如何显示职务成为一个问题。最后通过查看Nutz API,使用了一对一映射。代码详见EmployeeModel.java注解,以及EmployeeServiceImpl.java init方法,使用了fetchLinks方法解决,然后在遍及数据时,封装每一个元素的viewDuty属性,以便于datagrid数据加载绑定。
4、由于使用了iframe,开发中发现第一次打开添加/编辑页面时,界面元素样式有很大问题,只要一刷新iframe中的页面,就不会有问题了。最后通过使用jquery类库高版本,方才解决问题。我使用的是1.9版本,最后不要超过2.0(该版本不兼容IE6、7浏览器)。
效果图:
数据库设计:
职务表:
员工表:
程序结构图:
源码在线:
EmployeeModel.java
package org.chris.model; import java.util.Date; import org.nutz.dao.entity.annotation.Column; import org.nutz.dao.entity.annotation.Id; import org.nutz.dao.entity.annotation.One; import org.nutz.dao.entity.annotation.Table; @Table("employee") public class EmployeeModel { @Id @Column private int id; @Column private String name; @Column("duty_id") private int dutyId; @Column private String gender; @Column private Date birthday; @Column private Date firedate; @Column private Date hiredate; @Column private String idcard; @Column private String address; @Column private String phone; @Column private String email; @Column("create_by") private int createBy; @Column("create_date") private Date createDate; @One(target=DutyModel.class,field="dutyId") private DutyModel duty; private String viewDuty; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getDutyId() { return dutyId; } public void setDutyId(int dutyId) { this.dutyId = dutyId; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getBirthday() { return birthday; } public void setBirthday(Date birthday) { this.birthday = birthday; } public Date getFiredate() { return firedate; } public void setFiredate(Date firedate) { this.firedate = firedate; } public Date getHiredate() { return hiredate; } public void setHiredate(Date hiredate) { this.hiredate = hiredate; } public String getIdcard() { return idcard; } public void setIdcard(String idcard) { this.idcard = idcard; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getPhone() { return phone; } public void setPhone(String phone) { this.phone = phone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public int getCreateBy() { return createBy; } public void setCreateBy(int createBy) { this.createBy = createBy; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } public DutyModel getDuty() { return duty; } public void setDuty(DutyModel duty) { this.duty = duty; } public String getViewDuty() { return viewDuty; } public void setViewDuty(String viewDuty) { this.viewDuty = viewDuty; } }
package org.chris.service; import java.util.Map; import org.chris.model.EmployeeModel; public interface EmployeeService { /** * 添加 * @author Chris Suk * @date 2014-4-24 下午08:41:51 * @param model */ public Map<String, Object> save(EmployeeModel model); /** * 删除 * @author Chris Suk * @date 2014-4-24 下午08:41:51 * @param ids */ public Map<String, Object> delete(String...ids); /** * 加载 * @author Chris Suk * @date 2014-4-24 下午08:43:10 * @return */ public Map<String, Object> init(int rows,int page); }
package org.chris.service.impl; import java.util.HashMap; import java.util.List; import java.util.Map; import org.chris.model.DutyModel; import org.chris.model.EmployeeModel; import org.chris.service.EmployeeService; import org.nutz.dao.Cnd; import org.nutz.dao.pager.Pager; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.service.IdEntityService; @IocBean(name="employeeService",fields={"dao"}) public class EmployeeServiceImpl extends IdEntityService<EmployeeModel> implements EmployeeService { public Map<String, Object> save(EmployeeModel model) { Map<String, Object> result = new HashMap<String, Object>(); try { EmployeeModel query = this.dao().fetch(EmployeeModel.class, model.getId()); if(null!=query){ this.dao().update(model); }else{ this.dao().insert(model); } result.put("type", "0"); result.put("message", "保存成功"); } catch (RuntimeException e) { result.put("type", "1"); result.put("message", e.getMessage()); e.printStackTrace(); } return result; } public Map<String, Object> delete(String... ids) { Map<String, Object> result = new HashMap<String, Object>(); try { this.dao().clear(EmployeeModel.class, Cnd.where("id", "in", ids)); result.put("type", "0"); result.put("message", "删除成功"); } catch (RuntimeException e) { result.put("type", "1"); result.put("message", e.getMessage()); e.printStackTrace(); } return result; } /** * 分页查询 * @author Chris Suk * @date 2014-5-11 下午08:58:45 * @param rows * @param page * @return */ public Map<String, Object> init(int rows,int page) { Map<String, Object> result = new HashMap<String, Object>(); Pager pager = new Pager(); pager.setPageNumber(page); pager.setPageSize(rows); List<EmployeeModel> list = this.dao().query(EmployeeModel.class, null,pager); for(EmployeeModel model : list){ this.dao().fetchLinks(model, "duty"); DutyModel duty = model.getDuty(); if(null!=duty){ model.setViewDuty(duty.getName()); } } result.put("total", this.dao().query(EmployeeModel.class, null).size()); result.put("rows", list); return result; } }
package org.chris.module; import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.chris.model.EmployeeModel; import org.chris.service.impl.EmployeeServiceImpl; import org.nutz.ioc.loader.annotation.Inject; import org.nutz.ioc.loader.annotation.IocBean; import org.nutz.mvc.annotation.At; import org.nutz.mvc.annotation.Ok; import org.nutz.mvc.annotation.Param; @IocBean public class EmployeeModule { @Inject private EmployeeServiceImpl employeeService; @At("/employee/save") @Ok("json") // 返回形式是jsp public Map<String, Object> save(@Param("::model.") EmployeeModel model) { return this.employeeService.save(model); } @At("/employee/delete") @Ok("json") // 返回形式是jsp public Map<String, Object> delete(HttpServletRequest request) { String[] ids = request.getParameter("ids").split(","); return this.employeeService.delete(ids); } /** * 加载 * @author Chris Suk * @date 2014-4-22 下午10:13:57 * @param request */ @At("/employee/init") @Ok("json") // 返回形式是jsp public Map<String, Object> init(HttpServletRequest request,int rows,int page) { Map<String, Object> map = this.employeeService.init(rows,page); return map; } /** * 编辑 * @author Chris Suk * @date 2014-4-22 下午10:13:57 * @param request */ @At("/employee/edit") @Ok("jsp:/module/system/sys_employee_edit.jsp") // 返回形式是jsp public void edit(HttpServletRequest request,int id) { EmployeeModel model=this.employeeService.fetch(id); request.setAttribute("model", model); } }
sys_employee_manager.jsp 员工管理页面
<%@ page language="java" pageEncoding="UTF-8"%> <%@ include file="../../inc/include.jsp" %> <c:set var="title" value="员工管理"/> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${title}</title> <jsp:include page="../../inc/Common.jsp"/> <script type="text/javascript" src="${thisPath}/js/Common.js?v=${version}"></script> <script type="text/javascript" src="${thisPath}/module/js/Pager.js?v=${version}"></script> <script> Pager.actionPrefix='${thisPath}/employee/'; Pager.init(); </script> </head> <body> <table title="${title}"id="list" width="100%" height="auto" data-options="iconCls:'icon-edit',rownumbers: true,singleSelect:true,idField:'id',fitColumns:true,onClickRow: Pager.onClickRow"> <thead> <tr> <th data-options="field:'name',width:100,editor:'text'">姓名</th> <th data-options="field:'viewDuty',width:100,editor:'text'">职务</th> <th data-options="field:'gender',width:100,editor:'text',formatter:function(value,row,index){return value=='1'?'男':'女'}">性别</th> <th data-options="field:'firedate',width:100,editor:'text',formatter:function(value,row,index){return value?value.substring(0,10):'';}">入职日期</th> <th data-options="field:'address',width:100,editor:'text'">住址</th> <th data-options="field:'email',width:100,editor:'text'">邮箱</th> <th data-options="field:'phone',width:100,editor:'text'">电话</th> </tr> </thead> </table> <!-- 添加\编辑窗口 使用iframe方式,很方便的。自己创意,方便数据填充表单,利于代码维护。 --> <div id="editWindow" class="easyui-window" title="新建员工" data-options="iconCls:'icon-save',modal:true" style="width:400px;height:450px;padding:5px;"> <div class="easyui-layout" data-options="fit:true"> <iframe width="400" height="450" frameborder="0" src="" id="editIframe"></iframe> </div> </div> </body> </html>
说明:由于添加和修改想共用一个页面,当编辑时,根据选中行的id查询,填充到表单,所以我就使用了iframe来加载添加/修改页面。
<%@ page language="java" pageEncoding="UTF-8"%> <%@ include file="../../inc/include.jsp" %> <c:set var="title" value="员工管理"/> <c:set var="model" value="${requestScope.model}"/> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>${title}</title> <jsp:include page="../../inc/Common.jsp"/> <script type="text/javascript" src="${thisPath}/js/Common.js?v=${version}"></script> <script type="text/javascript" src="${thisPath}/module/js/Pager.js?v=${version}"></script> <script> Pager.actionPrefix='${thisPath}/employee/'; </script> </head> <body> <div class="editBox" data-options="region:'north'" style="padding:10px;"> <form id="editForm" method="post"> <input type="hidden" name="model.id" value="${model.id}"/> <ul> <li> <span class="label" for="name">员工姓名:</span> <input class="easyui-validatebox" type="text" name="model.name" data-options="required:true" value="${model.name}"/> </li> <li> <span class="label" for="dutyId">职务:</span> <input class="easyui-combobox" type="text" name="model.dutyId" data-options=" required:true, url:'${thisPath}/common/dutyList.do', valueField:'id', textField:'name', panelHeight:'auto'" value="${model.dutyId}"/> </li> <li> <span class="label" for="gender">性别:</span> <select class="easyui-combobox" name="model.gender" style="width:152px;"> <option selected="selected" value="1">男</option> <option value="2">女</option> </select> </li> <li> <span class="label" for="birthday">出生日期:</span> <input class="easyui-datebox" type="text" name="model.birthday" value="${model.birthday}"/> </li> <li> <span class="label" for="firedate">入职日期:</span> <input class="easyui-datebox" type="text" name="model.firedate" value="${model.firedate}"/> </li> <li> <span class="label" for="idcard">身份证号:</span> <input class="easyui-validatebox" type="text" name="model.idcard" value="${model.idcard}"/> </li> <li> <span class="label" for="address">住址:</span> <input class="easyui-validatebox" type="text" name="model.address" value="${model.address}" /> </li> <li> <span class="label" for="phone">电话:</span> <input class="easyui-validatebox" type="text" name="model.phone" value="${model.phone}"/> </li> <li> <span class="label" for="email">邮箱:</span> <input class="easyui-validatebox" type="text" name="model.email" data-options="validType:'email'" value="${model.email}"/> </li> <li class="buttons"> <a class="easyui-linkbutton" data-options="iconCls:'icon-ok'" href="javascript:void(0)" onclick="javascript:Pager.save();">确定</a> <a class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" href="javascript:void(0)" onclick="javascript:alert('cancel')">关闭</a> </li> </ul> </form> </div> </body> </html>
1、include.jsp
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <%@ page language="java" pageEncoding="GBK"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <c:set value="${pageContext.request.contextPath}" var="thisPath"/> <c:set var="appTitle" value="信息发布管理平台"/> <%String v = java.util.UUID.randomUUID().toString();%> <c:set var="version" value="<%=v %>"/>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <c:set value="${pageContext.request.contextPath}" var="thisPath"/> <%String v = java.util.UUID.randomUUID().toString();%> <c:set var="version" value="<%=v %>"/> <link rel="stylesheet" type="text/css" href="${thisPath}/plugins/jquery.easyui.1.3.6/themes/default/easyui.css"> <link rel="stylesheet" type="text/css" href="${thisPath}/plugins/jquery.easyui.1.3.6/themes/icon.css"> <link rel="stylesheet" type="text/css" href="${thisPath}/css/Common.css?v=${version}"> <script type="text/javascript" src="${thisPath}/plugins/jquery.easyui.1.3.6/jquery.min.js"></script> <script type="text/javascript" src="${thisPath}/plugins/jquery.easyui.1.3.6/jquery.easyui.min.js"></script> <script type="text/javascript" src="${thisPath}/plugins/jquery.easyui.1.3.6/easyui-lang-zh_CN.js"></script>
var editIndex = undefined; /** * 本基类为基础数据模块提供公共服务业务处理 * @author Chris Suk * @date 2014/4/26 * @type */ var Pager={ /** * action前缀 * @type String */ actionPrefix:'', title:'', /** * 初始化配置 */ init:function(){ $(function(){ $('#editWindow').window('close'); $('#list').datagrid({ url:Pager.actionPrefix+'init.do', pageNumber: 1, toolbar:[{ text:'新增', iconCls: 'icon-add', handler: function(){Pager.append();} },'-',{ text:'删除', iconCls: 'icon-remove', handler: function(){Pager.remove();} },'-',{ text:'编辑', iconCls: 'icon-edit', handler: function(){Pager.edit();} }], pageSize: 15,//每页显示的记录条数,默认为10 pageList: [15,30,50],//可以设置每页记录条数的列表 pagination: { pageNumber: 1, beforePageText: '第',//页数文本框前显示的汉字 afterPageText: '页 共 {pages} 页', displayMsg: '当前显示 {from} - {to} 条记录 共 {total} 条记录' } }); }); }, /** * Datagrid单击触发 * @param {} index */ onClickRow:function(index){ if (editIndex != index){ $('#list').datagrid('selectRow', index); editIndex = index; } }, /** * 判断是否正在编辑 */ endEditing:function(){ var rows = $('#list').datagrid('getRows'); for ( var i = 0; i < rows.length; i++) { $('#list').datagrid('endEdit', i); } }, /** * 新增 */ append:function(){ $('#editIframe').attr('src',this.actionPrefix+'edit.do'); $('#editWindow').window('open'); }, /** * 编辑 */ edit:function(){ var row = $('#list').datagrid('getSelected'); if(row){ $('#editIframe').attr('src',this.actionPrefix+'edit.do?id='+row.id); $('#editWindow').window('open'); }else{ $.msg('请选中一条记录'); } }, /** * 删除 */ remove:function(){ $.messager.confirm('操作提示', '您确定要删除选中记录吗?', function(r){ if (r){ var rows = $('#list').datagrid('getSelected'); if(rows){ var ids = rows.id; $.post(this.actionPrefix+'delete.do',{ids:ids},function(){ $('#list').datagrid('reload'); $.msg('删除成功'); }); }else{ $.msg('请选中一条记录'); } } }); }, /** * 保存 */ save:function(){ $.messager.progress(); var isValid = $('#editForm').form('validate'); if (!isValid){ $.messager.progress('close'); // 如果表单是无效的则隐藏进度条 }else{ var param = $('#editForm').serialize(); $.post(this.actionPrefix+'save.do',param,function(result){ result=eval('('+result+')'); if(result.type==0){ parent.$('#editWindow').window('close'); $.msg(result.message); parent.$('#list').datagrid('reload'); }else{ $.msg(result.message); } $.messager.progress('close'); // 如果提交成功则隐藏进度条 }); } } }