Day83.尚好房 — 用户管理— Hplus(UI框架)、Layer(弹出层框架)、增删改查、分页组件 :分页查询

目录

用户角色管理

一、后台主题UI框架 (Hplus)

1. 集成框架

2. 添加、修改框架主页面

3. IndexController 框架页面控制器 (路径使用常量)

二、角色管理

二、弹出层框架 (layer)

1. layer封装

2. 测试弹出层

三、添加角色

4. 保存角色:controller  -》 service  -》 dao  -》 dao.xml

5. 新增弹出层成功提示页面

四、修改角色

SQl语句 列编辑 ★

五、删除角色 (软删除)

六、分页查询 ★

1. RoleController层,注释掉原有列表方法

2. mybatis-config.xml 添加分页支持、导包添加依赖

3. RoleService层 添加接口与实现

4. Dao层、xml方法

5、列表页面

6. 测试


用户角色管理

效果展示

一、后台主题UI框架 (Hplus)

后台前端框架模板:Hplus

下载地址:hplus: Hplus(H+)官方仓库

1. 集成框架

在web-admin模块webapp下新建static文件夹,用于存放静态资源文件

复制Hplus静态资源到 webapp\static 文件夹下

2. 添加、修改框架主页面

1、在templates目录新建frame文件夹,用于存放框架相关页面

2、复制hplus-master文件夹index.html文件到frame文件夹

3、删除index.html无用代码,更改静态资源与图片路径,代码如下index.html

frame/index.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
	<head>
		<meta charset="utf-8" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0" />
		<meta name="renderer" content="webkit" />

		<title>H+ 后台主题UI框架 - 主页</title>

		<meta name="keywords" content="H+后台主题,后台bootstrap框架,会员中心主题,后台HTML,响应式后台" />
		<meta name="description" content="H+是一个完全响应式,基于Bootstrap3最新版本开发的扁平化主题,她采用了主流的左右两栏式布局,使用了Html5+CSS3等现代技术" />

		<!--[if lt IE 9]>
			<meta http-equiv="refresh" content="0;ie.html" />
		<![endif]-->

		<link rel="shortcut icon" th:href="@{/static/favicon.ico}" />
		<link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet" />
		<link th:href="@{/static/css/font-awesome.min.css?v=4.4.0}" rel="stylesheet" />
		<link th:href="@{/static/css/animate.css}" rel="stylesheet" />
		<link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet" />
		<link th:href="@{/static/css/jquery.contextMenu.min.css}" rel="stylesheet"/>
	</head>

	<body class="fixed-sidebar full-height-layout gray-bg" style="overflow: hidden;">
		<div id="wrapper">
			<!--左侧导航开始-->
			<nav class="navbar-default navbar-static-side" role="navigation">
				<div class="nav-close"><i class="fa fa-times-circle"></i></div>
				<div class="sidebar-collapse">
					<ul class="nav" id="side-menu">
						<li class="nav-header">
							<div class="dropdown profile-element">
								<span><img alt="image" class="img-circle" th:src="@{/static/img/profile_small.jpg}" /></span>
								<a data-toggle="dropdown" class="dropdown-toggle" href="#">
									<span class="clear">
										<span class="block m-t-xs"><strong class="font-bold">Beaut-zihan</strong></span>
										<span class="text-muted text-xs block">超级管理员<b class="caret"></b></span>
									</span>
								</a>
								<ul class="dropdown-menu animated fadeInRight m-t-xs">
									<li><a class="J_menuItem" href="form_avatar.html">修改头像</a></li>
									<li><a class="J_menuItem" href="profile.html">个人资料</a></li>
									<li><a class="J_menuItem" href="contacts.html">联系我们</a></li>
									<li><a class="J_menuItem" href="mailbox.html">信箱</a></li>
									<li class="divider"></li>
									<li><a href="login.html">安全退出</a></li>
								</ul>
							</div>
							<div class="logo-element">H+</div>
						</li>
						<li>
							<a href="#">
								<i class="fa fa-home"></i>
								<span class="nav-label">权限管理</span>
								<span class="fa arrow"></span>
							</a>
							<ul class="nav nav-second-level">
								<li>
									<a class="J_menuItem" href="index_v1.html" data-index="0">用户管理</a>
								</li>
								<li>
									<a class="J_menuItem" href="index_v2.html">角色管理</a>
								</li>
								<li>
									<a class="J_menuItem" href="index_v3.html">菜单管理</a>
								</li>
							</ul>
						</li>

						<li>
							<a href="#">
								<i class="fa fa-home"></i>
								<span class="nav-label">二手房管理</span>
								<span class="fa arrow"></span>
							</a>
							<ul class="nav nav-second-level">
								<li>
									<a class="J_menuItem" href="index_v1.html" data-index="0">数据字段</a>
								</li>
								<li>
									<a class="J_menuItem" href="index_v2.html">小区管理</a>
								</li>
								<li>
									<a class="J_menuItem" href="index_v3.html">房源管理</a>
								</li>
							</ul>
						</li>
						<li>
							<a href="#">
								<i class="fa fa-home"></i>
								<span class="nav-label">会员管理</span>
								<span class="fa arrow"></span>
							</a>
							<ul class="nav nav-second-level">
								<li>
									<a class="J_menuItem" href="index_v1.html" data-index="0">会员列表</a>
								</li>
							</ul>
						</li>


					</ul>
				</div>
			</nav>
			<!--左侧导航结束-->
			<!--右侧部分开始-->
			<div id="page-wrapper" class="gray-bg dashbard-1">
				<div class="row border-bottom">
					<nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0;">
						<div class="navbar-header">
							<a class="navbar-minimalize minimalize-styl-2 btn btn-primary" href="#"><i class="fa fa-bars"></i> </a>
							<form role="search" class="navbar-form-custom" method="post" action="search_results.html">
								<div class="form-group">
									<input type="text" placeholder="请输入您需要查找的内容 …" class="form-control" name="top-search" id="top-search" />
								</div>
							</form>
						</div>

					</nav>
				</div>
				<div class="row content-tabs">
					<button class="roll-nav roll-left J_tabLeft"><i class="fa fa-backward"></i></button>
					<nav class="page-tabs J_menuTabs">
						<div class="page-tabs-content">
							<a href="javascript:;" class="active J_menuTab" data-id="index_v1.html">首页</a>
						</div>
					</nav>
					<button class="roll-nav roll-right J_tabRight"><i class="fa fa-forward"></i></button>
					<div class="btn-group roll-nav roll-right">
						<button class="dropdown" data-toggle="dropdown">页签操作<span class="caret"></span></button>
						<ul role="menu" class="dropdown-menu dropdown-menu-right">
							<li class="tabCloseCurrent"><a>关闭当前</a></li>
							<li class="J_tabCloseOther"><a>关闭其他</a></li>
							<li class="J_tabCloseAll"><a>全部关闭</a></li>
						</ul>
					</div>
					<a href="#" class="roll-nav roll-right tabReload"><i class="fa fa-refresh"></i> 刷新</a>
				</div>
				<div class="row J_mainContent" id="content-main">
					<iframe class="J_iframe" name="iframe0" width="100%" height="100%" th:src="@{/main}" frameborder="0" data-id="index_v1.html" seamless></iframe>
				</div>
				<div class="footer">
					<div class="pull-right">&copy; 2014-2015 <a href="http://www.zi-han.net/" target="_blank">zihan's blog</a></div>
				</div>
			</div>
			<!--右侧部分结束-->


		</div>

		<!-- 全局js -->
		<script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
		<script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
		<script th:src="@{/static/js/plugins/metisMenu/jquery.metisMenu.js}"></script>
		<script th:src="@{/static/js/plugins/slimscroll/jquery.slimscroll.min.js}"></script>
		<script th:src="@{/static/js/plugins/contextMenu/jquery.contextMenu.min.js}"></script>
		<script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>

		<!-- 自定义js -->
		<script th:src="@{/static/js/hplus.js?v=4.1.0}"></script>
		<script type="text/javascript" th:src="@{/static/js/contabs.js}"></script>

	</body>
