後臺管理系統-菜單管理模塊

1 菜單管理頁面設計

1.1 業務設計

菜單管理又稱爲資源管理,是系統資源對外的表現形式。本模塊主要是實現對菜單進行添加、修改、查詢、刪除等操做。javascript

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` datetime DEFAULT 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='資源管理';

菜單表與角色表是多對多的關係,在表設計時,多對多關係一般由中間表(關係表)進行維護
image.pngcss

基於角色菜單表的設計,其角色和菜單對應的關係數據要存儲到關係表中,其具體存儲形式
image.png
菜單與角色的關係表腳本設計以下:html

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='角色與菜單對應關係';

1.2 原型設計

當在主頁左側菜單欄,點擊菜單管理時,在主頁內容呈現區,呈現菜單列表頁面
image.pngjava

當在菜單列表頁面點擊添加按鈕時,異步加載菜單編輯頁面,並在列表內容呈現區,呈現菜單編輯頁面,如圖-4所示。node

image.png

在菜單編輯頁面選擇上級菜單時,異步加載菜單信息,並以樹結構的形式呈現上級菜單jquery

image.png

1.3 API設計

菜單管理業務後臺API分層架構及調用關係如圖
image.pngweb

2 菜單管理頁面展現

2.1 首頁菜單事件處理

▪ 業務描述與設計實現ajax

首先準備菜單列表頁面(/templates/pages/sys/menu_list.html),而後在starter.html頁面中點擊菜單管理時異步加載菜單列表頁面。spring

▪ 關鍵代碼設計與實現數據庫

找到項目中的starter.html頁面,頁面加載完成之後,註冊菜單管理項的點擊事件,當點擊菜單管理時,執行事件處理函數。關鍵代碼以下:

$(function(){
 …
 doLoadUI("load-menu-id","menu/menu_list")
})

說明:對於doLoadUI函數,假如在starter.html中已經定義,則無需再次定義.

function doLoadUI(id,url){
  $("#"+id).click(function(){
  $("#mainContentId").load(url);
 });
}

其中,load函數爲jquery中的ajax異步請求函數。

2.2 菜單列表頁面

▪ 業務描述與設計實現

本頁面呈現菜單信息時要以樹結構形式進行呈現。此樹結構會藉助jquery中的treeGrid插件進行實現,因此在菜單列表頁面須要引入treeGrid相關JS。可是,具體的treeGrid怎麼用可自行在網上進行查詢(已比較成熟)。

▪ 關鍵代碼設計與實現:

關鍵JS引入(menu_list.html),代碼以下:

<script type="text/javascript" src="bower_components/treegrid/jquery.treegrid.extension.js"></script>
<script type="text/javascript" src="bowe
r_components/treegrid/jquery.treegrid.min.js"></script>
<script type="text/javascript" src="bower_components/treegrid/tree.table.js"></script>

3 菜單管理頁面代碼實現

3.1 菜單列表數據實現

3.1.1 數據加載時序

頁面數據展現
菜單列表頁面加載完成,啓動菜單數據異步加載操做,本次菜單列表頁面要呈現菜單以及上級菜單信息,其數據查詢時,數據的封裝及傳遞過程
image.png

頁面菜單數據刪除展現
基於用戶在列表頁面上選擇的的菜單記錄ID,執行刪除操做,本次刪除業務實現中,首先要基於id判斷當前菜單是否有子菜單,假若有子菜單則不容許刪除,沒有則先刪除菜單角色關係數據,而後再刪除菜單自身信息。
image.png
上級菜單頁面展現
在菜單編輯頁面上,點擊上級菜單時,其數據加載時序分析
image.png
菜單數據添加實現
用戶在菜單編輯頁面輸入數據,而後異步提交到服務端,其簡易數據傳遞基本架構
image.png
用戶在菜單添加頁面中填寫好菜單數據,而後點擊保存按鈕,將用戶填寫的數據添加到數據庫。
image.png
菜單數據更新展現
當點擊編輯頁面更新按鈕時
image.png

3.1.2 代碼實現

第一步:建立SysMenuDao層接口

package com.cy.pj.sys.dao;
import com.cy.pj.common.pojo.Node;
import com.cy.pj.sys.pojo.SysMenu;
import com.cy.pj.sys.pojo.SysUserMenu;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
import java.util.Map;
@Mapper
public interface SysMenuDao {
    List<SysUserMenu> findMenusByIds(List<Integer> menuIds);
    //基於菜單ID獲取受權表示
    List<String> findPermissions(List<Integer> menuIds);
    int updateObject(SysMenu entity);
    @Insert(" 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})")
    int insertObject(SysMenu entity);
    @Select("select id,name,parentId from sys_menus")
    List<Node> findZtreeMenuNodes();
    
    @Select("select count(*) from sys_menus where parentId=#{id}")
    int getChildCount(Integer id);
    @Delete("delete from sys_menus where id=#{id}")
    int deleteObject(Integer id);
    //查詢全部菜單信息
    List<Map<String,Object>> findObjects();
}

第二步:建立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">
    <resultMap type="com.cy.pj.sys.pojo.SysUserMenu" id="sysUserMenu">
        <!-- 一級菜單映射 -->
        <id property="id" column="id"/>
        <result property="name" column="name"/>
        <result property="url" column="url"/>
        <!-- 二級菜單映射 -->
        <collection property="childs" ofType="com.cy.pj.sys.pojo.SysUserMenu">
            <id property="id" column="cid"/>
            <result property="name" column="cname"/>
            <result property="url" column="curl"/>
        </collection>
    </resultMap>
    <select id="findMenusByIds"
        resultMap="sysUserMenu">
        select p.id,p.name,p.url,c.id cid,c.name cname,c.url curl
        from sys_menus p join sys_menus c
        on c.parentId=p.id
        <where>
            <foreach collection="menuIds"
                 open="("
                 close=")"
                 separator="or"
                 item="menuId">
                c.id=#{menuId}
            </foreach>
            and p.parentId is null
        </where>
    </select>
    <select id="findPermissions"
        resultType="string">
        select permission <!-- sys:user:update -->
        from sys_menus
        where id in
        <foreach collection="menuIds"
             open="("
             close=")"
             separator=","
             item="item">
            #{item}
        </foreach>
    </select>
    <!--查詢全部菜單以及菜單對應的上級菜單,當沒有上級菜單時,當前菜單的上級菜單顯示爲null-->
    <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>
    <update id="updateObject"
        parameterType="com.cy.pj.sys.pojo.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>
</mapper>

第三步:建立SysMenuService接口

在菜單查詢中,業務層對象主要是藉助數據層對象完成菜單數據的查詢。後續還能夠基於AOP對數據進行緩存,記錄訪問日誌等。

package com.cy.pj.sys.servive;
import com.cy.pj.common.pojo.Node;
import com.cy.pj.sys.pojo.SysMenu;
import com.cy.pj.sys.pojo.SysUserMenu;
import java.util.List;
import java.util.Map;
public interface SysMenuService {
    List<SysUserMenu> findUserMenusByUserId(Integer id);
    int updateObject(SysMenu entity);
    int saveObject(SysMenu entity);
    List<Node> findZtreeMenuNodes();
    int deleteObject(Integer id);
    List<Map<String,Object>> findObjects();
}

第四步:建立SysMenuServiceImpl實現類

package com.cy.pj.sys.servive.impl;
import com.cy.pj.common.exception.ServiceException;
import com.cy.pj.common.pojo.Node;
import com.cy.pj.sys.dao.SysUserRoleDao;
import com.cy.pj.sys.pojo.SysMenu;
import com.cy.pj.sys.dao.SysMenuDao;
import com.cy.pj.sys.dao.SysRoleMenuDao;
import com.cy.pj.sys.pojo.SysUserMenu;
import com.cy.pj.sys.servive.SysMenuService;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;
@Service
public class SysMenuServiceImpl implements SysMenuService {
    @Autowired
    private SysMenuDao sysMenuDao;
    @Autowired
    private SysRoleMenuDao sysRoleMenuDao;
    @Autowired
    private SysUserRoleDao sysUserRoleDao;
    @Override
    public List<SysUserMenu> findUserMenusByUserId(Integer id) {
        //1.對用戶id進行判斷
        //2.基於用戶id查找用戶對應的角色id
        List<Integer> roleIds=
                sysUserRoleDao.findRoleIdsByUserId(id);
        //3.基於角色id獲取角色對應的菜單信息,並進行封裝.
        List<Integer> menuIds=
                sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
        //4.基於菜單id獲取用戶對應的菜單信息並返回
        return sysMenuDao.findMenusByIds(menuIds);
    }
    @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;
    }
    @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;
    }
    @Override
    public List<Node> findZtreeMenuNodes() {
        return sysMenuDao.findZtreeMenuNodes();
    }
    @Override
    public int deleteObject(Integer id) {
        //1,參數校驗
        if(id==null||id<1)
            throw new IllegalArgumentException("id值無效");
        //2,斷定菜單是否有子菜單,有則不容許刪除
        int childCount=sysMenuDao.getChildCount(id);
        if(childCount>0)
            throw new ServiceException("請先刪除子菜單");
        //3,刪除關係數據
        sysRoleMenuDao.deleteObjectsByMenuId(id);
        int rows=sysMenuDao.deleteObject(id);
        //4,刪除自身信息
        if(rows==0)
            throw new ServiceException("記錄可能已經不存在");
        return rows;
    }
    @Override
    public List<Map<String, Object>> findObjects() {
        return sysMenuDao.findObjects();
    }
}

第五步:建立SysMenuController控制層

控制層對象主要負責請求和響應數據的處理,例如,本模塊經過業務層對象執行業務邏輯,再經過VO對象封裝響應結果(主要對業務層數據添加狀態信息),最後將響應結果轉換爲JSON格式的字符串響應到客戶端。

package com.cy.pj.sys.controller;
import com.cy.pj.common.pojo.JsonResult;
import com.cy.pj.sys.pojo.SysMenu;
import com.cy.pj.sys.servive.SysMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SysMenuController {
    @Autowired
    private SysMenuService sysMenuService;
    @RequestMapping("/menu/doUpdateObject")
    public JsonResult doUpdateObject(SysMenu entity){
        sysMenuService.updateObject(entity);
        return new JsonResult("update ok");
    }
    @RequestMapping("/menu/doSaveObject")
    public JsonResult doSaveObject(SysMenu entity){
        sysMenuService.saveObject(entity);
        return new JsonResult("save ok");
    }
    @RequestMapping("/menu/doFindZtreeMenuNodes")
    public JsonResult doFindZtreeMenuNodes(){
        return new JsonResult(
                sysMenuService.findZtreeMenuNodes());
    }
    @RequestMapping("/menu/doDeleteObject")
    public JsonResult doDeleteObject(Integer id){
        sysMenuService.deleteObject(id);
        return new JsonResult("delete ok");
    }
    @GetMapping("menu/doFindObjects")
    public JsonResult doFindObjects(){
        return new JsonResult(sysMenuService.findObjects());
    }
}

第六步:建立SysRoleMenuDao接口

package com.cy.pj.sys.dao;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface SysRoleMenuDao {
    List<Integer> findMenuIdsByRoleIds(
            @Param("roleIds")List<Integer> roleIds);
    int insertObjects(
            @Param("roleId")Integer roleId,
            @Param("menuIds")Integer[] menuIds);
    @Delete("delete from sys_role_menus where role_id=#{roleId}")
    int deleteObjectsByRoleId(Integer roleId);
    //基於菜單id執行關係
 @Delete("delete from sys_role_menus where menu_id=#{menuId}")
    int deleteObjectsByMenuId(Integer menuId);
}

第七步:建立SysRoleMenuMapper.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.SysRoleMenuDao">
    <select id="findMenuIdsByRoleIds"
 resultType="int">
        select menu_id
        from sys_role_menus
        where role_id in
        <foreach collection="roleIds"
 open="("
 close=")"
 separator=","
 item="item">
            #{item}
        </foreach>
    </select>
    <select id="findMenuIdsByRoleId"
 resultType="int">
            select menu_id
            from sys_role_menus
            where role_id=#{id}
    </select>
    <insert id="insertObjects">
        insert into sys_role_menus
        (role_id,menu_id)
        values
        <foreach collection="menuIds"
 separator=","
 item="menuId">
            (#{roleId},#{menuId})
        </foreach>
    </insert>
</mapper>

第八步:建立Node 類
定義值對象封裝查詢到的上級菜單id,name,parentId信息。

package com.cy.pj.common.pojo;
import lombok.Data;
import java.io.Serializable;
@Data
public class Node implements Serializable {
    private static final long serialVersionUID = -7022202313802285223L;
    private Integer id;
    private String name;
    private Integer parentId;
}

第九步:建立SysMenu 類
定義持久化對象,封裝客戶端請求數據,並將數據傳遞到數據層進行持久化。

package com.cy.pj.sys.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class SysMenu implements Serializable {
    private static final long serialVersionUID = -1086340530112865421L;
    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;
}

3.2 客戶端頁面呈現

menu_list.html

<div class="row">
   <div class="col-xs-12">
      <div class="box">
         <div class="box-header">
            <h3 class="box-title">
            
            菜單管理</h3>
            <div class="box-tools">
               <div class="input-group input-group-sm" style="width: 100px;">
                  <div class="input-group-btn">
                  
                     <button type="button" 
class="btn btn-success btn-delete">
                     刪除</button>
                     <button type="button" class="btn btn-default btn-add">添加</button>
                     <button type="button" class="btn btn-default btn-update">修改</button>
                  </div>
               </div>
            </div>
         </div>
         <!-- /.box-header -->
 <div class="box-body table-responsive no-padding">
          <table id="menuTable" class="table table-hover">
           <thead>
           <tr>
            <th data-field="selectItem" data-checkbox="true"></th>
           </tr>
          </thead>
          
         </table>
        </div>
      </div>
      <!-- /.box -->
 </div>
</div>
<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>
<script type="text/javascript">
/**
 * 初始化表格的列
 */
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();
   $(".input-group-btn")
   .on("click",".btn-delete",doDeleteObject)
    .on("click",".btn-add,.btn-update",doLoadEditUI);
})
function doLoadEditUI(){
   var title;
   //基於點擊對象的class屬性值,修改標題
 if($(this).hasClass("btn-add")){
      title="添加菜單";
   }else{
      title="修改菜單";
      var item=doGetCheckedItem();
      if(!item){
         alert("請先選擇");
         return;
      }
      $("#mainContentId")
      .data("rowData",item);
   }
   //異步加載編輯頁面
 var url="menu/menu_edit";
   $("#mainContentId").load(url,function(){
      $(".box-title").html(title);
   })
}
function doGetCheckedItem(){
   return $("tbody input[type='radio']:checked")
   .parents("tr").data("rowData");
}
function doGetCheckedId(){
   //方法1:
 //var radio=$("tbody input[type='radio']:checked"); //if(radio)return radio.val(); //方法2:
 //1.獲取選中的記錄
 var selections=$("#menuTable")
   //bootstrapTreeTable是treeGrid插件內部定義的jquery擴展函數
 //getSelections爲擴展函數內部要調用的一個方法
 .bootstrapTreeTable("getSelections");
   //2.對記錄進行斷定
 if(selections.length==1)
   return selections[0].id;
}
function doDeleteObject(){
  //1.獲取選中記錄的id值
 var id=doGetCheckedId();
  console.log("id="+id);
  if(!id){
     alert("請先選中");
     return;
  }
  //2.給出提示是否確認刪除
 if(!confirm("確認刪除嗎"))return;
  //3.發送異步請求執行刪除操做
 //3.1定義請求參數
 var params={"id":id};
  //3.2定義請求url
 var url="menu/doDeleteObject";
  //3.3發送異步請求
 $.post(url,params,function(result){
     if(result.state==1){
        alert(result.message);
        $("tbody input[type='radio']:checked")
        .parents("tr").remove();
     }else{
        alert(result.message);
     }
  })
}
function doGetObjects(){
   //移除mainContentId位置的數據
 $("#mainContentId").removeData();
   var treeTable=new TreeTable(
            "menuTable",//tableId
 "menu/doFindObjects",//url
 columns);//表中列的配置
 //treeTable.setExpandColumn(2);
 //作表格初始化
 treeTable.init();  //發起ajax請求(藉助ajax函數)
  }

菜單列表頁面(/templates/pages/sys/menu_edit.html)

<!-- Horizontal Form -->
 <div class="box box-info">
      <div class="box-header with-border">
        <h3 class="box-title">添加菜單</h3>
      </div>
      <!-- /.box-header -->
 <!-- form start --> <form class="form-horizontal">
        <div class="box-body">
          <div class="form-group">
            <label for="nameId" class="col-sm-2 control-label">類型</label>
            <div class="col-sm-10 typeRadio">
               <label class="radio-inline">
            <input type="radio" name="typeId" value="1" checked> 菜單 </label>
            <label class="radio-inline">
            <input type="radio" name="typeId" value="2"> 按鈕 </label>
            </div>
          </div>
          <div class="form-group">
            <label for="nameId" class="col-sm-2 control-label">菜單名稱</label>
            <div class="col-sm-10">
              <input type="text" class="form-control" id="nameId" placeholder="名稱">
            </div>
          </div>
          <div class="form-group">
            <label for="parentId" class="col-sm-2 control-label">上級菜單</label>
            <div class="col-sm-10">
              <input type="text" class="form-control load-sys-menu" readonly="readonly" id="parentId" placeholder="上級菜單">
            </div>
          </div>
          <div class="form-group">
            <label for="urlId" class="col-sm-2 control-label">菜單URL</label>
            <div class="col-sm-10">
              <input type="text" class="form-control" id="urlId" placeholder="url">
            </div>
          </div>
          <div class="form-group">
         <label for="permissionId" class="col-sm-2 control-label">受權標識:</label>
         <div class="col-sm-10">
            <input type="text" id="permissionId"
 placeholder="多個用逗號分隔,如:user:list,user:create"
 class="form-control">
         </div>
        </div>
        <div class="form-group">
            <label for="sortId" class="col-sm-2 control-label">排序號:</label>
            <div class="col-sm-10">
               <input type="text" id="sortId" placeholder="排序號"
 class="form-control">
            </div>
       </div>
        </div>
        <!-- /.box-body -->
 <div class="box-footer">
          <button type="button" class="btn btn-default btn-cancel">Cancel</button>
          <button type="button" class="btn btn-info pull-right btn-save">Save</button>
        </div>
        <!-- /.box-footer -->
 </form>
      <!-- zTree 對應的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>
  </div>
  <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>
  <script type="text/javascript">
  
  var zTree; //zTree是第三方擴展的一個Jquery插件
 //初始化zTree時會用到
 var setting = {
   data : {
      simpleData : {
         enable : true,//表示使用簡單數據模式
 idKey : "id",  //節點數據中保存惟一標識的屬性名稱
 pIdKey : "parentId",  //節點數據中保存其父節點惟一標識的屬性名稱
 rootPId : null //根節點id
 }//json 格式javascript對象
 }
  }//json 格式的javascript對象
 $(function(){
     $(".form-horizontal")//事件不能註冊到$("#mainContentId")對象上
 .on("click",".load-sys-menu",doLoadZtreeNodes);
     
     $("#menuLayer")
      .on("click",".btn-confirm",doSetSelectNode)
      .on("click",".btn-cancel",doHideTree);
     
     $(".box-footer")
     .on("click",".btn-cancel",doCancel)
     .on("click",".btn-save",doSaveOrUpdate)
     
     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);
  }
  //獲取表單數據
 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;
  }
  function doSaveOrUpdate(){
     //1.獲取表單數據
 var params=doGetEditFormData();
      var rowData=
      $("#mainContentId").data("rowData");
     //2.異步提交表單數據(post)
 var insertUrl="menu/doSaveObject";
      var updateUrl="menu/doUpdateObject";
      var url=rowData?updateUrl:insertUrl;
      if(rowData)params.id=rowData.id;
      $.post(url,params,function(result){
           if(result.state==1){
              alert(result.message);
              doCancel();
           }else{
              alert(result.message);
           }
     });
  }
  //編輯頁面cancel事件處理
 function doCancel(){
     //1.定義url
 var url="menu/menu_list";
     //2.異步加載列表頁面
 $("#mainContentId").load(url);
  }
  
  //zTree取消按鈕事件處理函數
 function doHideTree(){
       $("#menuLayer").css("display","none");
  }
  //zTree肯定按鈕事件處理函數
 function doSetSelectNode(){
     //1.獲取選中的節點對象
 var nodes=zTree.getSelectedNodes();
     if(nodes.length==1){   
       var selectedNode=nodes[0];
       console.log("selectNode",selectedNode);
       var rowData=$("#mainContentId").data("rowData");
       if(rowData){//修改時作以下處理
 //斷定當前選中的上級菜單節點是否爲當前要修改節點的子節點.
 var flag=isChild(rowData.id,selectedNode);
         if(flag){
            alert("不能選擇當前節點以及對應子節點");
            return;
         }
       }
     //2.將對象中內容,填充到表單
 $("#parentId").data("parentId",selectedNode.id);
      $("#parentId").val(selectedNode.name);
      }
     //3.隱藏樹對象
 doHideTree();
  }
  //斷定當前選中節點是不是當前節點的子節點
 function isChild(currentNodeId,selectNode){
    if(selectNode.id==currentNodeId)return true;
    var node=selectNode.getParentNode();
    if(!node)return false;
    return isChild(currentNodeId,node);
  }
  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);//id,name,parentId
 //doRemoveNodeFromZtree();//修改時,可考慮此方案
 //顯示zTree對應的div
 $("#menuLayer").css("display","block");
        }else{
           alert(result.message);
        }
     })
  }
  function doRemoveNodeFromZtree(){
     //斷定是不是修改,假如是修改,從zTree中移除當前菜單以及對應子菜單
 var rowData=$("#mainContentId").data("rowData");
      if(rowData){//rowData有值,表示是修改.
 console.log("zTree",zTree);
        //1.獲取當前的菜單對象
 var node=zTree.getNodeByParam("id",rowData.id,null);
        console.log("node",node);
        //2.移除當前菜單.
 zTree.removeNode(node);
      }
  }
 </script>
相關文章
相關標籤/搜索