汽车租赁系统(4)-菜单管理开发第一部分查询的实现


前文推荐
汽车租赁系统的介绍和项目搭建(1)
JavaSSM框架学完,手写一个汽车租赁系统,真NE!
汽车租赁系统(2)-完成登录功能
汽车租赁系统(3)-工作台开发和菜单树的加载

菜单管理

特别提醒:只展示部分比较重要的代码,部分代码省略

菜单管理功能演示

用动图演示一下,菜单管理的主要功能:

在这里插入图片描述

我们在动图中主要演示了下列的功能:

  1. 首先在左侧要加载一颗菜单树(有组织的)
  2. 右侧希望在点击进来时直接显示所有的菜单信息,并提供模糊查询的功能
  3. 具有菜单添加,修改,删除的功能.且要求点击左侧菜单树也能实现显示该菜单下的所有菜单

菜单管理分析:

image-20200716080326933

分析:

  1. 菜单管理页面被分为两部分,左边一部分是菜单的导航树,右边的是菜单相关详细信息的表格和模糊查询的实现
  2. 根据这样的布局,决定使用framset的布局方式

接下来菜单管理一般步骤的开发

  1. 生成Menu实体类
  2. 生成MenuMapper
  3. 生成MenuMapper
  4. 创建MenuVo
  5. 创建MenuService
  6. 创建MenuServiceImpl
  7. 创建MenuController

查询

查询分为两部分:

  1. 根据查询结果构建左侧菜单树
  2. 显示查询结果到表格中

一.菜单页面布局的实现

创建一个MenuManager,jsp实现页面的布局,将页面分为左边加载菜单的MenuManagerLeft.jsp和MenuManagerRight.jsp.

  • 注意使用framset的布局方式,那么在其中不能再出现body标签

MenuManager.jsp

<%--
  Created by IntelliJ IDEA.
  User: YLJ
  Date: 2020年7月8日
  Time: 16:43:20
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <title>菜单管理</title>
</head>

<%--如果使用frameset 包含页面 主页面不能有body--%>
<frameset cols="230,*" border="1">
    <frame src="${leiyujia}/sys/toMenuLeft.action" name="left">
    <frame src="${leiyujia}/sys/toMenuRight.action" name="right">
</frameset>

</html>

二.实现左侧菜单树

1.创建页面

MenuManagerLeft.jsp

<%--
  Created by IntelliJ IDEA.
  User: LYJ
  Date: 2020年7月8日
  Time: 16:42:48
  To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="utf-8">
    <title>菜单树</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <link rel="icon" href="favicon.ico">
    <link rel="stylesheet" href="${leiyujia}/static/layui/css/layui.css" media="all"/>
    <link rel="stylesheet" href="${leiyujia}/static/css/public.css" media="all"/>
    <link rel="stylesheet" href="${leiyujia}/static/layui_ext/dtree/dtree.css">
    <link rel="stylesheet" href="${leiyujia}/static/layui_ext/dtree/font/dtreefont.css">
</head>
<body class="main_body">

    <ul id="menuTree" class="dtree" data-id="0"></ul>

    <script type="text/javascript" src="${leiyujia}/static/layui/layui.js"></script>
    <script type="text/javascript">
        var menuTree;
        layui.extend({
            dtree: '${leiyujia}/static/layui_ext/dist/dtree'
        }).use(['jquery', 'layer', 'form', 'dtree'], function () {
            var $ = layui.jquery;
            var layer = layui.layer;
            var form = layui.form;
            var dtree = layui.dtree;

            // 初始化树
            menuTree = dtree.render({
                elem: "#menuTree",
                dataStyle: "layuiStyle",  //使用layui风格的数据格式
                response: {message: "msg", statusCode: 0},  //修改response中返回数据的定义
                dataFormat: "list",  //配置data的风格为list
                url: "${leiyujia}/menu/loadMenuManagerLeftTreeJson.action?spread=1" // 使用url加载(可与data加载同时存在)
            });

            //监听树的节点点击 事件
            dtree.on("node('menuTree')", function (obj) {
                var id = obj.param.nodeId;
                window.parent.right.reloadTable(id);
            });
        });
    </script>
</body>
</html>

注意使用的是LayUI的dtree+list风格的树型组件

其要求的json的数据格式是

image-20200716082419645

可以看出在layUI中要求的数据结构比较简单,便于我们根据数据库的数据区组装它的结果,所以我们决定用它.

2.修改MenuController

