动吧项目(权限管理子系统)学习-菜单管理

1. 页面数据呈现

1.1 设计说明

菜单管理又称为资源管理,是系统资源对外的表现形式。本模块主要是实现对菜
单进行添加、修改、查询、删除等操作

1.1.1 数据库说明

在这里插入图片描述

1.1.2 多表关系结构图

在这里插入图片描述
在这里插入图片描述

1.2 原型设计图

1.2.1 首页

在这里插入图片描述

1.2.1 添加页面

在这里插入图片描述

1.2.2 编辑页面

在这里插入图片描述

1.3 服务端实现

1.3.1 时序图分析

在这里插入图片描述

1.3.2 编辑PageController

在这里插入图片描述

@Controller
public class PageController {
	/*
		//该代码通用性不够强
        @GetMapping("/menu/menu_list")
	    public String doMenuUI(){
	       return "sys/menu_list";
	    }
	*/
    //通过rest风格的url处理客户端的ui请求
    @GetMapping("/{module}/{moduleUI}")
    public String doModuleUI(@PathVariable String moduleUI){
        return "sys/"+moduleUI;
    }

1.3.3 在start.html上编辑点击事件

说明:点击菜单按钮,回显menu_list页面的跳转

<script type="text/javascript">
   $(function(){//jQuery中的函数,在页面加载完成之后执行
        doLoadUI("load-menu-id", "/menu/menu_list");
    })
    //实现共性代码封装
    function doLoadUI(id,url){//创建点击事件
      $("#"+id).click(function(){
        //mainContentId指具体页面位置进行异步加载url对应的资源
        $("mainContentId").load(url);
      })
    }
</script>

1.3.4 点击页面实现的效果展示

在这里插入图片描述

1.4 菜单列表页面实现

1.4.1 时序图

在这里插入图片描述

1.4.2 编辑数据层(SysMenuDao)

在这里插入图片描述

package cn.tedu.dbadmin.dao;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;
@Mapper
public interface SysMenuDao {
    List<Map<String, Object>> findObjects();
}

1.4.3 在Mapper.xml文件中编辑sql语句

在这里插入图片描述

<?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="cn.tedu.dbadmin.dao.SysMenuDao">
    <!--嵌套查询-->
    <select id="findObjects" resultType="map">
        select c.*,(select name from sys_menus p where c.parentId = p.id) parenName
        from sys_menus c
    </select>
    <!--表关联查询-->
    <!--<select id="findObjects">
        select c.*, p.name parentName
        from sys_menus c left join sys_menus p on c.parentId = p.id
    </select>-->
</mapper>

1.4.4 编辑业务层接口以及实现类(SysMenuServiceImpl)

在这里插入图片描述

package cn.tedu.dbadmin.service;


import java.util.List;
import java.util.Map;
public interface SysMenuService {
    List<Map<String, Object>> findObjects();
}

package cn.tedu.dbadmin.service;

import cn.tedu.dbadmin.dao.SysMenuDao;
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;

    @Override
    public List<Map<String, Object>> findObjects() {
        return  sysMenuDao.findObjects();
    }
}

1.4.5 编辑控制层(Controller)

在这里插入图片描述

@RestController
public class SysMenuController {
    @Autowired
    private SysMenuService sysMenuService;
    @GetMapping("/menu/doFindObjects")
    public JsonResult doFindObjects() throws InterruptedException {
        return new JsonResult(sysMenuService.findObjects());
    }
}

1.4.6 页面数据呈现

在这里插入图片描述

1.5 实现JQuery中treeGrid

1.5.1 创建web项目,编辑menu-01.html,实现简单跨域访问

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <div class="container">
  <h1>The Menu Page</h1>
  <table class="table">
      <thead>
        <tr>
            <th>id</th>
            <th>name</th>
            <th>parentName</th>
        </tr>
      </thead>
      <tbody>
          <tr><td colspan="3">Data is loading ....</td></tr>
      </tbody>
  </table>
  </div>
  <script src="/js/jquery.min.js"></script>
  <script>
      $(()=>{
          doFindObjects();
      })
      function doFindObjects(){
         let url="http://localhost/menu/doFindObjects";
         $.get(url,(result)=>{
             debugger
             //console.log(result);
             doHandleQueryResult(result);
         })
      }
      function doHandleQueryResult(result){//JsonResult
          if(result.state==1){
              doSetTableBodyRows(result.data)
          }else{
              alert(result.message);
          }
      }
      function doSetTableBodyRows(menus){
          //获取tbody对象
          let tBody=$("tbody");
          //清空tbody中原有内容
          tBody.empty();
          //将服务端返回的结果更新到页面上
          //方法1:
          // for(let i=0;i<menus.length;i++) {
          //     tBody.append(menus[i]);
          // }
          //方法2
          // menus.forEach(function(item){
          //     tBody.doCreateRow(item)
          // })
          //方法3
          menus.forEach((item)=>{ //箭头函数
              tBody.append(doCreateRow(item));
          })
      }
      function doCreateRow(row){
         return  `<tr>
                  <td>${row.id}</td>
                  <td>${row.name}</td>
                  <td>${row.parentName}</td>
               </tr>`
      }
  </script>