</html>

fream/main.html (在index中引入)

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="renderer" content="webkit" />
    <!--[if lt IE 9]>
    <meta http-equiv="refresh" content="0;ie.html" />
    <![endif]-->
</head>
<body style="position: relative;">
<div style="text-align:center;margin-top: 100px;font-size: 20px;">
    <strong>欢迎登录尚好房平台管理系统</strong>
</div>
</body>
</html>

3. IndexController 框架页面控制器 (路径使用常量)

package com.atguigu.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @Date 2022/6/16 22:44
 * @Author by:Plisetsky
 */
@Controller
@RequestMapping
public class IndexController {
    private static final String PATH_INDEX = "frame/index";
    private static final String PAGE_MAIN = "frame/main";

    //框架首页
    @RequestMapping("/")
    public String index(){

        return PATH_INDEX;
    }
    //框架主页
    @GetMapping("/main")
    public String main() {
        return PAGE_MAIN;
    }

}

二、角色管理

1. 修改role/index.html

复制模板页面的css与js引用,目前只做列表展示,分页功能后续补充。

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <!-- Data Tables -->
    <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">
    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

    <!-- 全局js -->
    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
    <script th:src="@{/static/js/plugins/jeditable/jquery.jeditable.js}"></script>
    <!-- Data Tables -->
    <script th:src="@{/static/js/plugins/dataTables/jquery.dataTables.js}"></script>
    <script th:src="@{/static/js/plugins/dataTables/dataTables.bootstrap.js}"></script>
