【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置
一、user.jsp改造
删除引入菜单
抽取导航栏 nav-bar.jsp,删除引入导航栏
删除引入main.jsp的到好烂
数据库里添加url
报错,url不对
没有/
url正确
action="${ctp}/permission/user/login"
<a href="${c_menu.url }">
<%@page import="com.atguigu.scw.manager.constant.Constants"%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<div class="col-sm-3 col-md-2 sidebar">
<div class="tree">
<ul style="padding-left: 0px;" class="list-group">
<li class="list-group-item tree-closed"><a href="${ctp }/main.html"><i
class="glyphicon glyphicon-dashboard"></i> 控制面板</a></li>
<!-- 遍历菜单 -->
<c:forEach items="<%=session.getAttribute(Constants.USER_MENUS) %>" var="p_menu">
<li class="list-group-item tree-closed"><span>
<i class="${p_menu.icon }"></i> ${p_menu.name }
<span class="badge" style="float: right">${fn:length(p_menu.childs)}</span></span>
<ul style="margin-top: 10px; display: none;">
<c:forEach items="${p_menu.childs}" var="c_menu">
<li style="height: 30px;"><a href="${ctp }/${c_menu.url }"><i
class="${c_menu.icon }"></i> ${c_menu.name }</a></li>
</c:forEach>
</ul>
</li> </c:forEach>
</ul>
</div>
</div>
在controller里实现分页逻辑
package com.atguigu.scw.manager.controller.permission;
//处理所有/permission/user下的请求
@RequestMapping("/permission/user")
@Controller
public class UserController { private final String MANAGER_MAIN = "manager/main";
@Autowired
UserService userService; /**
* 用户列表页面显示
*
* @Description (TODO这里用一句话描述这个方法的作用)
* @return
*/
@RequestMapping("/list")
public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model) {
// 有表单提交,防止重复提交,建议额外写一个转发方法重定向到页面
// 没有表单提交就直接转发到目标页面
// 分页获取用户的逻辑
System.out.println("分页获取用户的逻辑");
PageHelper.startPage(pn, ps);
// 拿到分页查出的结果
List<TUser> list = userService.getAll();
// 去页面显示的数据
PageInfo<TUser> info = new PageInfo<TUser>(list, 5);
model.addAttribute("user_info", info);// 直接转到页面
return "manager/permission/user";
} @RequestMapping("/login")
public String login(TUser user, HttpSession session) {
// 省略
} // /permission/user/reg
@RequestMapping("/reg")
public String reg(TUser user, Model model, HttpSession session) {
// 省略
}
}
Mybatis的插件 PageHelper 分页查询使用方法 https://blog.csdn.net/maoyuanming0806/article/details/77720754
pageHelper.startPage(m,n),只对最近的一次查询有效,之前不是很理解什么是最近的一次查询。
原来mapper代理对象.selectXXX(),这个方法就是查询。
比如说:
pageHelper.startPage(1,30);
List<Item> list = ItemMapper.selectByExample(example);
也就是分页只针对这次获得的list有效。
PageHelper.startPage(pageNum, pageSize);
pageNum :当前页数
pageSize :一页大小
调用该方法后,在此方法后面的第一个mybaits查询语句就会按照这个进行分页
PageInfo pageInfo=new PageInfo(shippingList);
则对第一次查询的集合传入,可以获得更多的页面操作信息,封装在PageInfo 这个类上PageInfo pageInfo = new PageInfo(list,5);
使用pageInfo包装查询后的结果,封装了详细的查询数据,其中参数5是页码导航连续显示的页数
用到了UserService的getAll方法
在接口中添加方法,在实现类中实现方法
public interface UserService { public boolean register(TUser user); public TUser login(TUser user); public List<TUser> getAll();
}
实现类
package com.atguigu.scw.manager.service.impl; @Service
public class UserServiceImpl implements UserService { @Autowired
TUserMapper userMapper; public boolean register(TUser user) {
// 省略
} public TUser login(TUser user) {
// 省略
} public List<TUser> getAll() { return userMapper.selectByExample(null);
} }
user.jsp
<tbody>
<c:forEach items="${user_info.list}" var="user">
<tr>
<!-- varStatus="" 当前遍历的所有信息,索引 -->
<!-- 取出用户的实际ID -->
<td>${user.id }</td>
<td><input type="checkbox"></td>
<td>${user.loginacct }</td>
<td>${user.username }</td>
<td>${user.email }</td>
<td>
<button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>
<button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>
<button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>
</td>
</tr>
</c:forEach>
</tbody> <tfoot>
<tr >
<td colspan="6" align="center">
<ul class="pagination">
<li><a href="${ctp}/permission/user/list?pn=1">首页</a></li> <c:if test="${user_info.hasPreviousPage}">
<li><a href="${ctp}/permission/user/list?pn=${user_info.prePage }">上一页</a></li>
</c:if> <!-- 遍历连续显示的页面navigatepageNums: int[] -->
<c:forEach items="${user_info.navigatepageNums }" var="pn">
<!-- 是当前页 -->
<c:if test="${pn == user_info.pageNum }">
<li class="active"><a href="${ctp}/permission/user/list?pn=${pn}">${pn } <span
class="sr-only">(current)</span></a></li>
</c:if>
<!-- 不是当前页 -->
<c:if test="${pn != user_info.pageNum }">
<li><a href="${ctp}/permission/user/list?pn=${pn }">${pn }</a></li>
</c:if>
</c:forEach> <c:if test="${user_info.hasNextPage}">
<li><a href="${ctp}/permission/user/list?pn=${user_info.nextPage }">下一页</a></li>
</c:if> <li><a href="${ctp}/permission/user/list?pn=${user_info.pages }">末页</a></li> </ul>
</td>
</tr> </tfoot>
tbody标签就是显示的用户信息
tfoot标签中就是下面的导航
逻辑就是,点击用户维护按钮,会有请求到/permission/user/list,UserController的usrers处理该请求,使用PageHelpler插件,设置每页显示多少,通过新定义的getAll()方法从数据库获得用户信息,放在PageInfo对象中,在model中添加该对象往前台传数据,命名位user_info,最后转到user.jsp。
user.jsp接收到user_info,遍历该对象的list,显示用户的信息
在页脚,如果没有前一页就是首页,没有后一页就是末页,遍历首页和末页中正在连续显示的页面,这些页面中是当前的页面就高亮显示。
二、页面样式优化
当再次点击 用户维护 的时候
url链接重叠
菜单抽取中设置的url不对
<a href="${ctp }/${c_menu.url }"><i class="${c_menu.icon }"></i> ${c_menu.name }</a>
应改为当前项目下,这样才会最终是绝对路径,否则上面是相对路径,出现url重叠的现象
<a href="${ctp }/${c_menu.url }"><i class="${c_menu.icon }"></i> ${c_menu.name }</a>
来到页面后我们发现菜单是闭合的
我们想要展开,且当前菜单红色显示
查看网页源码
<!-- 遍历菜单 --> <li class="list-group-item tree-closed">
<span><i class="glyphicon glyphicon glyphicon-tasks"></i> 权限管理
<span class="badge" style="float:right">3</span></span>
<ul style="margin-top:10px;display:none;"> <li style="height:30px;">
<a href="/manager-web/permission/user/list"><i class="glyphicon glyphicon-user"></i> 用户维护</a>
</li> <li style="height:30px;">
<a href="/manager-web/"><i class=""></i> 角色维护</a>
</li> <li style="height:30px;">
<a href="/manager-web/"><i class=""></i> 许可维护</a>
</li> </ul>
</li>
<ul style="margin-top:10px;display:none;">我们发现展示是none
<a href="/manager-web/permission/user/list"><i class="glyphicon glyphicon-user"></i> 用户维护</a> 子在a链接里
因此要展示ul,且在a链接中设置字体颜色,编写js
<script type="text/javascript">
// 省略// 当前页面所在的那个超链接red:color
// 它的父list-group-item tree-closed是没有的
// 找到当前页面的a链接
// 使用css为某个元素加样式 list-group-item
$("a[href='${ctp }/permission/user/list']").css("color", "red");
$("a[href='${ctp }/permission/user/list']").parent(".list-group-item").removeClass("tree-closed");
$("a[href='${ctp }/permission/user/list']").parent().parent("ul").show(100); </script>
还要设置最上面的导航栏
在nav-bar.jsp中改为
<div><a class="navbar-brand" style="font-size:32px;" href="#">众筹平台 - ${navinfo }</a></div>
在user.jsp中添加这个navinfl变量
<body>
<%pageContext.setAttribute("navinfo", "用户维护"); %>
...
同理在需要该变量的各个页面设置即可
抽取页面显示效果
我们想各个页面都是菜单展开,当前菜单红色的设置,因此将共同的显示效果进行抽取
把js抽取抽来存放到common-js.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<script>
changePageStyle("${curUrl }");
function changePageStyle(url) {
//只有超链接在变化
$("a[href='${ctp }/"+url+"']").css("color", "red");
$("a[href='${ctp }/"+url+"']").parent(".list-group-item").removeClass("tree-closed");
$("a[href='${ctp }/"+url+"']").parent().parent("ul").show(100);
}
</script>
user.jsp中使用时只需要
设置curUrl并引入该jsp文件
<%
pageContext.setAttribute("navinfo", "用户维护");
pageContext.setAttribute("curUrl", "permission/user/list");
%>
...
<%@include file="/WEB-INF/includes/common-js.jsp" %>
<%@include file="/WEB-INF/includes/common-js.jsp" %>要插在<script>标签以外
三、带查询条件的分页
是一个form表单
指定action,表单提交的方向
指定提交方式为post
<form class="form-inline" role="form" style="float:left;" action="${ctp }/permission/user/list" method="post">
<div class="form-group has-feedback">
<div class="input-group">
<div class="input-group-addon">查询条件</div>
<input class="form-control has-success"
type="text" name="sp"
placeholder="请输入查询条件">
</div>
</div>
<button type="submit" class="btn btn-warning"><i class="glyphicon glyphicon-search"></i> 查询</button>
</form>
controller
@RequestMapping("/list")
public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
@RequestParam(value = "searchParam", defaultValue = "") String search) {
// 有表单提交,防止重复提交,建议额外写一个转发方法重定向到页面
// 没有表单提交就直接转发到目标页面
// 分页获取用户的逻辑
System.out.println("分页获取用户的逻辑");
PageHelper.startPage(pn, ps);
// 拿到分页查出的结果,不带条件的
// List<TUser> list = userService.getAll();
// 带条件的查询,将条件作为用户名或用户昵称的查询条件
// select * from t_user where loginacct like ? or username=? // 第一次创建的条件,默认使用and连接
TUserExample example = new TUserExample();
Criteria criteria1 = example.createCriteria();
Criteria criteria2 = example.createCriteria();
if (!search.trim().equals("")) {
criteria1.andLoginacctLike("%" + search + "%");
criteria2.andUsernameLike("%" + search + "%");
}
example.or(criteria2);
List<TUser> list = userService.getAllByCondition(example); // 去页面显示的数据
PageInfo<TUser> info = new PageInfo<TUser>(list, 5);
model.addAttribute("user_info", info);
for (TUser tUser : list) {
System.out.println(tUser);
} // 直接转到页面
return "manager/permission/user";
}
service层定义方法
接口
public interface UserService { public boolean register(TUser user); public TUser login(TUser user); public List<TUser> getAll(); public List<TUser> getAllByCondition(TUserExample example);
}
实现类
public List<TUser> getAllByCondition(TUserExample example) { return userMapper.selectByExample(example);
}
存在的问题是:查询条件不能回显,且当切换页面的时候,重新回到了不查询的状态,即查询状态无法维持
原因:当换页的时候,每个页的按钮都有转向的url,现在的url没有查询参数,因此切换的时候不会带查询条件
解决:给分页超链接绑上单击事件
// 为所有分页连接绑定单击事件,让其动态带上分页查询参数
$(".pagination").find("a").click(function(){
// 1.获取查询表单的查询参数
//$("input[name='searchParam']").val();
// 不禁用默认行为,而是为超链接多拼装上查询条件
// 为超链接动态拼上查询条件
var href = $(this).attr("href")+"&sp="+$("input[name='sp']").val();
$(this).attr("href", href); });
回显
controller里添加
model.addAttribute("sp", search);
往前端传递search,名字为sp
查询框添加value
<input class="form-control has-success"
type="text" name="sp"
placeholder="请输入查询条件" value=${sp }>
四、批量删除
首先实现全选全不选
user.jsp
<div class="table-responsive">
<table class="table table-bordered">
<thead>
<tr >
<th width="30">#</th>
<th width="30"><input id="checkall_btn" type="checkbox"></th>
<th>账号</th>
<th>名称</th>
<th>邮箱地址</th>
<th width="100">操作</th>
</tr>
</thead>
<tbody>
<c:forEach items="${user_info.list}" var="user">
<tr>
<!-- varStatus="" 当前遍历的所有信息,索引 -->
<!-- 取出用户的实际ID -->
<td>${user.id }</td>
<td><input type="checkbox" class="single_check"></td>
<td>${user.loginacct }</td>
<td>${user.username }</td>
<td>${user.email }</td>
<td>
<button type="button" class="btn btn-success btn-xs"><i class=" glyphicon glyphicon-check"></i></button>
<button type="button" class="btn btn-primary btn-xs"><i class=" glyphicon glyphicon-pencil"></i></button>
<button type="button" class="btn btn-danger btn-xs"><i class=" glyphicon glyphicon-remove"></i></button>
</td>
</tr>
</c:forEach>
</tbody>
js实现全选
放在common-js.jsp中
// 做全选全不选功能
// 传入全选按钮对象
function check_reverse(check_all_btn, check_btn) {
check_all_btn.click(function(){
// 如果是原生的属性,使用prop获取比较好
var flag = $(this).prop("checked");
check_btn.prop("checked", $(this).prop("checked"))
});
check_btn.click(function(){
// 当check_btn点满以后check_all_btn勾上,否则不选中
// 获取被选中的checkbtn个数
var flag = check_btn.filter(":checked").length == check_btn.length;
check_all_btn.prop("checked", flag);
});
}
删除
在user.jsp中获得id,并拼接成url
button的class设置为deleteAllBtn
js处理该button的点击
...
<button type="button" class="btn btn-danger deleteAllBtn" style="float:right;margin-left:10px;">
<i class=" glyphicon glyphicon-remove">
</i> 删除</button> ... check_reverse($("#checkall_btn"), $(".single_check"));
$(".deleteAllBtn").click(function () {
// 点击删除按钮,先拿到要删除的所有员工的id
var delUrl = "${ctp}/permission/user/del?ids="
var ids = "";
$(".single_check:checked").each(function () {
// 取出自定义的id属性
ids += $(this).attr("del_id")+","; // 1,2,3,
})
//剔除最后一个逗号 1,2,3
delUrl += ids.substring(0, ids.length-1);
//让浏览器访问这个删除链接
if(confirm("确认删除【"+ids+"】这些员工吗?")){
location.href = delUrl;
}
return false;
});
转到controller里进行处理
package com.atguigu.scw.manager.controller.permission; //处理所有/permission/user下的请求
@RequestMapping("/permission/user")
@Controller
public class UserController { private final String MANAGER_MAIN = "manager/main";
@Autowired
UserService userService; /**
* 用户删除
*/
@RequestMapping("/del")
public String userDelete(@RequestParam(value = "ids", defaultValue = "") String ids) {
if (!ids.trim().equals("")) { userService.deleteBatchOrSingle(ids); }
// 删除完成重新查询所有数据
return "redirect:/permission/user/list";
} /**
* 用户列表页面显示
*
* @Description (TODO这里用一句话描述这个方法的作用)
* @return
*/
@RequestMapping("/list")
public String users(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
@RequestParam(value = "sp", defaultValue = "") String search) {
// 省略
} @RequestMapping("/login")
public String login(TUser user, HttpSession session) {
// 省略
} // /permission/user/reg
@RequestMapping("/reg")
public String reg(TUser user, Model model, HttpSession session) {
// 省略
}
}
userService接口增加deleteBatchOrSingle(ids)方法
接口
public interface UserService { public boolean register(TUser user); public TUser login(TUser user); public List<TUser> getAll(); public List<TUser> getAllByCondition(TUserExample example); public void deleteBatchOrSingle(String ids);
}
实现类中实现方法
public void deleteBatchOrSingle(String ids) { if (ids.contains(",")) {
String[] split = ids.split(",");
List<Integer> list = new ArrayList<Integer>();
for (String s : split) {
int i = 0;
try {
i = Integer.parseInt(s);
} catch (NumberFormatException e) {
}
list.add(i);
}
TUserExample example = new TUserExample();
Criteria criteria = example.createCriteria();
// 删除id所在的集合
criteria.andIdIn(list);
userMapper.deleteByExample(example);
} else {
userMapper.deleteByPrimaryKey(Integer.parseInt(ids));
}
}
五、角色分配页面
从用户页面点击分配角色,来到分配角色页面,左侧是未分配角色列表,右侧是已分配角色列表
数据库角色
user.jsp配置下分配权限按钮
<tbody>
<c:forEach items="${user_info.list}" var="user">
<tr>
<!-- varStatus="" 当前遍历的所有信息,索引 -->
<!-- 取出用户的实际ID -->
<td>${user.id }</td>
<td><input type="checkbox" class="single_check" del_id=${user.id }></td>
<td>${user.loginacct }</td>
<td>${user.username }</td>
<td>${user.email }</td>
<td>
<button u_id="${user.id }" type="button" class="btn btn-success btn-xs assignBtn">
<i class=" glyphicon glyphicon-check"></i></button>
<button type="button" class="btn btn-primary btn-xs">
<i class=" glyphicon glyphicon-pencil"></i></button>
<button type="button" class="btn btn-danger btn-xs">
<i class=" glyphicon glyphicon-remove"></i></button>
</td>
</tr>
</c:forEach>
</tbody>
js
// 点击权限分配来到权限分配页面
$(".assignBtn").click(function(){
// 必须将用户id带给后台 自定义用attr
var id = $(this).attr("u_id");
// 去权限列分配页面
var url = "${ctp}/permission/user/toAssignRole?uid="+id;
location.href=url;
})
location.href
自定义属性
定义响应/permission/user/toAssignRole的controller
UserController中添加
@Autowired
RoleService roleService;
// 去权限分配页面
@RequestMapping("/toAssignRole")
public String toAssignRolePage(@RequestParam(value = "uid") Integer uid, Model model) {
System.out.println("要去权限分配页面,用户id:" + uid);
// 1.查出所有权限
List<TRole> roles = roleService.getAllRole();
// 2.查出当前用户拥有的权限
//
List<TRole> userRole = roleService.getUserRole(uid);
Map<Integer, TRole> map = new HashMap<Integer, TRole>();
for (TRole tRole : userRole) {
map.put(tRole.getId(), tRole);
}
// 3.用户未分配权限
List<TRole> unRoles = new ArrayList<TRole>();
for (TRole tRole : roles) {
if (!map.containsKey(tRole.getId())) {
// 用户已拥有的权限
unRoles.add(tRole);
}
}
model.addAttribute("unroles", unRoles);
model.addAttribute("roles", userRole);
// 来到权限分配页
return "manager/permission/assignRole"; }
定义RoleService接口
package com.atguigu.scw.manager.service; import java.util.List; import com.atguigu.scw.manager.bean.TRole; public interface RoleService { public List<TRole> getAllRole(); public List<TRole> getUserRole(Integer userId);
}
实现方法
package com.atguigu.scw.manager.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.atguigu.scw.manager.bean.TRole;
import com.atguigu.scw.manager.dao.TRoleMapper;
import com.atguigu.scw.manager.service.RoleService; @Service
public class RoleServiceImpl implements RoleService { @Autowired
TRoleMapper roleMapper; public List<TRole> getAllRole() { return roleMapper.selectByExample(null);
} public List<TRole> getUserRole(Integer userId) {
// select t.id,t.name from t_role t left join t_user_role u_r ON t.`id`=u_r.`roleid`
// left join t_user u on u. `id`=u_r.`userid`
// WHERE u.`id`=? return roleMapper.getUserRole(userId);
}
}
TRoleMapper.xml中增加自己以方法
<select id="getUserRole" resultMap="BaseResultMap">
select t.id,t.name from t_role t left join t_user_role u_r ON t.`id`=u_r.`roleid`
left join t_user u on u.`id`=u_r.`userid`
where u.`id`=#{uid}
</select>
连接查询
select 我们本意要查的字段from这个表
left join 其他表 on a 关联表
跳转到assignRole.jsp
<div class="panel panel-default">
<div class="panel-body">
<form role="form" class="form-inline">
<div class="form-group">
<label for="exampleInputPassword1">未分配角色列表</label><br>
<select class="form-control unroles" multiple size="10" style="width:100px;overflow-y:auto;">
<c:forEach items="${unroles }" var="role">
<option value="${role.id }">${role.name }</option> </c:forEach>
</select>
</div>
<div class="form-group">
<ul>
<li class="btn btn-default glyphicon glyphicon-chevron-right"></li>
<br>
<li class="btn btn-default glyphicon glyphicon-chevron-left" style="margin-top:20px;"></li>
</ul>
</div>
<div class="form-group" style="margin-left:40px;">
<label for="exampleInputPassword1">已分配角色列表</label><br>
<select class="form-control roles_select" multiple size="10" style="width:100px;overflow-y:auto;">
<c:forEach items="${roles }" var="role">
<option value="${role.id }">${role.name }</option> </c:forEach> </select>
</div>
</form>
</div>
</div>
分别对应
js
$(".glyphicon-chevron-right").click(function () { var rids = ""
$(".unroles :selected").each(function(){
rids += $(this).val()+",";
});
// 去掉最后的,
rids = rids.substring(0, rids.length-1); // 选中的添加到权限中
// 发送请求给后台,数据库完成操作
// 必须带上权限id的拼串和userid
var uid = "${param.uid }"
$.get("${ctp }/permission/user/assignrole?opt=add&uid="+uid+"&rids="+rids,function(){
// 选中并且分配成功的过去
$(".unroles :selected").appendTo(".roles_select");
})
}); $(".glyphicon-chevron-left").click(function () {
var uid = "${param.uid }"
var rids = ""
$(".roles_select :selected").each(function(){
rids += $(this).val()+",";
});
// 去掉最后的,
rids = rids.substring(0, rids.length-1); // 发送请求移除
$.get("${ctp }/permission/user/assignrole?opt=remove&uid="+uid+"&rids="+rids,function(){
//显示移除的效果
$(".roles_select :selected").appendTo(".unroles");
});
});
EL表达式${param.xxx}可以从url中获取参数放在页面中直接使用
比如:一个网址:127.0.0.1/test/testparam?test1=3&test2=sss
用${param.test1}就可以直接获取到test1的值,也就是3
用${param.test2}就可以直接获取到test2的值,也就是sss
${param.xxx} 就等价于 request.getparam("xxx"),也就是服务器从页面或者客户端获取的内容
定义响应/permission/user/assignrole的controller
控制器处理请求:
查出当前用户为拥有的权限
查出当前用户已拥有的权限
查出的结果放在页面
UserController中添加
@Autowired
UserRoleService urService; // 添加角色 如果返回值为空,默认请求地址就会当成页面地址
// public void UserRole(@RequestParam("rids") String rids, @RequestParam("uid") Integer uid) {
// 加@ResponseBody注解后,return "成功!"相当于out.write("成功")
@ResponseBody
@RequestMapping("/assignrole")
public String UserRole(@RequestParam("rids") String rids, @RequestParam("uid") Integer uid,
@RequestParam("opt") String opt) {
if ("add".equals(opt)) {
// 为某个用户添加一些角色
urService.addRole(rids, uid);
System.out.println("成功");
} else if ("remove".equals(opt)) {
// 移除角色
urService.removeRole(rids, uid);
System.out.println("删除完成");
} return "";
}
创建接口,实现方法
package com.atguigu.scw.manager.service; public interface UserRoleService { // 给用户添加角色
public void addRole(String ids, Integer userId); // 移除用户的某些角色
public void removeRole(String ids, Integer userId);
}
实现方法
package com.atguigu.scw.manager.service.impl; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import com.atguigu.scw.manager.bean.TUserRole;
import com.atguigu.scw.manager.bean.TUserRoleExample;
import com.atguigu.scw.manager.bean.TUserRoleExample.Criteria;
import com.atguigu.scw.manager.dao.TUserRoleMapper;
import com.atguigu.scw.manager.service.UserRoleService; @Service
public class UserRoleServiceImpl implements UserRoleService { @Autowired
TUserRoleMapper userRoleMapper; public void addRole(String ids, Integer userId) {
// 没有包含逗号,直接添加
if (ids.contains(",")) {
String[] split = ids.split(",");
for (String rid : split) {
// 创建一个中间表的数据对象
TUserRole role = new TUserRole(); int i = Integer.parseInt(rid);
role.setRoleid(i);
role.setUserid(userId);
userRoleMapper.insertSelective(role);
}
} else {
TUserRole role = new TUserRole();
int i = Integer.parseInt(ids);
role.setRoleid(i);
role.setUserid(userId);
userRoleMapper.insertSelective(role);
}
} public void removeRole(String ids, Integer userId) {
if (ids.contains(",")) {
String[] split = ids.split(",");
for (String rid : split) {
int i = Integer.parseInt(rid);
TUserRoleExample example = new TUserRoleExample();
Criteria criteria = example.createCriteria();
criteria.andRoleidEqualTo(i);
criteria.andUseridEqualTo(userId);
userRoleMapper.deleteByExample(example);
}
} else { int i = Integer.parseInt(ids);
TUserRoleExample example = new TUserRoleExample();
Criteria criteria = example.createCriteria();
criteria.andRoleidEqualTo(i);
criteria.andUseridEqualTo(userId);
userRoleMapper.deleteByExample(example);
}
} }
六、角色维护
新建控制器
t_permission
role.jsp设置导航栏、菜单等
先把分页部分做好
tbody
tfoot
<tbody>
<c:forEach items="${role_info.list }" var="role">
<tr>
<td>${role.id }</td>
<td><input type="checkbox"></td>
<td>${role.name }</td>
<td>
<button type="button" rid="${role.id }"
class="btn btn-success btn-xs assignPermissionModelBtn">
<i class=" glyphicon glyphicon-check"></i>
</button>
<button type="button" class="btn btn-primary btn-xs">
<i class=" glyphicon glyphicon-pencil"></i>
</button>
<button type="button" class="btn btn-danger btn-xs">
<i class=" glyphicon glyphicon-remove"></i>
</button>
</td>
</tr>
</c:forEach> </tbody>
<tfoot>
<tr>
<td colspan="6" align="center">
<ul class="pagination">
<!-- 即使点击分页连接也应该带上查询条件的值 -->
<!-- 给分页超链接绑定单击事件; -->
<li><a href="${ctp}/permission/role/list?pn=1">首页</a></li>
<c:if test="${role_info.hasPreviousPage}">
<li><a
href="${ctp}/permission/role/list?pn=${role_info.prePage}">上一页</a></li>
</c:if> <!-- 遍历连续显示的页面 navigatepageNums : int[]-->
<c:forEach items="${role_info.navigatepageNums}" var="pn">
<c:if test="${pn == role_info.pageNum }">
<li class="active"><a
href="${ctp}/permission/role/list?pn=${pn}">${pn } <span
class="sr-only">(current)</span></a></li>
</c:if>
<c:if test="${pn != role_info.pageNum }">
<li><a href="${ctp}/permission/role/list?pn=${pn}">${pn }</a></li>
</c:if>
</c:forEach> <c:if test="${role_info.hasNextPage}">
<li><a
href="${ctp}/permission/role/list?pn=${role_info.nextPage}">下一页</a></li>
</c:if>
<li><a
href="${ctp}/permission/role/list?pn=${role_info.pages}">末页</a></li>
</ul>
</td>
</tr> </tfoot>
RoleContrller里写处理逻辑
package com.atguigu.scw.manager.controller.permission; // 处理角色维护模块
@RequestMapping("/permission/role")
@Controller
public class RoleController { @Autowired
RoleService roleService;
// 来到角色维护页面
@RequestMapping("/list")
public String toRolePage(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
@RequestParam(value = "sp", defaultValue = "") String search) {
PageHelper.startPage(pn, ps);
List<TRole> role = roleService.getAllRole();
PageInfo<TRole> info = new PageInfo<TRole>(role, 5); // 连续显示5页
model.addAttribute("role_info", info); return "manager/permission/role";
}
}
bootstrap的模态框
在模态框里展示权限树
<!-- 模态框 -->
<div class="modal fade" id="permissModel" tabindex="-1" role="dialog"
aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"
aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title" id="myModalLabel">分配权限</h4>
</div>
<div class="modal-body">
<!-- 展示权限树 -->
<div>
<ul id="permissionTree" class="ztree"></ul>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="addPermissionBtn">分配权限</button>
</div>
</div>
</div>
</div>
js
ztree的js和cs文件放入cs-file.jsp、js-file.jsp
//保存ztree对象的
var ztreeObject;
//用户角色分配权限-
//点击按钮-打开模态框-查出所有的权限-在模态框中树形显示-将当前用户拥有的权限选中
/* $("tbody .btn-success").click(function() {
window.location.href = "assignPermission.html";
}); */
//点击分配权限按钮,
//模态框的按钮 $(".assignPermissionModelBtn").click(function() {
var options = {
backdrop : 'static',
show : true
} //"permissionTree"刷出权限树
//js的this会经常飘逸
initPermissionTree($(this).attr("rid"));
//getUser(1)
//勾选当前角色的权限
//打开模态框
$('#permissModel').modal(options);
//将角色id保存到模态框的哪个属性中; }); //treeId:是权限树ul的id
//treeNode:当前节点信息
function showIcon(treeId, treeNode) {
//console.log(treeId);
//treeNode里面有一个tId;
//这个tid用来拼串以后就是图标显示位置的元素id和名字显示位置的元素id
//tId:"permissionTree_3"
//<span id="permissionTree_2_span">用户维护</span>
//<span id="permissionTree_2_ico" ></span>
//console.log(treeNode);
//改图标;找到当前元素图标显示的节点,将这个节点的class设置为当前节点的icon
$("#" + treeNode.tId + "_ico").removeClass()
.addClass(treeNode.icon);
} function initPermissionTree(rid) {
var setting = {
data : {
simpleData : {
enable : true,
idKey : "id",
pIdKey : "pid",
},
key : {
url : "haha"
}
},
view : {
//自定义显示的效果
addDiyDom : showIcon
},
check : {
enable : true
}
}; //从数据库查出的所有权限节点数据
//发送ajax请求获取到所有权限的json数据
$.getJSON("${ctp}/permission/role/json", function(nodes) {
//console.log(nodes);
//给每一个节点修改或者添加一些属性
$.each(nodes, function() {
if (this.pid == 0) {
this.open = true;
}
})
//如果不是用var声明的变量,这个变量就默认变为全局的
//把初始化好的ztree对象传递给外界使用,可以通用操作这个对象,来改变树
//ztree为了不影响下面的操作是异步展示数据的
ztreeObject = $.fn.zTree.init($("#permissionTree"), setting,
nodes);
checkcurPermisson(rid);
})
}
RoleController处理
// 处理角色维护模块
@RequestMapping("/permission/role")
@Controller
public class RoleController { @Autowired
RoleService roleService; @Autowired
TPermissionService permissionService; // 返回所有权限的json数据
// 返回所有权限的list
@ResponseBody
@RequestMapping("/json")
public List<TPermission> getAllPermission() {
// 返回所有的权限
return permissionService.getPermissions();
} // 来到角色维护页面
@RequestMapping("/list")
public String toRolePage(@RequestParam(value = "pn", defaultValue = "1") Integer pn,
@RequestParam(value = "ps", defaultValue = "10") Integer ps, Model model,
@RequestParam(value = "sp", defaultValue = "") String search) {
PageHelper.startPage(pn, ps);
List<TRole> role = roleService.getAllRole();
PageInfo<TRole> info = new PageInfo<TRole>(role, 5); // 连续显示5页
model.addAttribute("role_info", info); return "manager/permission/role";
} }
TPermissionService接口添加方法,并实现
package com.atguigu.scw.manager.service.impl; @Service
public class TPermissionServiceImpl implements TPermissionService { @Autowired
TPermissionMapper mapper; public List<TPermission> getAllMenus() {
// 省略
} public List<TPermission> getPermissions() { return mapper.selectByExample(null);
} }
七、分配权限
已有的权限应该打勾
控制器里增加
RoleController
// /permission/role/perm/4
@ResponseBody
@RequestMapping("/perm/{id}")
public List<TPermission> getRolePermission(@PathVariable("id")Integer rid) {
List<TPermission> permissions = permissionService.getRolePermission(rid);
return permissions;
}
接口中增加方法,并实现该方法
package com.atguigu.scw.manager.service; public interface TPermissionService { // 拿到所有菜单
public List<TPermission> getAllMenus(); public List<TPermission> getPermissions(); public List<TPermission> getRolePermission(Integer rid);
}
实现方法
// 查询角色对应的权限
public List<TPermission> getRolePermission(Integer rid) {
return mapper.getRolePermission(rid); }
TPermissionMapper中增加查询方法
List<TPermission> getRolePermission(Integer rid);
实现
配置mybatis的mapper文件
TPermissionMapper.xml
<!-- List<TPermission> getRolePermission -->
<select id="getRolePermission" resultMap="BaseResultMap">
SELECT p.* FROM t_permission p
LEFT JOIN t_role_permission rp ON rp.`permissionid`=p.`id`
WHERE rp.`roleid`=#{rid}
</select>
js
<script type="text/javascript">
$(function() {
$(".list-group-item").click(function() {
if ($(this).find("ul")) {
$(this).toggleClass("tree-closed");
if ($(this).hasClass("tree-closed")) {
$("ul", this).hide("fast");
} else {
$("ul", this).show("fast");
}
}
});
}); //保存ztree对象的
var ztreeObject;
//用户角色分配权限-
//点击按钮-打开模态框-查出所有的权限-在模态框中树形显示-将当前用户拥有的权限选中
/* $("tbody .btn-success").click(function() {
window.location.href = "assignPermission.html";
}); */
//点击分配权限按钮,
//模态框的按钮
$("#addPermissionBtn").click(function(){
//1、获取当前我们已经选中的权限
var nodes = ztreeObject.getCheckedNodes(true);
//2、将这些权限的id和角色的id发给程序
var permission_ids = "";
$.each(nodes,function(){
permission_ids += this.id+",";
});
var rid = $(this).attr("rid");
//3、使用程序保存这个角色对应的权限的值
//写程序;删除对应的东西即可
$.get("${ctp}/permission/role/update?pids="+permission_ids+"&rid="+rid,function(){
alert("权限分配成功");
$('#permissModel').modal("hide");
})
}); $(".assignPermissionModelBtn").click(function() {
var options = {
backdrop : 'static',
show : true
} //"permissionTree"刷出权限树
//js的this会经常飘逸
initPermissionTree($(this).attr("rid"));
//getUser(1)
//勾选当前角色的权限
//打开模态框
$('#permissModel').modal(options);
//将角色id保存到模态框的哪个属性中;
//打开模态框将角色id传递给model里面的权限分配按钮
$('#addPermissionBtn').attr("rid",$(this).attr("rid"));
}); //treeId:是权限树ul的id
//treeNode:当前节点信息
function showIcon(treeId, treeNode) {
//console.log(treeId);
//treeNode里面有一个tId;
//这个tid用来拼串以后就是图标显示位置的元素id和名字显示位置的元素id
//tId:"permissionTree_3"
//<span id="permissionTree_2_span">用户维护</span>
//<span id="permissionTree_2_ico" ></span>
//console.log(treeNode);
//改图标;找到当前元素图标显示的节点,将这个节点的class设置为当前节点的icon
$("#" + treeNode.tId + "_ico").removeClass()
.addClass(treeNode.icon);
} ///传入角色id,将当前角色拥有的权限勾选
function checkcurPermisson(rid) {
// /permission/role/perm/4
$.getJSON("${ctp}/permission/role/perm/" + rid, function(data) {
//查出的当前角色拥有的权限
//ztree对象的方法;checkNode;
//三个参数:
//第一个参数就是要勾选的节点
//第二个参数就是勾选与否
//第三个参数是是否和父节点级联互动
//第四个参数是勾选状态变化后,是否调用之前用(callback)规定的回调函数
$.each(data, function() {
//console.log(this);
//从ztree中获取到要勾选的对象;
var node = ztreeObject.getNodeByParam("id", this.id, null);
ztreeObject.checkNode(node, true, false);
})
})
} function initPermissionTree(rid) {
var setting = {
data : {
simpleData : {
enable : true,
idKey : "id",
pIdKey : "pid",
},
key : {
url : "haha"
}
},
view : {
//自定义显示的效果
addDiyDom : showIcon
},
// 图标前的选中框开启
check : {
enable : true
}
}; //从数据库查出的所有权限节点数据
//发送ajax请求获取到所有权限的json数据
$.getJSON("${ctp}/permission/role/json", function(nodes) {
//console.log(nodes);
//给每一个节点修改或者添加一些属性 父菜单pid为0
$.each(nodes, function() {
if (this.pid == 0) {
this.open = true;
}
})
//如果不是用var声明的变量,这个变量就默认变为全局的
//把初始化好的ztree对象传递给外界使用,可以通用操作这个对象,来改变树
//ztree为了不影响下面的操作是异步展示数据的
ztreeObject = $.fn.zTree.init($("#permissionTree"), setting, nodes);
checkcurPermisson(rid);
})
}
</script>
分配权限数据读取
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">关闭</button>
<button type="button" class="btn btn-primary" id="addPermissionBtn">分配权限</button>
</div>
//点击分配权限按钮,
//模态框的按钮
$("#addPermissionBtn").click(function(){
//1、获取当前我们已经选中的权限
var nodes = ztreeObject.getCheckedNodes(true);
//2、将这些权限的id和角色的id发给程序
var permission_ids = "";
$.each(nodes,function(){
permission_ids += this.id+",";
});
var rid = $(this).attr("rid");
//3、使用程序保存这个角色对应的权限的值 })
}); $(".assignPermissionModelBtn").click(function() {
var options = {
backdrop : 'static',
show : true
} //"permissionTree"刷出权限树
//js的this会经常飘逸
initPermissionTree($(this).attr("rid"));
//getUser(1)
//勾选当前角色的权限
//打开模态框
$('#permissModel').modal(options);
//将角色id保存到模态框的哪个属性中;
//打开模态框将角色id传递给model里面的权限分配按钮
$('#addPermissionBtn').attr("rid",$(this).attr("rid"));
});
更新角色权限
RoleController
package com.atguigu.scw.manager.controller.permission;
// 处理角色维护模块
@RequestMapping("/permission/role")
@Controller
public class RoleController { @Autowired
RoleService roleService; @Autowired
TPermissionService permissionService; /**
* 更新角色权限
* 1.先删除当前角色的所有权限
* 2.在新增之前选中的所有权限
*/
@ResponseBody // ajax请求
@RequestMapping("/update")
public String deleteRolePermission(@RequestParam("pids")String pids,
@RequestParam("rid")Integer rid) {
boolean flag = permissionService.updatePermission(pids, rid);
return "ok";
} // 省略 }
接口增加上面方法,实现该方法
package com.atguigu.scw.manager.service; import java.util.List; import com.atguigu.scw.manager.bean.TPermission; public interface TPermissionService { // 拿到所有菜单
public List<TPermission> getAllMenus(); public List<TPermission> getPermissions(); public List<TPermission> getRolePermission(Integer rid); public boolean updatePermission(String pids, Integer rid);
}
实现方法
package com.atguigu.scw.manager.service.impl; @Service
public class TPermissionServiceImpl implements TPermissionService { @Autowired
TPermissionMapper mapper; @Autowired
TRolePermissionMapper rolePermissionMapper; // 省略 public boolean updatePermission(String pids, Integer rid) { // 1.删除当前角色的所有权限
TRolePermissionExample example = new TRolePermissionExample();
Criteria criteria = example.createCriteria();
criteria.andRoleidEqualTo(rid);
rolePermissionMapper.deleteByExample(example);
// 2.新增
String[] split = pids.split(",");
if (split != null && split.length>=1) {
for (String pid : split) {
int i = Integer.parseInt(pid);
TRolePermission permission = new TRolePermission();
// 设置角色id
permission.setRoleid(rid);
// 设置权限id
permission.setPermissionid(i);
// 保存角色权限关系
rolePermissionMapper.insertSelective(permission);
}
return true;
}
return false;
} }
js
$("#addPermissionBtn").click(function(){
//1、获取当前我们已经选中的权限
var nodes = ztreeObject.getCheckedNodes(true);
//2、将这些权限的id和角色的id发给程序
var permission_ids = "";
$.each(nodes,function(){
permission_ids += this.id+",";
});
var rid = $(this).attr("rid");
//3、使用程序保存这个角色对应的权限的值
//写程序;删除对应的东西即可
$.get("${ctp}/permission/role/update?pids="+permission_ids+"&rid="+rid,function(){
alert("权限分配成功");
$('#permissModel').modal("hide");
})
});
后续完成
几个同类的增删改查:
1.项目分类 每个项目属于一类 类别的增删改查
2.项目标签(目前做独立的)
每个分类下有一些标签,小分类(spu)
和分类没联系
经常使用的技巧:
1)抽取页面
2)利用某个按钮获取某个元素设置自定义属性来给回调函数带值
<button uid="${user.id}"></button>
$("#btn").click(function(){
// 用户id
$(this).attr("uid")
})
3)给某个元素绑定属性值
绑定:jQuery.data(element,[key],[value])
获取: 当前jQuery对象.key
4)写一个功能的流程:
- 从登陆注册写起
- 具体某一个功能,分清楚整个跳转逻辑
- 搭出整个跳转流程
- 分析执行功能要给服务器带什么数据 想尽办法把页面带给服务器的数据组装好
- 服务器 收到数据进行增删改查分析 原则:能用mbg生成的dao自带的CRUD就用自带的,不能就给这个dao新增方法
- 梳理清楚流程,脑海中必须有实现出的最终效果
【JavaWeb项目】一个众筹网站的开发(八)后台页面详细设置的更多相关文章
- 【JavaWeb项目】一个众筹网站的开发(二)架构搭建之架构测试
1.dao层和pojo都是使用mbg生成,基本的CRUD以及JavaBean 2.将mbg放在dao层,一旦dao层打包以后mbg就删除掉 一.创建数据库用于测试 数据库名称:scw_0325 SQL ...
- 【JavaWeb项目】一个众筹网站的开发(五)后台用户登录功能
用户模块 1)注册 表单校验,使用校验插件 用户密码需要加密存储 注册成功后来到管理控制台,将用户放在session中,防止以后获取 以后用户经常获取用户id,使用mabatis主键自增策略,保存用户 ...
- 【JavaWeb项目】一个众筹网站的开发(四)后台用户注册功能
重点: 密码加密存储 使用jQuery插件做校验和错误提示等 密码不能明文存储,在数据库中是加密存储的 可逆加密:通过密文使用解密算法得到明文 DES AES 不可逆加密:通过密文,得不到明文 MD5 ...
- 【JavaWeb项目】一个众筹网站的开发(一)架构搭建
本项目是@尚硅谷相关视频的记录. 本项目使用Maven构建,工程架构如下图所示: 一.公司的公共父工程和工具类包 1.父工程 每个公司都有自己的父工程 父工程作用:对公司使用的jar包进行统一管理,别 ...
- 【JavaWeb项目】一个众筹网站的开发(九)邮件开发
Java官方支持邮件开发,Javax-mail jdk中默认没有,需要另外下载 apache的基于Javax-mail开发了commons-mail,更加简单高效,推荐使用 一.电子邮件接收和发送协议 ...
- 【JavaWeb项目】一个众筹网站的开发(六)后台用户权限控制
登陆成功进入控制面板后 左侧的菜单是共同的元素,抽取出来做静态包含 要求必须是按照不同的用户得到不同的菜单 用户做了权限限制,哪个用户能操作哪些内容(链接.按钮.内容) 一.RBAC权限模型 权限管理 ...
- 【JavaWeb项目】一个众筹网站的开发(三)第一个网页
一.bootstrap 本项目采用bootstrap3 bootstrap中文网 https://www.bootcss.com/ 使用bootstrap三步: 1.导入jQuery 2.导入boot ...
- 【JavaWeb项目】一个众筹网站的开发(七)后台用户菜单
mvn命令不能运行: jar-war-pom之间是可以直接写,优先找这个工程,而不是仓库的位置 pom-pom子父关系,需要去仓库中找,我们需要使用<relativePath>../pro ...
- 【SSH网上商城项目实战03】使用EasyUI搭建后台页面框架
转自:https://blog.csdn.net/eson_15/article/details/51312490 前面两节,我们整合了SSH并且抽取了service和action部分的接口,可以说基 ...
随机推荐
- 微信浏览器 video - android适配
阶段一: 直接裸用 video 标签, 安卓 - 会重新弹一个播放层, 和之前video的父盒子错位, 要多丑有多丑, 体验要多烂有多烂. 阶段二: video添加以下属性, 安卓可实现内联播放, 但 ...
- 【leetcode】207. Course Schedule
题目如下: There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may have ...
- 用List和Map排序输出
参考:java的treemap反序输出 int->string string->int java对象数组的概述 List import java.io.*; import java.uti ...
- SQL Server 2014 安装说明
SQL Server 2014 安装说明 本节内容将说明如何通过安装向导在 Windows Server 2012 R2 上安装 SQL Server 2014. 先从 MSDN 网站上下载安装了 S ...
- for循环语句示例
for循环语句示例 一判断/var/目录下所有文件的类型 完整脚本 [root@centos73 ~]# cat shell_scripts/filetype.sh #!/bin/bash #Auth ...
- Python--模块之sys模块、logging模块、序列化json模块、序列化pickle模块
sys模块 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit() sys.path 返回模块的搜索路径,初始化时使用PYTHONPA ...
- px4::init_once();和px4::init(argc, argv, "px4");函数学习
px4::init_once(); void init_once() { _shell_task_id = pthread_self(); ...
- Qt事件学习
一.创建Qt gui应用对应的源码: 点击(此处)折叠或打开 //mylineedit.h #ifndef MYLINEEDIT_H #define MYLINEEDIT_H #include < ...
- stat函数学习
stat函数组 前面介绍的通过ls命令查看到的文件信息,都可以使用stat函数组提取出来• stat函数组– 使用命令man stat查看相关文档• 函数int stat(const char *pa ...
- 工程师技术(三):独立Web站点的快速部署、虚拟Web主机的部署、配置网页内容访问、使用自定Web根目录、配置安全Web服务、部署并测试WSGI站点
一.独立Web站点的快速部署 目标: 本例要求为 http://server0.example.com 配置Web站点,要求如下: 1> 从http://classroom/pub/materi ...