</body>
</html>

在这里插入图片描述

1.5.2 引入libs相关js文件

在这里插入图片描述

1.5.3 编辑menu-treegrid.html

  • 使用Bootstrap
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <!-- Bootstrap -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" rel="stylesheet">
    <!-- 引入CSS/JS -->
    <link href="/libs/treegrid/jquery.treegrid.css" rel="stylesheet">
</head>
<body>
  <div class="container">
  <h1>The Menu Page</h1>
      <table id="menuTable" class="table table-hover">
          <thead>
          <tr>
              <th data-field="selectItem" data-checkbox="true"></th>
          </tr>
         </thead>
      </table>
  </div>
  <script src="/js/jquery.min.js"></script>
  <script type="text/javascript" src="/libs/treegrid/jquery.treegrid.extension.js"></script>
  <script type="text/javascript" src="/libs/treegrid/jquery.treegrid.min.js"></script>
  <script type="text/javascript" src="/libs/treegrid/tree.table.js"></script>

  <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(){
          doFindObjects();
      })
      function doFindObjects(){
          let url="http://localhost/menu/doFindObjects";
          //构建treeTable对象(第一个参数是用于显示结果的table,第三个参数为列标题)
          let treeTable=new TreeTable("menuTable",url,columns);
          //初始化treeTable对象
          treeTable.init();//底层发送ajax请求
      }
  </script>
</body>
</html>

在这里插入图片描述

2. 删除操作实现

2.1 业务说明

基于用户在列表页面上选择的的菜单记录 ID,执行删除操作,本次删除业务实现中,首先
要基于 id 判断当前菜单是否有子菜单,假如有子菜单则不允许删除,没有则先删除菜单角
色关系数据,然后再删除菜单自身信息。

2.2 时序图

在这里插入图片描述

2.3 实现过程

2.3.1 编辑SysRoleMenuDao

package cn.tedu.dbadmin.dao;

import org.apache.ibatis.annotations.Mapper;

@Mapper
public interface SysRoleMenuDao {
    //基于菜单id删除角色菜单关系
    int deleteObjectsByMenuId(Integer id);
}

2.3.2 编辑SysMenuDao

package cn.tedu.dbadmin.dao;

import org.apache.ibatis.annotations.Mapper;

import java.util.List;
import java.util.Map;
@Mapper
public interface SysMenuDao {
    List<Map<String, Object>> findObjects();

    //根据菜单查询子菜单数量
    int getChildCount(Integer id);
    //基于菜单id删除菜单
    int deleteObject(Integer id);
}

2.3.3 编辑SysRoleMenuMapper

<?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="cn.tedu.dbadmin.dao.SysRoleMenuDao">
    <delete id="deleteObjectsByMenuId">
        delete from sys_role_menus
        where #{id} = menu_id
    </delete>
</mapper>

2.3.4 编辑SysMenuMapper

    <select id="getChildCount" resultType="int">
        select count(*) from sys_menus
        where parentId = #{id};
    </select>

    <delete id="deleteObject">
        delete from sys_menus
        where id = #{id};
    </delete>

2.3.5 编辑业务接口和实现类

package cn.tedu.dbadmin.service;


import java.util.List;
import java.util.Map;
public interface SysMenuService {
    List<Map<String, Object>> findObjects();

    int deleteObject(Integer id);
}

package cn.tedu.dbadmin.service;

import cn.tedu.dbadmin.dao.SysMenuDao;
import cn.tedu.dbadmin.dao.SysRoleMenuDao;
import cn.tedu.dbcommon.exception.ServiceException;
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;

    @Override
    public List<Map<String, Object>> findObjects() {
//        List<Map<String, Object>> list = sysMenuDao.findObjects();
//        return list;
        return sysMenuDao.findObjects();
    }

    @Override
    public int deleteObject(Integer id) {
        if(id == null || id < 1){
            throw new IllegalArgumentException("请先选择");
        }
        //查询子菜单数量
        int rows = sysMenuDao.getChildCount(id);
        if(rows > 1){
            throw new ServiceException("请先删除子菜单");
        }
        //删除角色菜单关系
        sysRoleMenuDao.deleteObjectsByMenuId(id);
        //删除菜单
        int row = sysMenuDao.deleteObject(id);

        return row;
    }
}

2.3.5 编辑SysMenuController

package cn.tedu.dbadmin.controller;

import cn.tedu.dbadmin.service.SysMenuService;
import cn.tedu.dbcommon.pojo.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequestMapping("/menu/")
@RestController
public class SysMenuController {

    @Autowired
    private SysMenuService sysMenuService;

    @RequestMapping("doFindObjects")
    public JsonResult doFindObjects(){
        return new JsonResult(sysMenuService.findObjects());

    }

    @RequestMapping("doDeleteObject")
    public JsonResult doDeleteObject(Integer id){
        sysMenuService.deleteObject(id);
        return new JsonResult("删除成功");
    }
}

3. 添加操作实现

3.1 上级菜单数据加载以及实现

在这里插入图片描述

3.1.1 定义pojo对象封装查询到的菜单信息