</head>
<body class="gray-bg">
    <div class="wrapper wrapper-content animated fadeInRight">
        <div class="row">
            <div class="col-sm-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-content">
                        <table class="table table-striped table-bordered table-hover dataTables-example">
                            <thead>
                            <tr>
                                <th>序号</th>
                                <th>角色名称</th>
                                <th>角色编码</th>
                                <th>描述</th>
                                <th>创建时间</th>
                            </tr>
                            </thead>
                            <tbody>
                            <tr class="gradeX" th:each="item,it : ${list}">
                                <td class="text-center" th:text="${it.count}">11</td>
                                <td th:text="${item.roleName}">22</td>
                                <td th:text="${item.roleCode}">33</td>
                                <td th:text="${item.description}">33</td>
                                <td th:text="${#dates.format(item.createTime,'yyyy-MM-dd HH:mm:ss')}" >33</td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
</body>
</html>

2. 将角色列表添加到框架页面中

更改frame/index.html ,部分代码

二、弹出层框架 (layer)

添加、修改、删除功能我们会使用弹出层的方式进行处理

弹出层框架:Layui - 经典开源模块化前端 UI 框架

layer参考文档:layer弹层组件开发文档 - Layui

hplus-master已经引入了layer框架,路径static/js/plugins/layer,可以直接使用

1. layer封装

我们把可能使用到的弹出层方法进行封装,方便后续使用

static/js 目录新建文件:myLayer.js

var opt = {
   alert : function(msg){
      layer.alert(msg);
   },

   load : function () {
      layer.load(1, {
         shade: [0.5,'#fff'] //0.1透明度的白色背景
      });
   },

   confirm : function(url, msg) {
      var msg = msg ? msg : "确定该操作吗?";
      layer.confirm(msg,function(index){
         opt.load();
         window.location = url;
      });
   },

   dialog : function(message, messageType) {
      if(message != '' && message != null) {
         if(messageType == '1') {
            layer.msg(message, {icon: 1});
         } else {
            layer.alert(message, {icon: 2});
         }
      }
   },

   openWin : function(url,title, width,height) {
      var title = title ? title : false;
      layer.open({
         type: 2,
         title: title,
         zIndex:10000,
         anim: -1,
         maxmin: true,
         aini:2,
         shadeClose: false, //点击遮罩关闭层
         area: [width+"px", height+"px"],
         content: url
      });
   },
   closeWin : function(refresh,call) {
      var index = parent.layer.getFrameIndex(window.name);
      if(refresh) {
         parent.location.reload();
      }
      if(call) {
         parent.init();
      }
      parent.layer.close(index); //执行关闭
   }
}

2. 测试弹出层

role/index.html 角色列表页面测试弹出层

  • 引入弹出层js
  <!-- 弹出层js -->
  <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
  <!--封装了Layer-->
  <script th:src="@{/static/js/myLayer.js}"></script>
  • 添加测试案例
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <!-- Data Tables -->
    <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">
    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

    <!-- 全局js -->
    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
    <script th:src="@{/static/js/plugins/jeditable/jquery.jeditable.js}"></script>
    <!-- Data Tables -->
    <script th:src="@{/static/js/plugins/dataTables/jquery.dataTables.js}"></script>
    <script th:src="@{/static/js/plugins/dataTables/dataTables.bootstrap.js}"></script>

    <!-- 弹出层js -->
    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
    <script th:src="@{/static/js/myLayer.js}"></script>
</head>
<body class="gray-bg">
    <div class="wrapper wrapper-content animated fadeInRight">
        <div class="row">
            <div class="col-sm-12">
                <div class="ibox float-e-margins">
                    <div class="ibox-content">
                        <div>
                            <button type="button" class="btn btn-sm btn-primary alert">alert</button>
                            <button type="button" class="btn btn-sm btn-primary load">load</button>
                            <button type="button" class="btn btn-sm btn-primary confirm">confirm</button>
                            <button type="button" class="btn btn-sm btn-primary dialog">dialog</button>
                            <button type="button" class="btn btn-sm btn-primary openWin">openWin</button>
                        </div>
                        <table class="table table-striped table-bordered table-hover dataTables-example">
                            <thead>
                            <tr>
                                <th>序号</th>
                                <th>角色名称</th>
                                <th>角色编码</th>
                                <th>描述</th>
                                <th>创建时间</th>
                            </tr>
                            </thead>
                            <tbody>
                            <tr class="gradeX" th:each="item,it : ${list}">
                                <td class="text-center" th:text="${it.count}">11</td>
                                <td th:text="${item.roleName}">22</td>
                                <td th:text="${item.roleCode}">33</td>
                                <td th:text="${item.description}">33</td>
                                <td th:text="${#dates.format(item.createTime,'yyyy-MM-dd HH:mm:ss')}" >33</td>
                            </tr>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>

<script th:inline="javascript">
    /*
    jQuery框架: 前端框架,主要功能:选择器,常用函数,提交ajax请求
    $(function (){ //相当于页面的onload事件 (body加载后执行)
    })
     */
    $(function(){

        //给页面元素绑定相应事件
        //${".alert"} 表示样式类选择器,查找页面使用了alert样式的元素
        //${"#id"}  表示id选择器,根据页面元素的id属性值获取元素,类似document.getElementById("id")

        $(".alert").on("click",function () {
            opt.alert("测试alert")
        });
        $(".load").on("click",function () {
            opt.load();
        });
        $(".confirm").on("click",function(){
            opt.confirm("","删除操作需要确认");
        });
        $(".dialog").on("click",function () {
            opt.dialog("测试提示框",1);
        });
        $(".openWin").on("click",function () {
            opt.openWin("/role","测试打开弹出窗口",580,430);
        });
    });
