目录
用户角色管理
一、后台主题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">© 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>页 共<span
id="pageTotal" th:text="${page.total}"></span>条记录
</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>页 共<span
id="pageTotal" th:text="${page.total}"></span>条记录
</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. 测试
文章来源:https://www.toymoban.com/news/detail-404517.html
文章来源地址https://www.toymoban.com/news/detail-404517.html
到了这里,关于Day83.尚好房 — 用户管理— Hplus(UI框架)、Layer(弹出层框架)、增删改查、分页组件 :分页查询的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!