springboot 動吧專案選單模組
-
選單管理設計說明
-
業務設計說明
選單管理又稱為資源管理,是系統資源對外的表現形式。本模組主要是實現對選單進行新增、修改、查詢、刪除等操作,其表設計語句如下:
CREATE TABLE `sys_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(50) DEFAULT NULL COMMENT '資源名稱', `url` varchar(200) DEFAULT NULL COMMENT '資源URL', `type` int(11) DEFAULT NULL COMMENT '型別 1:選單 2:按鈕', `sort` int(11) DEFAULT NULL COMMENT '排序', `note` varchar(100) DEFAULT NULL COMMENT '備註', `parentId` int(11) DEFAULT NULL COMMENT '父選單ID,一級選單為0', `permission` varchar(500) DEFAULT NULL COMMENT '授權(如:sys:user:create)', `createdTime` datetime DEFAULT NULL COMMENT '建立時間', `modifiedTime` datetimeDEFAULT NULL COMMENT '修改時間', `createdUser` varchar(20) DEFAULT NULL COMMENT '建立使用者', `modifiedUser` varchar(20) DEFAULT NULL COMMENT '修改使用者', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='資源管理';
選單表與角色表是多對多的關係,在表設計時,多對多關係通常由中間表(關係表)進行維護,如圖-1所示:
基於角色選單表的設計,其角色和選單對應的關係資料要儲存到關係表中,其具體存
儲形式,如圖-2所示:
選單與角色的關係表指令碼設計如下:
CREATE TABLE `sys_role_menus` ( `id` int(11) NOT NULL AUTO_INCREMENT, `role_id` int(11) DEFAULT NULL COMMENT '角色ID', `menu_id` int(11) DEFAULT NULL COMMENT 'ID', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='角色與選單對應關係';
-
原型設計說明
基於使用者需求,實現選單靜態頁面(html/css/js),通過靜態頁面為使用者呈現選單模組的基本需求實現。
當在主頁左側選單欄,點選選單管理時,在主頁內容呈現區,呈現選單列表頁面,如
圖-3所示。
當在選單列表頁面點選新增按鈕時,非同步載入選單編輯頁面,並在列表內容呈現區,
呈現選單編輯頁面,如圖-4所示。
在選單編輯頁面選擇上級選單時,非同步載入選單資訊,並以樹結構的形式呈現上級菜
單,如圖-5所示。
-
API設計說明
選單管理業務後臺API分層架構及呼叫關係如圖-6所示:
-
選單管理列表頁面呈現
-
業務時序分析
選單管理頁面的載入過程,其時序分析如圖-7所示:
-
Controller實現
-
業務描述與設計實現
基於選單管理的請求業務,在PageController中新增doMenuUI方法,用於返回選單列表頁面。
-
關鍵程式碼設計與實現
第一步:在PageController中定義返回選單列表的方法。程式碼如下:
@RequestMapping("menu/menu_list") public String doMenuUI() { return "sys/menu_list"; }
第二步:在PageController中基於rest風格的url方式優化返回UI頁面的方法。找出共性進行提取,例如:
@RequestMapping("{module}/{moduleUI}") public String doModuleUI(@PathVariable String moduleUI) { return "sys/"+moduleUI; }
-
客戶端實現
-
首頁選單事件處理
-
業務描述與設計實現
首先準備選單列表頁面(/templates/pages/sys/menu_list.html),然後在starter.html頁面中點選選單管理時非同步載入選單列表頁面。
-
關鍵程式碼設計與實現
找到專案中的starter.html頁面,頁面載入完成以後,註冊選單管理項的點選事件,當點選選單管理時,執行事件處理函式。關鍵程式碼如下:
$(function(){ … doLoadUI("load-menu-id","menu/menu_list") })
說明:對於doLoadUI函式,假如在starter.html中已經定義,則無需再次定義.
function doLoadUI(id,url){ $("#"+id).click(function(){ $("#mainContentId").load(url); }); }
選單管理列表資料呈現
-
資料架構分析
選單列表頁面載入完成,啟動選單資料非同步載入操作,本次選單列表頁面要呈現選單以及2息,其資料查詢時,資料的封裝及傳遞過程,如圖-8所示。
說明:本模組將從資料庫查詢到的選單資料封裝到map物件,一行記錄一個map物件,其中key為表中的欄位(列)名,值為欄位(列)對應的值。時序圖如下
-
服務端關鍵業務及程式碼實現
-
Dao介面實現
-
業務描述及設計實現
通過資料層物件,基於業務層引數,查詢選單以及上級選單資訊(要查詢上級選單名)。
-
關鍵程式碼分析及實現
第一步:定義資料層介面物件,通過此物件實現資料庫中選單資料的訪問操作。關鍵程式碼如下:
@Mapper public interface SysMenuDao { }
第二步:在SysMenuDao介面中新增findObjects方法,基於此方法實現選單資料的查詢操作。程式碼如下:
List<Map<String,Object>> findObjects();
-
Mapper檔案實現
-
業務描述及設計實現
基於Dao介面建立對映檔案,在此檔案中通過相關元素(例如select)描述要執行的資料操作。
-
關鍵程式碼設計及實現
第一步:在對映檔案的設計目錄中新增SysMenuMapper.xml對映檔案,程式碼如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysMenuDao"> </mapper>
第二步:在對映檔案中新增id為findObjects的元素,實現選單記錄查詢。我們要查詢所有選單以及選單對應的上級選單名稱。關鍵程式碼如下:
<select id="findObjects" resultType="map"> <!-- 方案1 select c.*,p.name parentName from sys_menus c left join sys_menus p on c.parentId=p.id --> <!-- 方案2 --> select c.*,( select p.name from sys_menus p where c.parentId=p.id ) parentName from sys_menus c </select>
說明:自關聯查詢分析,如圖-10所示:
-
Service介面及實現類
-
業務描述與設計實現
在選單查詢中,業務層物件主要是藉助資料層物件完成選單資料的查詢。後續還可以基於AOP對資料進行快取,記錄訪問日誌等。
-
關鍵程式碼設計及實現
第一步:定義選單業務介面及方法,暴露外界對選單業務資料的訪問,其程式碼參考如下:
package com.cy.pj.sys.service; public interface SysMenuService { List<Map<String,Object>> findObjects(); }
第二步:定義選單業務介面實現類,並新增選單業務資料對應的查詢操作實現,其程式碼參考如下:
package com.cy.pj.sys.service.impl; @Service public class SysMenuServiceImpl implements SysMenuService{ @Autowired private SysMenuDao sysMenuDao; @Override public List<Map<String, Object>> findObjects() { List<Map<String,Object>> list= sysMenuDao.findObjects(); if(list==null||list.size()==0) throw new ServiceException("沒有對應的選單資訊"); return list; }
-
Controller類實現
-
業務描述與設計實現
控制層物件主要負責請求和響應資料的處理,例如,本模組通過業務層物件執行業務邏輯,再通過VO物件封裝響應結果(主要對業務層資料新增狀態資訊),最後將響應結果轉換為JSON格式的字串響應到客戶端。
-
關鍵程式碼設計與實現
定義Controller類,並將此類物件使用Spring框架中的@Controller註解進行標識,表示此類物件要交給Spring管理。然後基於@RequestMapping註解為此類定義根路徑對映。程式碼參考如下:
package com.cy.pj.sys.controller; @RequestMapping("/menu/") @RestController public class SysMenuController { }
說明:這裡的@RestController註解等效於在類上同時添加了@Controller和 @ResponseBody註解.
在Controller類中新增選單查詢處理方法,程式碼參考如下:
@RequestMapping("doFindObjects") public JsonResult doFindObjects() { return new JsonResult(sysMenuService.findObjects()); }
-
客戶端關鍵業務及程式碼實現
-
選單列表資訊呈現
-
業務描述與設計實現
選單頁面載入完成以後,向服務端發起非同步請求載入選單資訊,當選單資訊載入完成需要將選單資訊呈現到列表頁面上。
-
關鍵程式碼設計與實現
第一步:在選單列表頁面引入treeGrid外掛相關的JS。
<script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.extension.js"></script> <script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.min.js"></script> <script type="text/javascript" src="bower_components/treegrid/tree.table.js"></script>
第二步:在選單列表頁面,定義選單列表配置資訊,關鍵程式碼如下:
var columns = [ { field : 'selectItem', radio : true }, { title : '選單ID', field : 'id', align : 'center', valign : 'middle', width : '80px' }, { title : '選單名稱', field : 'name', align : 'center', valign : 'middle', width : '130px' }, { title : '上級選單', field : 'parentName', align : 'center', valign : 'middle', sortable : true, width : '100px' }, { title : '型別', field : 'type', align : 'center', valign : 'middle', width : '70px', formatter : function(item, index) { if (item.type == 1) { return '<span class="label label-success">選單</span>'; } if (item.type == 2) { return '<span class="label label-warning">按鈕</span>'; } } }, { title : '排序號', field : 'sort', align : 'center', valign : 'middle', sortable : true, width : '70px' }, { title : '選單URL', field : 'url', align : 'center', valign : 'middle', width : '160px' }, { title : '授權標識',//要顯示的標題名稱 field : 'permission',//json串中的key align : 'center',//水平居中 valign : 'middle',//垂直居中 sortable : false //是否排序 } ];//格式來自官方demos -->treeGrid(jquery擴充套件的一個網格樹外掛)
第三步:定義非同步請求處理函式,程式碼參考如下:
function doGetObjects(){//treeGrid //1.構建table物件(bootstrap框架中treeGrid外掛提供) var treeTable=new TreeTable( "menuTable",//tableId "menu/doFindObjects",//url columns); //設定從哪一列開始展開(預設是第一列) //treeTable.setExpandColumn(2); //2.初始化table物件(底層傳送ajax請求獲取資料) treeTable.init();//getJSON,get(),... }
第四步:頁面載入完成,呼叫選單查詢對應的非同步請求處理函式,關鍵程式碼如下:
$(function(){ doGetObjects(); })
-
選單管理刪除操作實現
-
業務時序分析
基於使用者在列表頁面上選擇的的選單記錄ID,執行刪除操作,本次刪除業務實現中,首先要基於id判斷當前選單是否有子選單,假如有子選單則不允許刪除,沒有則先刪除選單角色關係資料,然後再刪除選單自身資訊。其時序分析如圖-11所示:
-
服務端關鍵業務及程式碼實現
-
Dao介面實現
-
業務描述及設計實現
資料層基於業務層提交的選單記錄id,刪除選單角色關係以及選單資料,選單自身記錄資訊。
-
關鍵程式碼設計及實現
第一步:建立SysRoleMenuDao並定義基於選單id刪除關係資料的方法,關鍵程式碼如下:
@Mapper public interface SysRoleMenuDao { int deleteObjectsByMenuId(Integer menuId); }
第二步:在SysMenuDao中新增基於選單id查詢子選單記錄的方法。程式碼參考如下:
int getChildCount(Integer id);
第三步:在SysMenuDao中新增基於選單id刪除選單記錄的方法。程式碼參考如下:
int deleteObject(Integer id);
-
Mapper檔案實現
-
業務描述及設計實現
在SysRoleMenuDao,SysMenuDao介面對應的對映檔案中新增用於執行刪除業務的delete元素,然後在元素內部定義具體的SQL實現。
-
關鍵程式碼設計與實現
第一步:建立SysRoleMenuMapper.xml檔案並新增基於選單id刪除關係資料的元素,關鍵程式碼如下:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.cy.pj.sys.dao.SysRoleMenuDao"> <delete id="deleteObjectsByMenuId" parameterType="int"> delete from sys_role_menus where menu_id=#{menuId} </delete> </mapper>
第二步:在SysMenuMapper.xml檔案中新增基於id統計子選單數量的元素,關鍵程式碼如下:
<select id="getChildCount" parameterType="int" resultType="int"> select count(*) from sys_menus where parentId=#{id} </select>
第三步:在SysMenuMapper.xml檔案新增delete元素,基於帶單id刪除選單自身記錄資訊,關鍵程式碼如下:
<delete id="deleteObject"> delete from sys_menus where id =#{id} </delete
-
Service介面及實現類
-
業務描述與設計實現
在選單業務層定義用於執行選單刪除業務的方法,首先通過方法引數接收控制層傳遞的選單id,並對引數id進行校驗。然後基於選單id統計子選單個數,假如有子選單則丟擲異常,提示不允許刪除。假如沒有子選單,則先刪除角色選單關係資料。最後刪除選單自身記錄資訊後並返回業務執行結果。
-
關鍵程式碼設計與實現
第一步:在SysMenuService介面中,新增基於id進行選單刪除的方法。關鍵程式碼如下:
int deleteObject(Integer id);
第二步:在SysMenuServiceImpl實現類中注入SysRoleMenuDao相關物件。關鍵程式碼如下:
@Autowired private SysRoleMenuDao sysRoleMenuDao;
第三步:在SysMenuServiceImpl實現類中新增刪除業務的具體實現。關鍵程式碼如下
@Override public int deleteObject(Integer id) { //1.驗證資料的合法性 if(id==null||id<=0) throw new IllegalArgumentException("請先選擇"); //2.基於id進行子元素查詢 int count=sysMenuDao.getChildCount(id); if(count>0) throw new ServiceException("請先刪除子選單"); //3.刪除角色,選單關係資料 sysRoleMenuDao.deleteObjectsByMenuId(id); //4.刪除選單元素 int rows=sysMenuDao.deleteObject(id); if(rows==0) throw new ServiceException("此選單可能已經不存在"); //5.返回結果 return rows; }
-
Controller類實現
-
業務描述與設計實現
在選單控制層物件中,新增用於處理選單刪除請求的方法。首先在此方法中通過形參接收客戶端提交的資料,然後呼叫業務層物件執行刪除操作,最後封裝執行結果,並在執行時將響應物件轉換為JSON格式的字串,響應到客戶端。
-
關鍵程式碼設計與實現
第一步:在SysMenuController中新增用於執行刪除業務的方法。程式碼如下:
@RequestMapping("doDeleteObject") public JsonResult doDeleteObject(Integer id){ sysMenuService.deleteObject(id); return new JsonResult("delete ok"); }
第二步:啟動tomcat進行訪問測試,開啟瀏覽器輸入如下網址:http://localhost/menu/doDeleteObject?id=10
-
客戶端關鍵業務及程式碼實現
-
選單列表頁面事件處理
-
業務描述及設計實現
使用者在頁面上首先選擇要刪除的元素,然後點選刪除按鈕,將使用者選擇的記錄id非同步提交到服務端,最後在服務端執行選單的刪除動作。
-
關鍵程式碼設計與實現
第一步:頁面載入完成以後,在刪除按鈕上進行點選事件註冊。關鍵程式碼如下:
$(".input-group-btn") .on("click",".btn-delete",doDeleteObject)
第二步:定義刪除操作對應的事件處理函式。關鍵程式碼如下:
function doDeleteObject(){ //1.獲取選中的記錄id var id=doGetCheckedId(); if(!id){ alert("請先選擇"); return; } //2.給出提示是否確認刪除 if(!confirm("確認刪除嗎"))return; //3.非同步提交請求刪除資料 var url="menu/doDeleteObject"; var params={"id":id}; $.post(url,params,function(result){ if(result.state==1){ alert(result.message); $("tbody input[type='radio']:checked") .parents("tr").remove(); }else{ alert(result.message); } }); }
第三步:定義獲取使用者選中的記錄id的函式。關鍵程式碼如下:
function doGetCheckedId(){ //1.獲取選中的記錄 var selections=$("#menuTable") //bootstrapTreeTable是treeGrid外掛內部定義的jquery擴充套件函式 //getSelections為擴充套件函式內部要呼叫的一個方法 .bootstrapTreeTable("getSelections"); //2.對記錄進行判定 if(selections.length==1) return selections[0].id; }
-
選單新增頁面呈現
-
業務時序分析
新增頁面載入時序分析,如圖-12所示:
-
準備選單編輯頁面
首先準備選單列表頁面(/templates/pages/sys/menu_edit.html),然後在menu_list.html頁面中點選選單新增時非同步載入選單編輯頁面。
-
選單編輯頁面呈現
-
業務描述與設計實現
選單列表頁面點選新增按鈕時,非同步載入選單編輯頁面。
-
關鍵程式碼設計與實現
第一步:選單列表頁面上,對新增按鈕進行事件註冊,關鍵程式碼如下:
在menu_edit.html頁面中定義用於呈現樹結構的DIV元件
<div class="layui-layer layui-layer-page layui-layer-molv layer-anim" id="menuLayer" type="page" times="2" showtime="0" contype="object" style="z-index:59891016; width: 300px; height: 450px; top: 100px; left: 500px; display:none"> <div class="layui-layer-title" style="cursor: move;">選擇選單</div> <div class="layui-layer-content" style="height: 358px;"> <div style="padding: 10px;" class="layui-layer-wrap"> <ul id="menuTree" class="ztree"></ul> <!-- 動態載入樹 --> </div> </div> <span class="layui-layer-setwin"> <a class="layui-layer-ico layui-layer-close layui-layer-close1 btn-cancel" ></a></span> <div class="layui-layer-btn layui-layer-btn-"> <a class="layui-layer-btn0 btn-confirm">確定</a> <a class="layui-layer-btn1 btn-cancel">取消</a> </div> </div>
-
ZTree資料呈現
-
業務描述與設計實現
引入zTree需要的JS,並,並基於JS中的定義的API初始化zTree中的選單資訊。
-
關鍵程式碼設計與實現
第一步:引入js檔案
<script type="text/javascript" src="bower_components/ztree/jquery.ztree.all.min.js"></script> <script type="text/javascript" src="bower_components/layer/layer.js"> </script>
第二步:在menu_edit.html中定義zTree配置資訊(初始化zTree時使用)
var zTree; var setting = { data : { simpleData : { enable : true, idKey : "id", //節點資料中儲存唯一標識的屬性名稱 pIdKey : "parentId", //節點資料中儲存其父節點唯一標識的屬性名稱 rootPId : null //根節點id } } }
第二步:定義非同步載入zTree資訊的函式,關鍵程式碼如下:
function doLoadZtreeNodes(){ var url="menu/doFindZtreeMenuNodes"; //非同步載入資料,並初始化資料 $.getJSON(url,function(result){ if(result.state==1){ //使用init函式需要先引入ztree對應的js檔案 zTree=$.fn.zTree.init( $("#menuTree"), setting, result.data); $("#menuLayer").css("display","block"); }else{ alert(result.message); } }) }
第三步:定義zTree中取消按鈕事件處理函式,點選取消隱藏zTree。關鍵程式碼如下:
function doHideTree(){ $("#menuLayer").css("display","none"); }
第四步:定義zTree中確定按鈕對應的事件處理處理函式。關鍵程式碼如下:
function doSetSelectNode(){ //1.獲取選中的節點物件 var nodes=zTree.getSelectedNodes(); if(nodes.length==1){ var node=nodes[0]; console.log(node); //2.將物件中內容,填充到表單 $("#parentId").data("parentId",node.id); $("#parentId").val(node.name); } //3.隱藏樹物件 doHideTree(); }
第五步:定義頁面載入完成以後的事件處理函式:
$(document).ready(function(){ $("#mainContentId") .on("click",".load-sys-menu",doLoadZtreeNodes) $("#menuLayer") .on("click",".btn-confirm",doSetSelectNode) .on("click",".btn-cancel",doHideTree) });
-
選單資料新增實現
-
資料基本架構分析
使用者在選單編輯頁面輸入資料,然後非同步提交到服務端,其簡易資料傳遞基本架構,如圖-14所示:
使用者在選單新增頁面中填寫好選單資料,然後點選儲存按鈕,將使用者填寫的資料新增
到資料庫。其時序分析,如圖-15所示:
-
服務端關鍵業務及程式碼實現
-
Entity類定義
-
業務描述與設計實現
定義持久化物件,封裝客戶端請求資料,並將資料傳遞到資料層進行持久化。
-
關鍵程式碼設計與實現
選單持久層物件型別定義,關鍵程式碼如下:
import lombok.Data;
@Data public class SysMenu implements Serializable{ private static final long serialVersionUID = -8805983256624854549L; private Integer id; /**選單名稱*/ private String name; /**選單url: log/doFindPageObjects*/ private String url; /**選單型別(兩種:按鈕,普通選單)*/ private Integer type=1; /**排序(序號)*/ private Integer sort; /**備註*/ private String note; /**上級選單id*/ private Integer parentId; /**選單對應的許可權標識(sys:log:delete)*/ private String permission; /**建立使用者*/ private String createdUser; /**修改使用者*/ private String modifiedUser; private Date createdTime; private Date modifiedTime;-
DAO介面定義
-
業務描述與設計實現
負責將使用者提交的選單資料,持久化到資料庫。
-
關鍵程式碼設計與實現
在SysMenuDao介面中定義資料持久化方法:
int insertObject(SysMenu entity);
-
Mapper對映檔案定義
-
業務描述與設計實現
基於SysMenuDao中方法的定義,編寫用於實現選單新增的SQL元素。
-
關鍵程式碼設計與實現
在SysMenuMapper.xml中新增insertObject元素,用於寫入選單資訊。關鍵程式碼如下:
<insert id="insertObject" parameterType="com.cy.pj.sys.entity.SysMenu"> insert into sys_menus (name,url,type,sort,note,parentId,permission, createdTime,modifiedTime,createdUser,modifiedUser) values (#{name},#{url},#{type},#{sort},#{note},#{parentId}, #{permission},now(),now(),#{createdUser},#{modifiedUser}) </insert>
-
Service介面定義及實現
-
業務描述與設計實現
基於控制層請求,呼叫資料層物件將選單資訊寫入到資料庫中。
-
關鍵程式碼設計與實現
第一步:在SysMenuService介面中,新增用於儲存選單物件的方法。關鍵程式碼如下
int saveObject(SysMenu entity);
第二步:在SysMenuServiceImpl類中,實現選單儲存操作。關鍵程式碼如下:
@Override public int saveObject(SysMenu entity) { //1.合法驗證 if(entity==null) throw new IllegalArgumentException("儲存物件不能為空"); if(StringUtils.isEmpty(entity.getName())) throw new IllegalArgumentException("選單名不能為空"); //2.儲存資料 int rows=sysMenuDao.insertObject(entity); //3.返回資料 return rows; }
-
Controller類定義
-
業務描述與設計實現
接收客戶端提交的選單資料,並對其進行封裝,然後呼叫業務層物件進行業務處理,最後將業務層處理結果響應到客戶端。
-
關鍵程式碼設計與實現
定義Controller方法,藉助此方法處理儲存選單資料請求和響應邏輯。關鍵程式碼如下:
@RequestMapping("doSaveObject") public JsonResult doSaveObject(SysMenu entity){ sysMenuService.saveObject(entity); return new JsonRehlt("save ok"); }
-
客戶端關鍵業務及程式碼實現
-
頁面cancel按鈕事件處理
-
業務描述與設計實現
點選頁面cancel按鈕時,載入選單那列表頁面。
-
關鍵程式碼設計與實現
第一步:事件註冊(頁面載入完成以後)
$(".box-footer") .on("click",".btn-cancel",doCancel)
第二步:事件處理函式定義
function doCancel(){ var url="menu/menu_list"; $("#mainContentId").load(url); }
-
頁面Save按鈕事件處理
-
業務描述與設計實現
點選頁面save按鈕時,將頁面上輸入的選單資訊非同步提交到服務端。
-
關鍵程式碼設計與實現
第一步:事件註冊(頁面載入完成以後)
$(".box-footer") .on("click",".btn-save",doSaveOrUpdate)
第二步:Save按鈕事件處理函式定義。關鍵程式碼如下:
function doSaveOrUpdate(){ //1.獲取表單資料 var params=doGetEditFormData(); //2.定義url var url="menu/doSaveObject"; //3.非同步提交資料 $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }); }
第三步:表單資料獲取及封裝函式定義。關鍵程式碼如下:
function doGetEditFormData(){ var params={ type:$("form input[name='typeId']:checked").val(), name:$("#nameId").val(), url:$("#urlId").val(), sort:$("#sortId").val(), permission:$("#permissionId").val(), parentId:$("#parentId").data("parentId") } return params; }
-
選單修改頁面資料呈現
-
業務時序分析
當在選單列表頁面中選中某條記錄,然後點選修改按鈕時,其業務時序分析如圖-16所示:
-
客戶端關鍵業務及程式碼實現
-
列表頁面修改按鈕事件處理
-
業務描述與設計實現
點選頁面修改按鈕時,獲取選中選單記錄,並非同步載入編輯頁面。
-
關鍵程式碼設計與實現
第一步:列表頁面修改按鈕事件註冊,關鍵程式碼如下:
$(".input-group-btn") .on("click",".btn-update",doLoadEditUI);
第二步:修改按鈕事件處理函式定義或修改,關鍵程式碼如下:
function doLoadEditUI(){ var title; if($(this).hasClass("btn-add")){ title="新增選單" }else if($(this).hasClass("btn-update")){ title="修改選單" //獲取選中的記錄資料 var rowData=doGetCheckedItem(); if(!rowData){ alert("請選擇一個"); return; } $("#mainContentId").data("rowData",rowData); } var url="menu/menu_edit"; $("#mainContentId").load(url,function(){ $(".box-title").html(title); }) }
第三步:獲取使用者選中記錄的函式定義。關鍵程式碼如下:
function doGetCheckedItem(){ var tr=$("tbody input[type='radio']:checked") .parents("tr"); return tr.data("rowData"); }
-
編輯頁面選單資料呈現
-
業務描述與設計實現
頁面載入完成,在頁面指定位置呈現要修改的資料。
-
關鍵程式碼設計與實現
第一步:頁面載入完成以後,獲取頁面div中繫結的資料。關鍵程式碼如下:
$(function(){ … //假如是修改 var data=$("#mainContentId").data("rowData"); if(data)doInitEditFormData(data); });
第二步:定義編輯頁面資料初始化方法。關鍵程式碼如下:
function doInitEditFormData(data){ /* $("input[type='radio']").each(function(){ if($(this).val()==data.type){ $(this).prop("checked",true); } }) */ $(".typeRadio input[value='"+data.type+"']").prop("checked",true); $("#nameId").val(data.name); $("#sortId").val(data.sort); $("#urlId").val(data.url); $("#permissionId").val(data.permission); $("#parentId").val(data.parentName); $("#parentId").data("parentId",data.parentId); }
-
選單資料更新實現
-
業務時序分析
當點選編輯頁面更新按鈕時,其時序分析如圖-17所示:
-
服務端關鍵業務及程式碼實現
-
DAO介面實現
-
業務描述與設計實現
負責將使用者編輯頁面提交到服務端的選單資料,更新到資料庫進行永續性儲存。
-
關鍵程式碼設計與實現
在SysMenuDao介面中新增資料更新方法,關鍵程式碼如下:
int updateObject(SysMenu entity);
-
Mapper對映檔案定義
-
業務描述與設計實現
基於SysMenuDao中updateObject方法的定義,編寫用於實現選單更新的SQL元素。
-
關鍵程式碼設計與實現
在SysMenuMapper.xml中新增updateObject元素,用於更新選單資訊。關鍵程式碼如下:
<update id="updateObject" parameterType="com.cy.pj.sys.entity.SysMenu"> update sys_menus set name=#{name}, type=#{type}, sort=#{sort}, url=#{url}, parentId=#{parentId}, permission=#{permission}, modifiedUser=#{modifiedUser}, modifiedTime=now() where id=#{id} </update>
-
Service介面及實現
-
業務描述與設計實現
基於控制層請求,對資料進行校驗並呼叫資料層物件將選單資訊更新到資料庫中。
-
關鍵程式碼設計與實現
第一步:在SysMenuService介面中,新增用於更新選單物件的方法。關鍵程式碼如下
int updateObject(SysMenu entity);
第二步:在SysMenuServiceImpl類中,實現選單儲存操作。關鍵程式碼如下:
@Override public int updateObject(SysMenu entity) { //1.合法驗證 if(entity==null) throw new ServiceException("儲存物件不能為空"); if(StringUtils.isEmpty(entity.getName())) throw new ServiceException("選單名不能為空"); //2.更新資料 int rows=sysMenuDao.updateObject(entity); if(rows==0) throw new ServiceException("記錄可能已經不存在"); //3.返回資料 return rows; }
-
Controller類定義
-
業務描述與設計實現
接收客戶端提交的選單資料,並對其進行封裝,然後呼叫業務層物件進行業務處理,最後將業務層處理結果響應到客戶端。
-
關鍵程式碼設計與實現
定義Controller方法,藉助此方法處理儲存選單資料請求和響應邏輯。關鍵程式碼如下
@RequestMapping("doUpdateObject") public JsonResult doUpdateObject( SysMenu entity){ sysMenuService.updateObject(entity); return new JsonResult("update ok"); }
-
客戶端關鍵業務及程式碼實現
-
編輯頁面更新按鈕事件處理
-
業務描述與設計實現
點選頁面save按鈕時,將頁面上輸入的選單編輯資訊提交到服務端。
-
關鍵程式碼設計與實現
編輯Save按鈕對應的事件處理函式。關鍵程式碼如下:
function doSaveOrUpdate(){ //1.獲取表單資料 var params=doGetEditFormData(); var rowData=$("#mainContentId").data("rowData"); //2.定義url var insertUrl="menu/doSaveObject"; var updateUrl="menu/doUpdateObject"; var url=rowData?updateUrl:insertUrl; if(rowData)params.id=rowData.id; //3.非同步提交資料 $.post(url,params,function(result){ if(result.state==1){ alert(result.message); doCancel(); }else{ alert(result.message); } }); }
-
重難點分析
-
選單管理在整個系統中的定位(資源管理)。
-
選單資料的自關聯查詢實現(查詢當前選單以及這個選單的上級選單)。
-
選單管理中資料的封裝過程(請求資料,響應資料)。
-
選單資料在客戶端的呈現。(treeGrid,zTree)
-
FAQ分析
-
選單表是如何設計的,都有哪些欄位?
-
選單列表資料在客戶端是如何展示的?(TreeGrid)
-
選單刪除業務是如何處理的?
-
選單編輯頁面中上級選單資料的呈現方式?(zTree)
-
常用表連線方式,如圖-18所示:
-
-
-