</script>
</body>
</html>

3. 效果展示
   

openWin:添加和修改时,使用该功能弹出表单页面  

三、添加角色

1. 列表页面添加新增按钮、JS绑定点击事件 (layer)

<button type="button" class="btn btn-sm btn-primary create">新增</button>
$(".create").on("click",function () {
  opt.openWin("/role/create","添加角色",580,430);
});

2. RoleController 前往新增页面控制器 (方法)

    private static final String PAGE_CREATE = "role/create";

    //前往新增页面
    @RequestMapping("/create")
    public String create(){
        return PAGE_CREATE;
    }

3. 添加create.html模板

参考模板页面:hplus-master/form_basic.html

rule/create.html

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>新增</title>

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <!-- Data Tables -->
    <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">
    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

    <!-- 全局js -->
    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
    
    <!-- 弹出层js -->
    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
    <script th:src="@{/static/js/myLayer.js}"></script>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <div class="ibox-content" style="width: 98%;">
            <form id="ec" th:action="@{/role/save}" method="post" class="form-horizontal">
                <div class="form-group">
                    <label class="col-sm-2 control-label">角色名称:</label>
                    <div class="col-sm-10">
                        <input type="text" name="roleName" id="roleName" value="" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">角色编码:</label>
                    <div class="col-sm-10">
                        <input type="text" name="roleCode" id="roleCode" value="" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">描述:</label>
                    <div class="col-sm-10">
                        <textarea name="description" id="description" class="form-control" style="width:100%;height: 50px;" ></textarea>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group posf">
                    <div class="col-sm-4 col-sm-offset-2 text-right">
                        <button class="btn btn-primary" type="submit">确定</button>
                        <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消</button></div>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

4. 保存角色:controller  -》 service  -》 dao  -》 dao.xml

注意:所有的数据库表都拥有 ID、创建时间、更新时间、软删除标记 字段,且设定了默认值、主键自增,会自动生成,所以新增sql语句无需加入时间。

controller
    //新增角色
    //springMVC根据反射创建Bean,调用参数名称的set方法,将参数注入到对象
    //Map 和 ModelMap 本质相同,model调用addAttribute,map调用put即可
    @RequestMapping("/save")
    public String save(Role role, Map map){
        roleService.insert(role);
        map.put("messagePage","添加成功");
        //return ACTION_LIST;  返回列表,效果不好
        return PAGE_SUCCESS;
    }
RoleServiceImpl
    @Override
    public Integer insert(Role role) {
        return roleDao.insert(role);
    }