我们需要给前端返回一个LayUI+list的json数据格式,这同样不是一个简单的json数据格式,是一个标准的数据格式

  • json数据格式
  • json数据中data的数据格式如何实现

    /**
     * 加载菜单左边的菜单树
     * @param menuVo
     * @return
     */
    @RequestMapping("loadMenuManagerLeftTreeJson")
    public DataGridView loadMenuManagerLeftTreeJson(MenuVo menuVo){
        menuVo.setAvailable(SysConstast.AVAILABLE_TRUE);//只查询可用的
        List<Menu> list = this.menuService.queryAllMenuForList(menuVo);
        List<TreeNode> nodes = new ArrayList<>();
        //把list里面的数据放到nodes
        for (Menu menu : list){
            Integer id = menu.getId();
            Integer pid = menu.getPid();
            String title = menu.getTitle();
            String icon = menu.getIcon();
            String href = menu.getHref();
            Boolean spread = menu.getSpread()==SysConstast.SPREAD_TRUE?true:false;
            String target = menu.getTarget();
            nodes.add(new TreeNode(id,pid,title,icon,href,spread,target));
        }
        return new DataGridView(nodes);
    }

  • 我们在Controller中对查询到的菜单数据进行封装,用之前博客中讲到的封装树型结构的treeNode的工具类,相当于封装了data中的数据格式

  • 还有外层的json数据的格式,我们需要再新建一个工具类来封装

DataGridView工具类

用于将数据包装成要求的json的数据格式

实现细节:

package per.leiyu.sys.utils;

/**
 * @author lleiyujia
 */
public class DataGridView {
    /**
     * 封装LayUI数据表格的数据对象
     */
    private Integer code=0;
    private String msg="";
    private Long count;
    private Object data;

    public DataGridView() {
    }

    public DataGridView(Object data) {
        super();
        this.data = data;
    }

    public DataGridView(Long count, Object data) {
        super();
        this.count = count;
        this.data = data;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public Long getCount() {
        return count;
    }

    public void setCount(Long count) {
        this.count = count;
    }

    public Object getData() {
        return data;
    }

    public void setData(Object data) {
        this.data = data;
    }
}

  1. code和meg属性我们都可以是设置为默认的
  2. 另外为了分页是可以显示到总条数我们还可以为其封装一个count属性

注意:封装前端所需要的json数据时,可以比简短需要数据格式的属性多,但是不能缺少其中的属性

  1. 只需要将实际前端需要的json数据封装为Object形式,然后在对Object数据再进行内部的封装就可以了

3.开发关于查询菜单信息的Service类和其实现类

MenuService

    /**
     * 查询所有菜单返回
     * @param menuVo
     * @return
     */
    @Override
    public List<Menu> queryAllMenuForList(MenuVo menuVo);

  • 注意返回值类型

MenuServiceImpl

   /**
     * 查询所有菜单返回
     * @param menuVo
     * @return
     */
    @Override
    public List<Menu> queryAllMenuForList(MenuVo menuVo) {
        return menuMapper.queryAllMenu(menuVo);
    }

菜单查询和菜单实体的创建这里就不做赘述

注意返回值类型

MenuServiceImpl

   /**
     * 查询所有菜单返回
     * @param menuVo
     * @return
     */
    @Override
    public List<Menu> queryAllMenuForList(MenuVo menuVo) {
        return menuMapper.queryAllMenu(menuVo);
    }

菜单查询和菜单实体的创建这里就不做赘述

三.显示查询到的数据在页面中的显示

1.创建显示页面MenuManagerRight.jsp

<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
    <meta charset="utf-8">
    <title>菜单管理</title>
    <meta name="renderer" content="webkit">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <meta http-equiv="Access-Control-Allow-Origin" content="*">
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
    <meta name="apple-mobile-web-app-status-bar-style" content="black">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="format-detection" content="telephone=no">
    <%--<link rel="icon" href="favicon.ico">--%>
    <link rel="stylesheet" href="${leiyujia}/static/layui/css/layui.css" media="all"/>
    <link rel="stylesheet" href="${leiyujia}/static/css/public.css" media="all"/>
    <link rel="stylesheet" href="${leiyujia}/static/layui_ext/dtree/dtree.css">
    <link rel="stylesheet" href="${leiyujia}/static/layui_ext/dtree/font/dtreefont.css">

