- 今天內容安排:
- 1、解決window窗口bug
- 2、bos項目整體需求分析(基礎設置、取派、中轉、路由、報表)
- 3、取派員添加功能
- 4、jQuery easyUI 數據網格控件 datagrid 的使用方式
- 5、基於datagrid實現取派員分頁查詢
- 6、取派員批量刪除功能
- 7、取派員信息修改功能
1、解決window窗口bug
將上面的js文件引入所需要的jsp頁面中,本例以index.jsp爲例 /bos19/WebContent/WEB-INF/pages/common/index.jsp
<!-- 引入 防止window拖拽出邊界的js代碼--> <script src="${pageContext.request.contextPath }/js/outOfBounds.js" type="text/javascript"> </script>
2、bos項目整體需求分析之部分需求分析
整個基礎設置部分對應需求文檔2.6章節。如下圖所示:
2.1、基礎檔案設置
功能概述: 在其他的系統中通常稱爲“數據字典”。`提供基礎數據,供其他模塊使用`。 主要是針對本系統中的一些自定義項,需要參照錄入,並作爲統計分析和計算的維度,用戶根據自己的需要動態設置的基礎檔案;對於自定義的檔案支持多級定義; 系統會事先預置一些系統級別的基礎檔案,如線路類型、保險類型等;客戶根據自己的需要動態增加,主要是應用在`參照錄入`; 此功能主要是爲`系統的可擴張性`而設置的; 此功能主要應用角色是`“系統管理員”`; 目前需要在此設置的基礎檔案包括:線路類型、取派員類型、簽收類型、保險類型、受理備註說明、配載信息、返貨原因、消單原因、取消簽收類型、返貨拒絕類型、大物流類型。
2.2、收派標準
功能概述: 將承接的貨物,按照重量和體積兩個標準,雙緯度定義貨物的標準。以便將不同標準的貨物分給不同收取和派送能力的人員。由運營部門制定。
2.3、班車設置
功能概述: 班車設置表,線路設置表。 將設置的線路和車輛建立對應關係。
2.4、取派員設置/替班
功能概述: 小件員設置主要是設置小件員和快遞員的資源信息,主要是爲了自動下單和取派任務件使用;包括增加小件員的交通工具和通訊設備,以及取派的重量和體積標準。 使用角色爲各級組織機構的系統管理人員在添加。 取派設置中包括小件員的替班信息設置。 以及被替班人信息的查詢功能。
2.5、區域設置
功能概述: 區域爲國家劃分的行政區域。
2.6、管理分區
功能概述: 區域範圍很大,不規則,不便於直接進行人員分配,需要對區域進行細分 --> 分區。
2.7、管理定區/調度排版
功能概述: `定區是物流分配的基本單位`。定區可以將分區、取派員、客戶信息進行關聯,爲自動分單提供數據支持。使用hessian技術,遠程調用技術。
2.8、收派時間管理
功能概述: 上班時間的管理,根據取派人員的可上班時間,將區域取派任務在不同時限分配給不同的取派人員。建議時間管理由總公司部門管理,固化出各種上班時間點。下級廳點只有調用權限,沒有修改權限。
3、取派員添加功能
頁面位置:/WEB-INF/pages/base/staff.jsp
爲了便於處理,我們先將取派員編號選項框
刪掉,該編號我們讓其自動生成。
我們在Staff.hbm.xml中更改主鍵生成策略,代碼如下:
<id name="id" type="java.lang.String"> <column name="id" length="32" /> <!-- generator:主鍵生成策略,uuid:生成32位的不重複隨機字符串當做主鍵 --> <generator class="uuid" /> </id>
修改後的界面,如下圖所示:
第一步:由於默認自帶的檢驗規則較少,所以我們需要擴展校驗規則,對手機號進行校驗
<script type="text/javascript"> // 擴展校驗規則 $(function() { var reg = /^1[3|4|5|7|8|9][0-9]{9}$/; $.extend($.fn.validatebox.defaults.rules, { phonenumber: { validator: function(value, param) { return reg.test(value); }, message: '手機號輸入有誤!' } }); }); </script>
第二步:在對應手機號輸入框上,應用上面的校驗規則
<tr> <td>手機號</td> <td><input type="text" name="telephone" class="easyui-validatebox" required="true" data-options="validType:'phonenumber'" /></td> </tr>
第三步:爲添加窗口中的“保存按鈕”綁定事件
<div class="datagrid-toolbar"> <a id="save" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a> <script type="text/javascript"> $(function() { // 綁定事件 $("#save").click(function() { // 先校驗表單輸入項 var v = $("#addStaffForm").form("validate"); if (v) { // 說明校驗通過,提交增加收派員的表單 $("#addStaffForm").submit(); } }); }); </script> </div>
第四步:創建StaffAction類,提供add方法,處理取派員添加動作 StaffAction.java
package com.itheima.bos.web.action; import javax.annotation.Resource; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller; import com.itheima.bos.domain.Staff; import com.itheima.bos.service.IStaffService; import com.itheima.bos.web.action.base.BaseAction; /** * 取派員設置 * @author Bruce * */ @Controller @Scope("prototype") public class StaffAction extends BaseAction<Staff> { // 注入service @Resource private IStaffService staffService; /** * 添加取派員 * @return */ public String add() { staffService.save(model); return "list"; } }
IStaffService.java
package com.itheima.bos.service; import com.itheima.bos.domain.Staff; public interface IStaffService { public void save(Staff model); }
StaffServiceImpl.java
package com.itheima.bos.service.impl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.itheima.bos.dao.IStaffDao; import com.itheima.bos.domain.Staff; import com.itheima.bos.service.IStaffService; @Service @Transactional public class StaffServiceImpl implements IStaffService { // 注入dao @Autowired private IStaffDao staffDao; public void save(Staff model) { staffDao.save(model); } }
IStaffDao.java
package com.itheima.bos.dao; import com.itheima.bos.dao.base.IBaseDao; import com.itheima.bos.domain.Staff; public interface IStaffDao extends IBaseDao<Staff> { }
StaffDaoImpl.java
package com.itheima.bos.dao.impl; import org.springframework.stereotype.Repository; import com.itheima.bos.dao.IStaffDao; import com.itheima.bos.dao.base.impl.BaseDaoImpl; import com.itheima.bos.domain.Staff; @Repository public class StaffDaoImpl extends BaseDaoImpl<Staff> implements IStaffDao { }
第五步:配置struts.xml
<!-- 配置staffAction--> <action name="staffAction_*" class="staffAction" method="{1}"> <result name="list">/WEB-INF/pages/base/staff.jsp</result> </action>
4、jQuery easyUI 數據網格控件 datagrid 的使用方式
數據網格(datagrid)以表格格式顯示數據,併爲選擇、排序、分組和編輯數據提供了豐富的支持。數據網格(datagrid)的設計目的是爲了減少開發時間,且不要求開發人員具備指定的知識。它是輕量級的,但是功能豐富。它的特性包括單元格合併,多列頁眉,凍結列和頁腳,等等。
4.1、方式一:將HTML代碼渲染成datagrid樣式
<h3>方式一:將靜態的HTML代碼渲染成datagrid樣式,不常用</h3> <table class="easyui-datagrid"> <thead> <tr> <th data-options="field:'id'">編號</th> <th data-options="field:'name'">姓名</th> <th data-options="field:'age'">年齡</th> </tr> </thead> <tbody> <tr> <td>001</td> <td>張三</td> <td>20</td> </tr> <tr> <td>002</td> <td>李四</td> <td>30</td> </tr> </tbody> </table>
4.2、方式二:發送ajax請求獲取json數據,並顯示,常用,該數據網格可以自己發送ajax請求
<h3>方式二:發送ajax請求獲取json數據,並顯示,常用,該數據網格可以自己發送ajax請求</h3> <table class="easyui-datagrid" data-options="url:'/bos19/json/data.json'"> <thead> <tr> <th data-options="field:'id'">編號</th> <th data-options="field:'name'">姓名</th> <th data-options="field:'age'">年齡</th> </tr> </thead> </table>
要求服務端返回的json數據的格式滿足:
該數據可以有多項,但是上述代碼我們只取前三項。
4.3、方式三:通過js代碼,使用插件提供的API動態創建datagrid,大量使用
<h3>方式三:通過js代碼,使用插件提供的API動態創建datagrid,大量使用</h3> <table id="grid"> </table> <script type="text/javascript"> $(function() { $("#grid").datagrid({ columns:[[ // 定義標題行所有的列,是一個二維數組 {field:'id',title:'編號',checkbox:true}, // 是否複選框 {field:'name',title:'姓名'}, {field:'age',title:'年齡'} ]], url:'/bos19/json/data.json', // 指定URL地址,datagrid控件會自動發送ajax請求獲取數據 toolbar:[ // 工具欄按鈕 {text:'添加',iconCls:'icon-add'}, {text:'刪除',iconCls:'icon-remove', handler:function() { // 獲得選中的行 var rows = $("#grid").datagrid("getSelections"); for(var i=0; i < rows.length; i++) { var id = rows[i].id; // 獲取id字段的值 alert(id); } }}, {text:'修改',iconCls:'icon-edit'} ], singleSelect:true, // 是否可以單選 pagination:true, // 分頁條 pageList:[3,5,7] // 自定義分頁條中的下拉框選項 }); }); </script>
要求服務端返回的json數據的格式滿足:
該數據可以有多項,但是上述代碼我們只取前三項。 注意兩個rows的區別:
三種方式的效果如下圖所示:
5、基於datagrid實現取派員分頁查詢
第一步:修改staff.jsp頁面中datagrid的URL地址,訪問action
// 取派員信息表格 $('#grid').datagrid( { iconCls : 'icon-forward', fit : true, // 自適應 border : false, rownumbers : true, // 顯示行號 striped : true, pageList: [3,5,10], pagination : true, toolbar : toolbar, // 工具欄 url : "${pageContext.request.contextPath}/staffAction_pageQuery.action", // 服務器響應回來的是json數據,通過jQuery EasyUI的datagrid數據網格顯示出來 idField : 'id', columns : columns, onDblClickRow : doDblClickRow // 雙擊表格數據 });
效果如下:
第二步:創建一個PageBean類,用於封裝分頁信息
package com.itheima.bos.utils; import java.util.List; import org.hibernate.criterion.DetachedCriteria; /** * 封裝分頁信息 * @author Bruce * */ public class PageBean { private int currentPage; // 當前頁碼 private int pageSize; // 每頁顯示記錄數 private int total; // 總記錄數 private DetachedCriteria detachedCriteria; // 離線條件查詢對象,封裝查詢條件 // List<?> 表示集合裏的對象類型不確定,未指定 private List<?> rows; // 當前頁需要展示的數據集合 public int getCurrentPage() { return currentPage; } public void setCurrentPage(int currentPage) { this.currentPage = currentPage; } public int getPageSize() { return pageSize; } public void setPageSize(int pageSize) { this.pageSize = pageSize; } public int getTotal() { return total; } public void setTotal(int total) { this.total = total; } public DetachedCriteria getDetachedCriteria() { return detachedCriteria; } public void setDetachedCriteria(DetachedCriteria detachedCriteria) { this.detachedCriteria = detachedCriteria; } public List<?> getRows() { return rows; } public void setRows(List<?> rows) { this.rows = rows; } }
第三步:在StaffAction類中提供pageQuery()方法 由於瀏覽器發送過來的請求中帶了2個參數(page和rows),我們需要採用屬性驅動的方式,提供兩個setPage和setRows方法,接收頁面提交過來的參數
// 採用屬性驅動的方式,接收頁面提交過來的參數 private int page; // 當前頁碼 private int rows; // 每頁顯示的記錄數 public void setPage(int page) { this.page = page; } public void setRows(int rows) { this.rows = rows; } /** * 分頁查詢 * @throws IOException */ public String pageQuery() throws IOException { PageBean pageBean = new PageBean(); // 設置當前頁碼 pageBean.setCurrentPage(page); // 設置每頁顯示記錄數 pageBean.setPageSize(rows); // 設置離線條件查詢對象,封裝查詢條件 DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Staff.class); // 創建離線條件查詢對象 pageBean.setDetachedCriteria(detachedCriteria); // 調用該方法,設置PageBean對象的其他屬性 staffService.pageBean(pageBean); // 步驟:先導入json-lib的jar包+依賴包,步驟鏈接:https://www.cnblogs.com/chenmingjun/p/9513143.html // 將PageBean對象轉爲JSON格式的數據響應給客戶端瀏覽器進行顯示 // 排除不需要的數據和排除關聯對象 JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setExcludes(new String[] {"currentPage", "pageSize", "detachedCriteria"}); JSONObject jsonObject = JSONObject.fromObject(pageBean, jsonConfig); String json = jsonObject.toString(); ServletActionContext.getResponse().setContentType("text/json;charset=UTF-8"); ServletActionContext.getResponse().getWriter().print(json); return "none"; }
第四步:在BaseDao中提供通用分頁查詢方法
/** * 通用分頁查詢方法 */ public void pageBean(PageBean pageBean) { // 我們先把在StaffAction類中已經對PageBean類賦值好的3個值取出來 int currentPage = pageBean.getCurrentPage(); int pageSize = pageBean.getPageSize(); DetachedCriteria detachedCriteria = pageBean.getDetachedCriteria(); // 我們的PageBean還差兩個屬性沒有賦值 // 總記錄數 --> select count(*) from bc_staff // 人爲改變Hibernate框架默認發出SQL的形式,默認發出的是:select * from bc_staff detachedCriteria.setProjection(Projections.rowCount()); // 發:select count(*) from bc_staff List<Long> list = this.getHibernateTemplate().findByCriteria(detachedCriteria); Long total = list.get(0); // 設置總記錄數 pageBean.setTotal(total.intValue()); // 將Hibernate框架發出SQL的形式還原成默認的形式:select * from bc_staff detachedCriteria.setProjection(null); // 重置表和類的映射關係 detachedCriteria.setResultTransformer(DetachedCriteria.ROOT_ENTITY); // 當前頁需要展示的數據集合 int firstResult = (currentPage - 1) * pageSize; int maxResult = pageSize; List<?> rows = this.getHibernateTemplate().findByCriteria(detachedCriteria, firstResult, maxResult); // 設置當前頁需要展示的數據集合 pageBean.setRows(rows); }
效果截圖:
6、取派員批量刪除功能
邏輯刪除取派員,將取派員的deltag改爲“1” 第一步:爲“作廢”按鈕綁定事件
// 批量刪除取派員 function doDelete() { // 獲得選中的行 var rows = $("#grid").datagrid("getSelections"); if (rows.length == 0) { // 沒有選中,提示 $.messager.alert("提示信息","請選擇需要刪除的記錄!","warning"); } else { var array = new Array(); // 選中了記錄,獲取選中行的id for(var i=0; i<rows.length; i++) { var id = rows[i].id; // 獲取屬性id的值 array.push(id); } var ids = array.join(","); // 1,2,3,4 // 發送同步請求,傳遞ids參數 window.location.href = '${pageContext.request.contextPath}/staffAction_delete.action?ids=' + ids; } }
第二步:在StaffAction中提供ids屬性和對應的set方法,創建delete()方法,用於批量刪除取派員
// 採用屬性驅動的方式,接收頁面提交過來的參數ids private String ids; public void setIds(String ids) { this.ids = ids; } /** * 批量刪除(邏輯刪除) * @return */ public String delete() { staffService.deleteBatch(ids); return "list"; }
第三步:在Service中提供批量刪除方法
/** * 批量刪除(邏輯刪除) */ public void deleteBatch(String ids) { String[] staffIds = ids.split(","); for (String staffId : staffIds) { staffDao.executeUpdate("staff.delete", staffId); } }
第四步:在Staff.hbm.xml中定義命名查詢語句
<!-- 命名查詢語句 --> <query name="staff.delete"> update Staff set deltag='1' where id=? </query>
列(Column)屬性中,單元格的格式化函數:formatter
// 定義列 var columns = [ [ { field : 'id', checkbox : true, },{ field : 'name', title : '姓名', width : 120, align : 'center' }, { field : 'telephone', title : '手機號', width : 120, align : 'center' }, { field : 'haspda', title : '是否有PDA', width : 120, align : 'center', formatter : function(data,row, index) { // formatter 單元格的格式化函數 if (data=="1") { return "有"; } else { return "無"; } } }, { field : 'deltag', title : '是否作廢', width : 120, align : 'center', formatter : function(data,row, index) { // formatter 單元格的格式化函數 if (data=="0") { return "正常使用" } else { return "已作廢"; } } }, { field : 'standard', title : '取派標準', width : 120, align : 'center' }, { field : 'station', title : '所謂單位', width : 200, align : 'center' } ] ];
7、取派員信息修改功能
第一步:複製添加取派員窗口,獲得修改取派員窗口,注意:要修改取派員窗口的格式,並添加隱藏域
<!-- 修改取派員窗口 --> <div class="easyui-window" title="對收派員進行添加或者修改" id="editStaffWindow" collapsible="false" minimizable="false" maximizable="false" style="top:20px;left:200px"> <div region="north" style="height:31px;overflow:hidden;" split="false" border="false" > <div class="datagrid-toolbar"> <!-- 爲添加窗口中的“保存按鈕”綁定事件 --> <a id="edit" icon="icon-save" href="#" class="easyui-linkbutton" plain="true" >保存</a> <script type="text/javascript"> $(function() { // 綁定事件 $("#edit").click(function() { // 先校驗表單輸入項 var v = $("#editStaffForm").form("validate"); if (v) { // 說明校驗通過,提交增加收派員的表單 $("#editStaffForm").submit(); } }); }); </script> </div> </div> <div region="center" style="overflow:auto;padding:5px;" border="false"> <form id="editStaffForm" action="${pageContext.request.contextPath}/staffAction_edit.action" method="post"> <!-- 提供隱藏域 --> <!-- <input type="text" name="id"> --> <input type="hidden" name="id"> <table class="table-edit" width="80%" align="center"> <tr class="title"> <td colspan="2">取派員信息</td> </tr> <!-- TODO 這裏完善收派員添加 table --> <!-- <tr> <td>取派員編號</td> <td><input type="text" name="id" class="easyui-validatebox" required="true"/></td> </tr> --> <tr> <td>姓名</td> <td><input type="text" name="name" class="easyui-validatebox" required="true"/></td> </tr> <tr> <td>手機號</td> <td><input type="text" name="telephone" class="easyui-validatebox" required="true" data-options="validType:'phonenumber'" /></td> </tr> <tr> <td>單位</td> <td><input type="text" name="station" class="easyui-validatebox" required="true"/></td> </tr> <tr> <td colspan="2"> <input type="checkbox" name="haspda" value="1" /> 是否有PDA</td> </tr> <tr> <td>取派標準</td> <td> <input type="text" name="standard" class="easyui-validatebox" required="true"/> </td> </tr> </table> </form> </div> </div>
第二步:修改datagrid的雙擊行事件的處理函數 onDblClickRow 當用戶雙擊一行時觸發,參數包括: rowIndex:被雙擊行的索引,從 0 開始 rowData:被雙擊行對應的記錄
// 當用戶雙擊一行時觸發該事件 function doDblClickRow(rowIndex, rowData) { // rowData => id:xxx,name:xxx,... // 打開修改取派員窗口 $('#editStaffWindow').window("open"); // 回顯數據 // $("input[name=name]").val(rowData.name); // 顯示姓名 $('#editStaffForm').form("load", rowData); // 顯示整個表格的數據 }
第三步:提交修改的表單
第四步:在StaffAction中提供edit()方法,修改取派員信息
/** * 取派員信息修改 * @return */ public String edit() { // 這樣直接更新是不正確的,因爲Staff這個表不是獨立的,它有很多引用和被引用。 // staffService.update(model); // 先查詢數據庫中的原始數據 Staff staff = staffService.findById(model.getId()); // 再按照頁面提交過來的參數進行對應的覆蓋 staff.setName(model.getName()); staff.setTelephone(model.getTelephone()); staff.setStation(model.getStation()); staff.setHaspda(model.getHaspda()); staff.setStandard(model.getStandard()); // 更新數據 staffService.update(staff); return "list"; }