RoleDao 
@Repository
public interface RoleDao {
    Integer insert(Role role);
}
<!--保存: bean对象保存前id属性是没有值的,保存后,执行insert语句,数据库分配主键值
mybatis框架会获取数据库分配的主键值,并赋值给bean对象的id属性,这个过程称为主键回填
-->
<insert id="insert" parameterType="Role" useGeneratedKeys="true" keyProperty="id">
    insert into acl_role(role_name,role_code,description) values (#{roleName},#{roleCode},#{description})
</insert>

5. 新增弹出层成功提示页面

新建common/successPage.html页面 ,添加、修改成功后跳转到该页面。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>成功提示页</title>

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <!-- Data Tables -->
    <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">
    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

    <!-- 全局js -->
    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>

    <!-- 弹出层js -->
    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
    <script th:src="@{/static/js/myLayer.js}"></script>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <div class="ibox-content">
            <div class="form-group">
                <div class="col-sm-10" th:text="${messagePage}">操作成功</div>
            </div>
            <div class="hr-line-dashed"></div>
            <div class="form-group posf">
                <div class="col-sm-4 col-sm-offset-2">
                    <button class="btn btn-primary" type="button" onclick="opt.closeWin(true);">确定</button>
                </div>
            </div>
        </div>
    </div>
</div>
</body>
</html>

6. 最终测试 


点击“确认”,会刷新父页面

四、修改角色

1. 列表添加修改

列表添加操作一栏

<th>操作 </th>
...
<td class="text-center">
    <a class="edit" th:attr="data-id=${item.id}">修改</a>
</td>
//给所有应用"edit"名称样式的元素增加单击事件
$(".edit").on("click",function () { //回调函数
    //$(this)  this表示当前触发事件的页面dom类型元素,
    // $()将某个dom元素转换为jquery对象,这样就就可以调用jQuery函数
    var id = $(this).attr("data-id");
    opt.openWin('/role/edit/' + id,'修改',580,430);//根据路径传参
});

2. RoleController 添加跳转修改页面方法

private final static String PAGE_EDIT = "role/edit";

//前往修改页面
@RequestMapping("/edit/{id}")
public String edit(ModelMap model, @PathVariable Long id){
    Role role = roleService.getById(id);
    model.addAttribute("role",role);
    return PAGE_EDIT;
}

3. 新建edit.html  修改页面

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>修改</title>

    <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
    <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
    <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

    <!-- Data Tables -->
    <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

    <link th:href="@{/static/css/animate.css}" rel="stylesheet">
    <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

    <!-- 全局js -->
    <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
    <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
    
    <!-- 弹出层js -->
    <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
    <script th:src="@{/static/js/myLayer.js}"></script>
</head>
<body class="gray-bg">
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="ibox float-e-margins">
        <div class="ibox-content" style="width: 98%;">
            <form id="ec" th:action="@{/role/update}" method="post" class="form-horizontal" >
                <input type="hidden" name="id" th:value="${role.id}">
                <div class="form-group">
                    <label class="col-sm-2 control-label">角色:</label>

                    <div class="col-sm-10">
                        <input type="text" name="roleName" id="roleName" th:value="${role.roleName}" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">角色编码:</label>
                    <div class="col-sm-10">
                        <input type="text" name="roleCode" id="roleCode" th:value="${role.roleCode}" class="form-control"/>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group">
                    <label class="col-sm-2 control-label">描述:</label>
                    <div class="col-sm-10">
                        <textarea name="description" id="description" class="form-control" style="width:100%;height: 50px;" th:text="${role.description}" ></textarea>
                    </div>
                </div>
                <div class="hr-line-dashed"></div>
                <div class="form-group posf">
                    <div class="col-sm-4 col-sm-offset-2 text-right">
                        <button class="btn btn-primary" type="submit">确定</button>
                        <button class="btn btn-white" type="button" onclick="javascript:opt.closeWin();" value="取消">取消</button></div>
                    </div>
                </div>
            </form>
        </div>
    </div>
</div>
</body>
</html>

4. RoleController 添加修改方法 -》 service -》dao (省略)

	@PostMapping(value="/update")
	public String update(Role role) {
		roleService.update(role);
		return PAGE_SUCCESS;
	}

5. dao层Sql语句编写 (列编辑)

void update(Role role);
<!--修改-->
    <update id="update">
        update acl_role
        <set>
            <if test="roleName!=null and roleName!=''">
                role_name = #{roleName},
            </if>
            <if test="roleCode!=null and roleCode!=''">
                role_code = #{roleCode},
            </if>
            <if test="description!=null and description!=''">
                description = #{description},
            </if>
            update_time = now()
        </set>
        where id = #{id}
    </update>
    <!--<update id="update" parameterType="Role">
        update ale_role set role_name = #{roleName},role_code = #{roleCode},
                            description = #{description},updateTime = now()
        where id = #{id}
    </update>-->

SQl语句 列编辑 

编写if动态sql时候,使用列编辑可提高开发效率: 选中要判断的字段

1. alt + 鼠标下拉
2. ctrl + w   或   ctrl + shift + 向左、向右
3. 鼠标滚轮 + 下拉

 

6. 效果展示

五、删除角色 (软删除)

1. 添加删除按钮及事件

<a class="delete" th:attr="data-id=${item.id}">删除</a>

//删除,带确认框
$(".delete").on("click",function(){
    var id = $(this).attr("data-id");
    opt.confirm('/role/delete/'+id,"确认删除吗?");
});

2. controller层 (删除成功后会自动关闭窗口,重定向到主页刷新列表)  service、dao省略

    private static final String ACTION_LIST = "redirect:/role"; //重定向

    //删除
    @RequestMapping("/delete/{id}")
    public String delete(@PathVariable Long id,ModelMap model){
        roleService.delete(id);
        return ACTION_LIST;
    }

3. dao.xml sql语句  (采用软删除)

    <!--软删除:修改表的 id_deleted字段,0 表示正常 1 表示被删除 -->
    <delete id="delete" parameterType="long">
        update acl_role
        set is_deleted = 1 , update_time = now()
        where id = #{id}
    </delete>

六、分页查询 ★

1. RoleController层,注释掉原有列表方法

filters封装页面搜索条件,如:roleName,查询条件

    //分页查询角色列表 需接收的查询条件: roleName、pageNum、pageSize
    @RequestMapping
    public String index(HttpServletRequest request,Map map) {
        Map<String, Object> filters = getFilters(request);
        //pageInfo比page封装了更多信息
        PageInfo pageInfo = roleService.findPage(filters);

        map.put("page",pageInfo);   //用于表单数据渲染
        map.put("filters",filters); //用于表单回显(查询参数:名称、页码等)
        return PAGE_INDEX;
    }

    /**
     * 封装页面提交的分页参数及搜索条件
     * @param request
     * @return
     * http://localhost:/role?age=22&age=23&roleName=管理员
     */
    protected Map<String, Object> getFilters(HttpServletRequest request) {
        Enumeration<String> paramNames = request.getParameterNames();
        Map<String, Object> filters = new TreeMap();
        while(paramNames != null && paramNames.hasMoreElements()) {
            String paramName = (String)paramNames.nextElement();
            //一个参数名可能有多个值,如果有多个则作为数组存储(如age=22或age=23)
            String[] values = request.getParameterValues(paramName);
            if (values != null && values.length != 0) {
                if (values.length > 1) {
                    filters.put(paramName, values);
                } else {
                    filters.put(paramName, values[0]);
                }
            }
        }
        //如果没有提交请求参数,给就这两个参数赋予默认值。
        if(!filters.containsKey("pageNum")) {
            filters.put("pageNum", 1);
        }
        if(!filters.containsKey("pageSize")) {
            filters.put("pageSize", 10);
        }
        return filters;
    }

2. mybatis-config.xml 添加分页支持、导包添加依赖

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!--开启驼峰命名自动映射-->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <!--开启分页插件配置-->
    <plugins>
        <!-- com.github.pagehelper 为 PageHelper 类所在包名 -->
        <plugin interceptor="com.github.pagehelper.PageHelper">
            <!-- dialect: 方言,设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL 六种数据库-->
            <property name="dialect" value="mysql"/>
        </plugin>
    </plugins>
</configuration>

common-util  pom.xml
<!--mybatis的分页插件-->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper</artifactId>
</dependency>

shf-parent 版本管理
<pagehelper.version>4.1.4</pagehelper.version>

3. RoleService层 添加接口与实现

public interface RoleService {
    PageInfo findPage(Map<String, Object> filters);
}

    @Override
    public PageInfo findPage(Map<String, Object> filters) {

        //使用工具类进行类型装换,设置默认值,解决空指针(访问首页时没有pageNum参数)
        int pageNum = CastUtil.castInt(filters.get("pageNum"),1);
        int pageSize = CastUtil.castInt(filters.get("pageSize"),1);

        //开启分页功能 (注意检查是否进行依赖、mybatis.xml是否配置)
        PageHelper.startPage(pageNum,pageSize);
        //将这两个参数,与当前线程(ThreadLocal)进行绑定,传递给dao层
        // select 语句,会自动追加limit ?,?  (limit startIndex,pageSize)
        // 公式: startIndex = (pageNum-1)*pageSize
        Page<Role> page = roleDao.findPage(filters);    //传递查询条件参数
        return new PageInfo<>(page,5);  //显示导航页数
    }

4. Dao层、xml方法

    Page<Role> findPage(Map<String, Object> filters);
    <!--功能提取  模糊查询也可写成"%"#{ename}"%",concat函数用于拼接字符-->
    <sql id="where">
        <where>
            <if test="roleName!=null and roleName!=''">
                role_name like concat('%',#{roleName},'%')
            </if>
            and is_deleted = 0
        </where>
    </sql>
    <!--带查询条件的 分页插件 查询-->
    <select id="findPage" parameterType="map" resultType="Role">
        select <include refid="column"></include>
        from acl_role
        <include refid="where"></include>
        order by id desc
    </select>

5、列表页面

模板页面:hplus-master/table_data_tables.html

a. 获取分页、导航条

  <!--搜索框,传递模糊查询参数-->
  <table class="table form-table margin-bottom10">
    <tr>
      <td>
        <input type="text" name="roleName" th:value="${#maps.containsKey(filters, 'roleName')} ? ${filters.roleName} : ''" placeholder="角色名称" class="input-sm form-control"/>
      </td>
    </tr>
  </table>

  <!--搜索框 解决了在第二页查询时,表单回显引起的BUG-->
  <button type="submit" class="btn btn-sm btn-primary" onclick="javascript:document.forms.ec.pageNum.value=1;">搜索</button><!--提交表单-->


  <!--分页条-->
  <div class="row" th:fragment="pagination">

    <!--隐藏了当前页、总页数,用于参数提交-->
    <input type="hidden" name="pageSize" id="pageSize" th:value="${page.pageSize}"/>
    <input type="hidden" name="pageNum" id="pageNum" th:value="${page.pageNum}"/>

    <div class="col-sm-6">
      <div class="dataTables_info" id="DataTables_Table_0_info" role="alert" aria-live="polite" aria-relevant="all">
        当前第<span th:text="${page.pageNum }"></span>页/共<span th:text="${page.pages}"></span>页&nbsp;&nbsp;共<span
              id="pageTotal" th:text="${page.total}"></span>条记录&nbsp;&nbsp;
      </div>
    </div>
    <div class="col-sm-6">
      <div class="dataTables_paginate paging_simple_numbers" id="DataTables_Table_0_paginate">
        <ul class="pagination">
          <!--首页 disabled样式: 禁止点击-->
          <li class="paginate_button previous" th:if="${!page.isFirstPage}"><a
                  href="javascript:document.forms.ec.pageNum.value=1;document.forms.ec.submit();">首页</a></li>
          <li class="paginate_button previous disabled" th:if="${page.isFirstPage}"><a href="javascript:">首页</a></li>
          <!--上一页-->
          <li class="paginate_button previous" th:if="${!page.isFirstPage}"><a
                  th:href="'javascript:document.forms.ec.pageNum.value='+${page.prePage}+';document.forms.ec.submit();'">上一页</a>
          </li>
          <li class="paginate_button previous disabled" th:if="${page.isFirstPage}"><a
                  href="javascript:">上一页</a></li>
          <!--页数循环-->
          <li th:each="i : ${page.navigatepageNums}"
              th:class="${i == page.pageNum } ? 'paginate_button active' : 'paginate_button'">
            <a th:href="'javascript:document.forms.ec.pageNum.value='+${i}+';document.forms.ec.submit();'"><span
                    th:text="${i}"></span></a>
          </li>
          <!--下一页-->
          <li class="paginate_button next" th:if="${!page.isLastPage}"><a
                  th:href="'javascript:document.forms.ec.pageNum.value='+${page.nextPage}+';document.forms.ec.submit();'">下一页</a>
          </li>
          <li class="paginate_button next disabled" th:if="${page.isLastPage}"><a href="javascript:">下一页</a>
          </li>
          <!--尾页-->
          <li class="paginate_button next" th:if="${!page.isLastPage}"><a
                  th:href="'javascript:document.forms.ec.pageNum.value='+${page.pages}+';document.forms.ec.submit();'">尾页</a>
          </li>
          <li class="paginate_button next disabled" th:if="${page.isLastPage}"><a href="javascript:">尾页</a></li>
        </ul>
      </div>
    </div>
  </div>

b. 给整体页面套入大表单,用于提交

搜索与分页都通过提交from表单的形式提交数据,后台controller获取参数放入Map对象作为参数

<!--大表单,用于数据提交-->
<body class="gray-bg">
   <form id="ec" th:action="@{/role}" method="post">
      ....
   </form>

c. 完整页面 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8">
  <title>Title</title>

  <link rel="shortcut icon" th:href="@{/static/favicon.ico}">
  <link th:href="@{/static/css/bootstrap.min.css?v=3.3.7}" rel="stylesheet">
  <link th:href="@{/static/css/font-awesome.css?v=4.4.0}" rel="stylesheet">

  <!-- Data Tables -->
  <link th:href="@{/static/css/plugins/dataTables/dataTables.bootstrap.css}" rel="stylesheet">

  <link th:href="@{/static/css/animate.css}" rel="stylesheet">
  <link th:href="@{/static/css/style.css?v=4.1.0}" rel="stylesheet">

  <!-- 全局js -->
  <script th:src="@{/static/js/jquery.min.js?v=2.1.4}"></script>
  <script th:src="@{/static/js/bootstrap.min.js?v=3.3.7}"></script>
  <script th:src="@{/static/js/plugins/jeditable/jquery.jeditable.js}"></script>
  <!-- Data Tables -->
  <script th:src="@{/static/js/plugins/dataTables/jquery.dataTables.js}"></script>
  <script th:src="@{/static/js/plugins/dataTables/dataTables.bootstrap.js}"></script>

  <!-- 弹出层js -->
  <script th:src="@{/static/js/plugins/layer/layer.min.js}"></script>
  <!--封装了Layer-->
  <script th:src="@{/static/js/myLayer.js}"></script>

</head>
<body class="gray-bg">
<!--大表单,用于数据提交-->
<form id="ec" th:action="@{/role}" method="post">

  <div class="wrapper wrapper-content animated fadeInRight">
    <div class="row">
      <div class="col-sm-12">
        <div class="ibox float-e-margins">
          <div class="ibox-content">

            <!--搜索框,传递模糊查询参数-->
            <table class="table form-table margin-bottom10">
              <tr>
                <td>
                  <input type="text" name="roleName" th:value="${#maps.containsKey(filters, 'roleName')} ? ${filters.roleName} : ''" placeholder="角色名称" class="input-sm form-control"/>
                </td>
              </tr>
            </table>

            <div>
              <!--<button type="button" class="btn btn-sm btn-primary alert">alert</button>
              <button type="button" class="btn btn-sm btn-primary load">load</button>
              <button type="button" class="btn btn-sm btn-primary confirm">confirm</button>
              <button type="button" class="btn btn-sm btn-primary dialog">dialog</button>
              <button type="button" class="btn btn-sm btn-primary openWin">openWin</button>-->
              <!--搜索框 解决了在第二页查询时,表单回显引起的BUG-->
              <button type="submit" class="btn btn-sm btn-primary" onclick="javascript:document.forms.ec.pageNum.value=1;">搜索</button><!--提交表单-->
              <button type="button" class="btn btn-sm btn-primary create">添加</button>
              <button type="button" class="btn btn-sm btn-primary" onclick="javascript:window.location.reload()">刷新</button>
            </div>

            <table class="table table-striped table-bordered table-hover dataTables-example">
              <thead>
              <tr>
                <th>序号</th>
                <th>角色名称</th>
                <th>角色编码</th>
                <th>描述</th>
                <th>创建时间</th>
                <th>操作</th>
              </tr>
              </thead>
              <tbody>
              <tr class="gradeX" th:each="item,it : ${page.list}">
                <td class="text-center" th:text="${it.count}">11</td>
                <td th:text="${item.roleName}">22</td>
                <td th:text="${item.roleCode}">33</td>
                <td th:text="${item.description}">33</td>
                <td th:text="${#dates.format(item.createTime,'yyyy-MM-dd HH:mm:ss')}" >33</td>
                <td class="text-center">
                  <!--attr: 将id值 赋值给临时属性,便于jQuery获取id-->
                  <a class="edit" th:attr="data-id=${item.id}">修改</a>
                  <a class="delete" th:attr="data-id=${item.id}">删除</a>
                </td>
              </tr>
              </tbody>
            </table>

            <!--分页条-->
            <div class="row" th:fragment="pagination">

              <!--隐藏了当前页、总页数-->
              <input type="hidden" name="pageSize" id="pageSize" th:value="${page.pageSize}"/>
              <input type="hidden" name="pageNum" id="pageNum" th:value="${page.pageNum}"/>

              <div class="col-sm-6">
                <div class="dataTables_info" id="DataTables_Table_0_info" role="alert" aria-live="polite" aria-relevant="all">
                  当前第<span th:text="${page.pageNum }"></span>页/共<span th:text="${page.pages}"></span>页&nbsp;&nbsp;共<span
                        id="pageTotal" th:text="${page.total}"></span>条记录&nbsp;&nbsp;
                </div>
              </div>
              <div class="col-sm-6">
                <div class="dataTables_paginate paging_simple_numbers" id="DataTables_Table_0_paginate">
                  <ul class="pagination">
                    <!--首页 disabled样式: 禁止点击-->
                    <li class="paginate_button previous" th:if="${!page.isFirstPage}"><a
                            href="javascript:document.forms.ec.pageNum.value=1;document.forms.ec.submit();">首页</a></li>
                    <li class="paginate_button previous disabled" th:if="${page.isFirstPage}"><a href="javascript:">首页</a></li>
                    <!--上一页-->
                    <li class="paginate_button previous" th:if="${!page.isFirstPage}"><a
                            th:href="'javascript:document.forms.ec.pageNum.value='+${page.prePage}+';document.forms.ec.submit();'">上一页</a>
                    </li>
                    <li class="paginate_button previous disabled" th:if="${page.isFirstPage}"><a
                            href="javascript:">上一页</a></li>
                    <!--页数循环-->
                    <li th:each="i : ${page.navigatepageNums}"
                        th:class="${i == page.pageNum } ? 'paginate_button active' : 'paginate_button'">
                      <a th:href="'javascript:document.forms.ec.pageNum.value='+${i}+';document.forms.ec.submit();'"><span
                              th:text="${i}"></span></a>
                    </li>
                    <!--下一页-->
                    <li class="paginate_button next" th:if="${!page.isLastPage}"><a
                            th:href="'javascript:document.forms.ec.pageNum.value='+${page.nextPage}+';document.forms.ec.submit();'">下一页</a>
                    </li>
                    <li class="paginate_button next disabled" th:if="${page.isLastPage}"><a href="javascript:">下一页</a>
                    </li>
                    <!--尾页-->
                    <li class="paginate_button next" th:if="${!page.isLastPage}"><a
                            th:href="'javascript:document.forms.ec.pageNum.value='+${page.pages}+';document.forms.ec.submit();'">尾页</a>
                    </li>
                    <li class="paginate_button next disabled" th:if="${page.isLastPage}"><a href="javascript:">尾页</a></li>
                  </ul>
                </div>
              </div>
            </div>

          </div>
        </div>
      </div>
    </div>
  </div>

</form>

<script th:inline="javascript">
/*
  jQuery框架: 前端框架,主要功能:选择器,常用函数,提交ajax请求
  $(function (){ //相当于页面的onload事件 (body加载后执行)
  })
*/
  $(function(){

    //给页面元素绑定相应事件
    //${".alert"} 表示样式类选择器,查找页面使用了alert样式的元素
    //${"#id"}  表示id选择器,根据页面元素的id属性值获取元素,类似document.getElementById("id")

    /*$(".alert").on("click",function () {
      opt.alert("测试alert")
    });
    $(".load").on("click",function () {
      opt.load();
    });
    $(".confirm").on("click",function(){
      opt.confirm("","删除操作需要确认");
    });
    $(".dialog").on("click",function () {
      opt.dialog("测试提示框",1);
    });
    $(".openWin").on("click",function () {
      opt.openWin("/role","测试打开弹出窗口",580,430);
    });*/
    $(".create").on("click",function () {
      opt.openWin("/role/create","添加角色",580,430);
    });
    $(".edit").on("click",function () {
      //$(this)  this表示当前触发事件的页面dom类型元素,
      // $()将某个dom元素转换为jquery对象,这样就就可以调用jQuery函数
      var id = $(this).attr("data-id");
      opt.openWin("/role/edit/"+ id,"修改角色",580,430);//Restful风格传参
    });

    $(".delete").on("click",function(){
      var id = $(this).attr("data-id");
      opt.confirm("/role/delete/"+ id,"确认删除吗?");
    });

  });
</script>

</body>
</html>

6. 测试

 

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值