    <style type="text/css">
        .select-test {
            position: absolute;
            max-height: 500px;
            height: 350px;
            overflow: auto;
            width: 100%;
            z-index: 123;
            display: none;
            border: 1px solid silver;
            top: 42px;
        }
        .layui-show {
            display: block !important;
        }
    </style>
</head>
<body class="childrenBody">

<!-- 搜索条件开始 -->
<fieldset class="layui-elem-field layui-field-title" style="margin-top: 20px;">
    <legend>查询条件</legend>
</fieldset>
<form class="layui-form" method="post" id="searchFrm">
    <div class="layui-form-item">
        <div class="layui-inline">
            <label class="layui-form-label">菜单名称:</label>
            <div class="layui-input-inline" style="padding: 5px">
                <input type="text" name="title" autocomplete="off" class="layui-input layui-input-inline"
                       placeholder="请输入菜单名称" style="height: 30px;border-radius: 10px">
            </div>
        </div>
        <div class="layui-inline">
            <button type="button"
                    class="layui-btn layui-btn-normal layui-icon layui-icon-search layui-btn-radius layui-btn-sm"
                    id="doSearch">查询
            </button>
            <button type="reset"
                    class="layui-btn layui-btn-warm layui-icon layui-icon-refresh layui-btn-radius layui-btn-sm">重置
            </button>
        </div>
    </div>
</form>

<!-- 数据表格开始 -->
<table class="layui-hide" id="menuTable" lay-filter="menuTable"></table>
<div style="display: none;" id="menuToolBar">
    <button type="button" class="layui-btn layui-btn-sm layui-btn-radius" lay-event="add">增加</button>
</div>
<div id="menuBar" style="display: none;">
    <a class="layui-btn layui-btn-xs layui-btn-radius" lay-event="edit">编辑</a>
    <a class="layui-btn layui-btn-danger layui-btn-xs layui-btn-radius" lay-event="del">删除</a>
</div>

<!-- 添加和修改的弹出层开始 -->
<div style="display: none;padding: 20px" id="saveOrUpdateDiv">
    <form class="layui-form" lay-filter="dataFrm" id="dataFrm">
        <div class="layui-form-item">
            <label class="layui-form-label">父级菜单:</label>
            <div class="layui-input-block">
                <div class="layui-unselect layui-form-select" id="pid_div">
                    <div class="layui-select-title">
                        <input type="hidden" name="pid" id="pid">
                        <input type="text" name="pid_str" id="pid_str" placeholder="请选择" lay-verify="required" readonly=""
                               class="layui-input layui-unselect">
                        <i class="layui-edge"></i>
                    </div>
                </div>
                <div class="layui-card select-test" id="menuSelectDiv">
                    <div class="layui-card-body">
                        <div id="toolbarDiv">
                            <ul id="menuTree" class="dtree" data-id="0" style="width: 100%;"></ul>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">菜单名称:</label>
            <div class="layui-input-block">
                <input type="hidden" name="id">
                <input type="text" name="title" placeholder="请输入菜单名称" lay-verify="required" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <label class="layui-form-label">菜单地址:</label>
            <div class="layui-input-block">
                <input type="text" name="href" placeholder="请输入菜单地址" autocomplete="off" class="layui-input">
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">菜单图标:</label>
                <div class="layui-input-inline">
                    <input type="text" name="icon" placeholder="请输入菜单图标" lay-verify="required" autocomplete="off"
                           class="layui-input">
                </div>
            </div>
            <div class="layui-inline">
                <label class="layui-form-label">TARGET:</label>
                <div class="layui-input-inline">
                    <input type="text" name="target" placeholder="请输入TRAGET" autocomplete="off" class="layui-input">
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-inline">
                <label class="layui-form-label">是否展开:</label>
                <div class="layui-input-inline">
                    <input type="radio" name="spread" value="1" title="展开">
                    <input type="radio" name="spread" value="0" title="不展开" checked="checked">
                </div>
            </div>
            <div class="layui-inline">
                <label class="layui-form-label">是否可用:</label>
                <div class="layui-input-inline">
                    <input type="radio" name="available" value="1" checked="checked" title="可用">
                    <input type="radio" name="available" value="0" title="不可用">
                </div>
            </div>
        </div>
        <div class="layui-form-item">
            <div class="layui-input-block" style="text-align: center;padding-right: 120px">
                <button type="button"
                        class="layui-btn layui-btn-normal layui-btn-md layui-icon layui-icon-release layui-btn-radius"
                        lay-filter="doSubmit" lay-submit="">提交
                </button>
                <button type="reset"
                        class="layui-btn layui-btn-warm layui-btn-md layui-icon layui-icon-refresh layui-btn-radius">重置
                </button>
            </div>
        </div>
    </form>
</div>

<script src="${leiyujia}/static/layui/layui.js"></script>
<script src="${leiyujia}/static/layui_ext/dist/dtree.js"></script>
<script type="text/javascript">
    var tableIns;
    layui.extend({
        dtree: '${leiyujia}/static/layui_ext/dist/dtree'
    }).use(['jquery', 'layer', 'form', 'table', 'dtree'], function () {
        var $ = layui.jquery;
        var layer = layui.layer;
        var form = layui.form;
        var table = layui.table;
        var dtree = layui.dtree;
        //渲染数据表格
        tableIns = table.render({
            elem: '#menuTable'   //渲染的目标对象
            , url: '${leiyujia}/menu/loadAllMenu.action' //数据接口
            , title: '用户数据表'//数据导出来的标题
            , toolbar: "#menuToolBar"   //表格的工具条
            , height: 'full-148'
            , cellMinWidth: 100 //设置列的最小默认宽度
            , page: true  //是否启用分页
            , cols: [[   //列表数据
                {type: 'checkbox', fixed: 'left'}
                , {field: 'id', title: 'ID', align: 'center', width: '50'}
                , {field: 'pid', title: '父节点ID', align: 'center', width: '90'}
                , {field: 'title', title: '菜单名称', align: 'center', width: '160'}
                , {field: 'href', title: '菜单地址', align: 'center', width: '225'}
                , {
                    field: 'spread', title: '是否展开', align: 'center', width: '90', templet: function (d) {
                        return d.spread == '1' ? '<font color=blue>展开</font>' : '<font color=red>不展开</font>';
                    }
                }
                , {field: 'target', title: 'TARGET', align: 'center', width: '90'}
                , {
                    field: 'icon', title: '菜单图标', align: 'center', width: '90', templet: function (d) {
                        return "<div class='layui-icon'>" + d.icon + "</div>";
                    }
                }
                , {
                    field: 'available', title: '是否可用', align: 'center', width: '90', templet: function (d) {
                        return d.available == '1' ? '<font color=blue>可用</font>' : '<font color=red>不可用</font>';
                    }
                }
                , {fixed: 'right', title: '操作', toolbar: '#menuBar', width: 120, align: 'center'}
            ]],
            done:function (data, curr, count) {
                //不是第一页时,如果当前返回的数据为0那么就返回上一页
                if(data.data.length==0&&curr!=1){
                    tableIns.reload({
                        page:{
                            curr:curr-1
                        }
                    })
                }
            }
        })
</script>
</body>
</html>

2.创建loadAllMenu的handler

    /**
     * 加载菜单列表返回DataGridView
     * @param menuVo
     * @return
     */
    @RequestMapping("loadAllMenu")
    public DataGridView loadAllMenu(MenuVo menuVo){
        return this.menuService.queryAllMenu(menuVo);
    }

3.创建Service和ServiceImpl

作用就是查询都所有的菜单的详细信息,并返回给Controller,注意返回数据的格式要求封装为LayUI的数据表格的格式

    /**
     * 查询所有菜单
     * @param menuVo
     * @return
     */
    public DataGridView queryAllMenu(MenuVo menuVo);
    /**
     * 查询所有菜单列表
     * @param menuVo
     * @return
     * 分页查询
     */
    @Override
    public DataGridView queryAllMenu(MenuVo menuVo) {
        Page<Object> page = PageHelper.startPage(menuVo.getPage(),menuVo.getLimit());
        List<Menu> data = this.menuMapper.queryAllMenu(menuVo);
        return new DataGridView(page.getTotal(),data);
    }

写Mapper抽象接口和其对应的xml文件

    /**
     * 查询所有菜单
     */
    List<Menu> queryAllMenu(Menu menu);

xml配置文件的sql语句

  <!--查询所有菜单-->
    <resultMap id="BaseResultMap" type="per.leiyu.sys.domain.Menu">
    <id column="id" jdbcType="INTEGER" property="id" />
    <result column="pid" jdbcType="INTEGER" property="pid" />
    <result column="title" jdbcType="VARCHAR" property="title" />
    <result column="href" jdbcType="VARCHAR" property="href" />
    <result column="spread" jdbcType="INTEGER" property="spread" />
    <result column="target" jdbcType="VARCHAR" property="target" />
    <result column="icon" jdbcType="VARCHAR" property="icon" />
    <result column="available" jdbcType="INTEGER" property="available" />
  </resultMap>
  <select id="queryAllMenu" resultMap="BaseResultMap">
    select
    <include refid="Base_Column_List" />
    from sys_menu
    <where>
        <if test="title!=null and title!=''">
            and title like concat("%",#{title},"%")
        </if>
        <if test="available!=null">
            and available=#{available}
        </if>
        <if test="id!=null">
            and (id=#{id} or pid=#{id})
        </if>
    </where>
  </select>

到这里,从前端到后端关于数据库中菜单数据的查询显示的功能就全部实现,下一篇文章将菜单的删除,批量删除,添加和修改功能实现

我是雷雨,一个普本科的学生,主要专注于Java后端和大数据开发

如果你喜欢这样的文章,可以关注我,一起努力,一起努力拿大厂offer
如果这篇文章有帮助到你,希望你给我一个的赞
如果有什么问题,希望你能评论区和我一起研究.

如果您要转载请转载注明出处
https://blog.csdn.net/qq_40742223

猜你喜欢

转载自blog.csdn.net/qq_40742223/article/details/107388056
今日推荐