本实例通过国内比较流行的MVC框架-Nutz,前台使用jquery EasyUI,其中表格使用的Datagrid实现数据员工管理,其中涉及增加、删除、修改、分页效果。
maven管理依赖源码:https://gitee.com/suze/zms_maven
Jar包管理源码:https://gitee.com/suze/zms_jars
本实例在开发中涉及的的问题有:
- 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;
}
}
EmployeeService接口:
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);
}
EmployeeServiceImpl.java实现类
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;
}
}
EmployeeModule.java(该累充当角色类似与struts2框架的Action)
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>
sys_employee_edit.jsp 员工添加/编辑页面
说明:由于添加和修改想共用一个页面,当编辑时,根据选中行的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 %>"/>
2、Common.jsp
<%@ 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>
3、Page.js
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'); // 如果提交成功则隐藏进度条
});
}
}
}