在这里插入图片描述

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;
}

3.1.2 编辑SysMenuDao

@Select("select id,name,parentId from sys_menus")
       public List<Node> findZtreeMenuNodes();

3.1.3 编辑SysMenuServiceImpl

public List<Node> findZtreeMenuNodes(){
        return sysMenuDao.findZtreeMenuNodes();
    }

3.1.4 编辑SysMenuController

@GetMapping("/menu/doFindZtreeMenuNodes")
    public JsonResult doFindZtreeMenuNodes(){
        return new JsonResult(sysMenuService.findZtreeMenuNodes());
    }

3.2 客户端树结构呈现shou

3.2.1 框架来源

在这里插入图片描述

3.2.2 在web项目中创建menu-ztree.html

说明: 实现树结构菜单的页面呈现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/libs/ztree/css/zTreeStyle/zTreeStyle.css" type="text/css">
</head>
<body>
<!--定义用于显示树结构的div-->
<div>
    <ul id="zTreeId" class="ztree"></ul>
</div>
<!--引入ztree需要的js-->
<script src="/js/jquery.min.js"></script>
<script src="/libs/ztree/jquery.ztree.all.min.js"></script>
<script>
    //定义ztree的简易配置
    var setting = {
        data: {
            simpleData: {
                enable: true,
                idKey: "id", //此id对应服务端返回的数据中的id
                pIdKey: "parentId",
                rootPId: 0
            }
        }
    };//尊重规则
    var url="http://localhost/menu/doFindZtreeMenuNodes";
    //向服务端发送ajax请求,将响应结果更新到页面上(以ztree结构进行呈现)
    $.get(url,function(result){//jsonresult
        //初始化zTree对象(参考官方-treejs.cn)-固定写法
        $.fn.zTree.init($("#zTreeId"),setting,result.data);
    })
</script>
</body>
</html>

3.2.3 页面呈现效果

在这里插入图片描述

3.3 添加操作具体实现

3.3.1 时序图

在这里插入图片描述

3.3.2 定义SysMenu的pojo类封装添加数据

在这里插入图片描述

package cn.tedu.dbcommon.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class SysMenu implements Serializable {
    private static final long serialVersionUID = 8049305945150183138L;

    private Integer id;//菜单id
    private String name;//菜单名称
    private String url;//菜单URL
    private Integer type = 1;
    private Integer sort;//菜单序号
    private String note;//菜单备注
    private Integer parentId;//上级菜单id
    private String permission;//授权标识
    private String createdUser;//创建用户
    private String modifiedUser;//修改用户
    private Date createdTime;//创建时间
    private Date modifiedTime;//修改时间

}

3.3.3 编辑SysMenuDao

int insertObject(SysMenu menu);

3.3.4 编辑SysMenuMapper

<insert id="insertObject">
        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>

3.3.5 编辑SysMenuService

int saveObject(SysMenu entity);

3.3.6 编辑SysMenuServiceImpl

@Override
    public int saveObject(SysMenu entity) {
        if(entity==null)
            throw new IllegalArgumentException("保存对象不能为空");
        if(entity.getName()==null||"".equals(entity.getName()))
            throw new IllegalArgumentException("菜单名不允许为空");
        //........
        int rows=sysMenuDao.insertObject(entity);
        return rows;
    }

3.3.7 编辑SysMenuController

@PostMapping("/menu/doSaveObject")
    public JsonResult doSaveObject(SysMenu entity){
        sysMenuService.saveObject(entity);
        return new JsonResult("save ok");
    }

3.3.7 实现效果图

在这里插入图片描述

4. 修改操作实现

4.1 时序图

在这里插入图片描述

4.2 点击修改实现页面数据呈现

在这里插入图片描述
在这里插入图片描述

4.3 修改操作实现

4.3.1 SysMenuDao

int updateObject(SysMenu menu);

4.3.2 SysMenuMapper

<update id="updateObject">
update sys_menus
 set
 name=#{name},
 type=#{type},
 sort=#{sort},
 url=#{url},
 parentId=#{parentId},
 permission=#{permission},
 modifiedUser=#{modifiedUser},
 modifiedTime=now()
 where id=#{id}
      </update>

4.3.3 SysMenuService

int updateObject(SysMenu entity);

4.3.4 SysMenuServiceImpl

 @Override
    public int updateObject(SysMenu entity) {
        if(entity==null)
            throw new IllegalArgumentException("保存对象不能为空");
        if(entity.getName()==null||"".equals(entity.getName()))
            throw new IllegalArgumentException("菜单名不允许为空");
        //........
        int rows=sysMenuDao.updateObject(entity);
        return rows;
    }

4.3.5 SysMenuController

@PostMapping("/menu/doUpdateObject")
    public JsonResult doUpateObject(SysMenu entity){
        sysMenuService.updateObject(entity);
        return new JsonResult("update ok");
    }

5. Bug总结

在这里插入图片描述

  • 根据日志提示,在红色框内添加返回结果类型:
    在这里插入图片描述
  • 查看POJO类JsonResult对象是否没有添加@Data注解,即没有get/set/toString方法
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Solider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值