有了笔记一中建立的前台页面框架,以及对于控制层和拦截器的配置之后,只需要对于login.ftl文件进行简单的修改即可改善登录功能。 登录改进1、修改验证码验证的控制层YanzhengmaController.java,修改验证码的验证方式,改用easyui中的异步验证
//验证验证码
@RequestMapping("validatecode")
@ResponseBody
public boolean isyanzhengma(HttpServletRequest request,String yanzhengma) {
HttpSession session = request.getSession(true);
String yanzhengmasession=(String)session.getAttribute("yanzhengma");
boolean flag= false;
if(yanzhengmasession!=null&&yanzhengmasession.equalsIgnoreCase(yanzhengma)){
flag= true;
}
return flag;
}
$("#codeImg").on("click",function(){changeImg()});
var changeImg = function(){
$(codeImg).prop("src","${base}/code/init?temp="+Math.random());
}
$('#code').validatebox({
required: true,
validType: "remote['${base}/code/validatecode','yanzhengma']",
tipPosition:'bottom' ,
deltaX:20
});
2、为login.ftl页面中的表单添加表单验证
也就是为用户名和密码添加非空验证。
<form id="loginForm">
<div>
用户名:<input type="text" id="userName" class="easyui-textbox" required=true/></br>
密 码:<input type="password" id="userPass" class="easyui-textbox" required=true/></br>
验证码:<input type="text" id="code"/>
<img src="${base}/code/init" id="codeImg"/></br>
</div>
</form>
3、登录方法的修改
只有当所有的表单验证通过之后才可以提交内容,进行登录
function user_login(){
var isValid = $("#loginForm").form('validate')
var userNameval = $("#userName").val();
var userPassval = $("#userPass").val();
if(isValid){
$.ajax({
url:"${base}/logincontroller/login",
data:{"userName":userNameval,"userPass":userPassval},
type:"get",
dataType:"json",
success:function(data){
console.log(data);
if(data == 0){
$.messager.alert("提示","用户名或密码错误!");
//重置表单
$("#loginForm").form('reset');
//切换验证码
changeImg()
}else{
$.messager.alert("提示","登录成功");
location.href="${base}/";
}
}
});
}
}
其他的后台验证方法都不需要进行修改。 列表功能改进 之前的列表页面中,需要有两个控制层方法才可以进行一步的数据查询,并且在进行数据列表的时候还需要手动的进行数据的输出,以及分页的配置。而使用了easyui中的分页组件,以及datagrid之后,明显没有那么复杂了。但是,使用easyui中的组件,很多的属性名称必须要与之对应起来,否则无法接受与传送数据。
对于easyui的分页组件中,它在列表发送请求之后,会自动的发送两个参数:①page:当前页,②rows:表示每页显示的条数。所以如果还想继续使用之前的分页模式,就必须将PageUtil.java类中的属性名称进行修改。
1、修改PageUtil.java类
public class PageUtil {
//easyUI的分页默认会发送这样两个固定名字的属性过来,所以为了接收方便,定义如下两个属性。
private int page = 1;
private int rows = 3;
public int getPage() {
return page;
}
public void setPage(int page) {
this.page = page;
}
public int getRows() {
return rows;
}
public void setRows(int rows) {
this.rows = rows;
}
}
同时在进行查询之后,页面中的组件会接收①rows:所有查询出来的数据和②total:数据的总条数两个参数。所以还需要修改BookServiceImpl.java中的分页设置以及返回的内容。并且也没有必要在使用另外ServicePageUtil.java类来进行操作,因为其要求的返回值内容已经非常少了。
@Override
public Map<String, Object> list(Book vo) {
if(vo != null){
if(vo.getBookLabel() != null && !"".equals(vo.getBookLabel())){
String labels = vo.getBookLabel().substring(1);
vo.setLabels(Arrays.asList(labels.split(",")));
}
Map<String,Object> map = new HashMap<String,Object>();
PageHelper.startPage(vo.getPage(), vo.getRows());
List<Book> list = this.bookDAO.findAll(vo);
Page page = (Page) list;
//获取总条数
long total = page.getTotal();
map.put("total", total);
map.put("rows", list);
return map;
}
return null;
}
分页修改好之后,还需要修改控制层的方法,所以需要修改BookController.java,删除show()方法,只保留一个list()方法即可
2、修改BookController.java类
@RequestMapping("list")
@ResponseBody
public Map<String,Object> list(HttpServletRequest request,Model model,Book vo){
if(vo != null){
Integer uid = (Integer) request.getSession().getAttribute("uid");
vo.setUserId(uid);
return this.bookService.list(vo);
}
return null;
}
//添加访问listBooks.ftl文件的路径,因为要在选项中显示listBooks.ftl文件
@RequestMapping("toList")
public String list() {
return "book/listBooks";
}
3、修改listBooks.ftl,并且删除showBooks.ftl文件。由于所有操作都要从listBooks.ftl文件出发,所以先修改列表操作。
<#assign base=request.contextPath />
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
</head>
<body>
<div data-options="region:'center',split:true"">
<#-- 声明数据表格容器 -->
<table id="tbcon"></table>
</div>
<script type="text/javascript">
//初始化数据表格
$("#tbcon").datagrid({
//数据接口
url:"${base}/book/list",
//开启分页
pagination:true,
//可选每页条数
pageList:[3,6,9],
//每页条数,必须设置首选项,否则默认值显示
pageSize:3,
//分页工具栏位置
//pagePosition:'bottom',
//自适应窗口大小
fit:true,
//列属性
columns:[[
{field:'suibian',checkbox:true},
{field:'bookId',title:'书籍ID'},
{field:'bookName',title:'书籍名称'},
{field:'bookAuthor',title:'书籍作者'},
//对于复杂的列,可以通过formatter对其内容进行设置,其方法中,value表示当前的值,row表示该行数据
{field:'bookCover',title:'书籍封面',
formatter: function(value,row,index){
//如下的写法太复杂了,注意只有数字才这么写.
var imgPath ="${base}" + value;
//imgPath = imgPath.replace(/\,/,"")
//console.log(imgPath)
return '<img width="120px" height="60px" border="0" src='+imgPath+'/>';
}
},
{field:'bookPrice',title:'书籍价格'},
{field:'bookType',title:'书籍类型',
formatter: function(value,row,index){
return row.bookType.typeName;
}
},
{field:'bookPress',title:'书籍出版社',
formatter: function(value,row,index){
return row.bookPress.pressName;
}
},
{field:'bookStatus',title:'书籍状态',
formatter: function(value,row,index){
if(row.bookStatus == 1){
return "上架";
}else{
return "下架";
}
}
},
{field:'bookAddTime',title:'书籍上架时间'},
{field:'bookLabel',title:'书籍标签',
formatter: function(value,row,index){
var str = "";
if(null != value && 0 < value.length){
if(-1 != value.indexOf(1)){
str += ",校园";
}
if(-1 != value.indexOf(2)){
str += ",青春";
}
if(-1 != value.indexOf(3)){
str += ",政治";
}
if(-1 != value.indexOf(4)){
str += ",经济";
}
}
if(0 < str.length){
str = str.substr(1)
}
return str;
}
},
{field:'bookDesc',title:'书籍描述'},
{field:'proLocation',title:'作者所在省',
formatter: function(value,row,index){
return row.proLocation.locationName;
}
},
{field:'cityLocation',title:'作者所在市',
formatter: function(value,row,index){
return row.cityLocation.locationName;
}
},
{field:'user',title:'操作用户',
formatter: function(value,row,index){
//console.log(row);
return row.user.userName;
}
}
]],
toolbar: [
{
text:"搜索",
iconCls: 'icon-search',
handler: function(){
//进行条件搜索的方法
user_search()
}
}
]
});
</script>
</body>
</html>
其中列表展示页面,包括了单选、多选、下拉列表、图片、以及多表查询返回的内容的数据展示时,数据的格式化操作。对于分页可以看出,框架一出现,所有的分页操作几乎变成了内置的,而且还是最简化的,不过你如果想使用人家的框架,必须要符合人家的要求。这一点会比较难受。 条件查询 当数据可以展示出来之后,面临的自认就是如何快速定位到想要的数据,所以还需要继续改进条件搜索的方式,也就是实现user_search()方法,并且需要设置相应的查询表格,而在设置过程中,又会接触到另一种下拉列表的生成,在easyui中叫做组合框comoboBox。
1、在显示页面补充条件查询所需要的表格,并且进行格式布局设置
<div class="easyui-layout" data-options="fit:true">
<div data-options="region:'north',split:true"">
<table border="1">
<tr>
<td>书籍名称</td>
<td>
<input name="bookName" id="bookName" class="easyui-textbox">
</td>
</tr>
<tr>
<td>书籍类型</td>
<td>
<input id="bookTypeId" />
</td>
</tr>
<tr>
<td>书籍出版社</td>
<td>
<input id="bookPressId" />
</td>
</tr>
<tr>
<td>文章状态</td>
<td>
<input type="radio" name="bookStatus" value="1"/>上架
<input type="radio" name="bookStatus" value="2"/>下架
</td>
</tr>
<tr>
<td>发布日期</td>
<td>
<input id="startTime" name="startTime" class="easyui-datebox">
--><input id="endTime" name="endTime" class="easyui-datebox">
</td>
</tr>
<tr>
<td>文章标签</td>
<td>
<input type="checkbox" name="bookLabel" value="1"/>校园
<input type="checkbox" name="bookLabel" value="2"/>青春
<input type="checkbox" name="bookLabel" value="3"/>政治
<input type="checkbox" name="bookLabel" value="4"/>经济
</td>
</tr>
</table>
</div>
<div data-options="region:'center',split:true"">
<#-- 声明数据表格容器 -->
<table id="tbcon"></table>
</div>
</div>
其中根据类型搜索以及根据出版社搜索,这两个操作都是需要生成对应的下拉列表,由于需要从数据库中读取,并且会自动生成,而且其默认不会选中value值为“-1”的"<option>”,所以还需要进行修改book-mapper.xml中之前的类型出版社条件查询的条件,并且还需要在其各自的业务层实现类中,设置第一个默认被选中的值,操作如下: ①修改BookTypeServiceImpl.java类中的内容
@Override
public List<BookType> list() {
List<BookType> booktype = this.typeDAO.findAll();
BookType type = new BookType();
type.setTypeName("--请选择--");
type.setTypeId(0);
booktype.add(0, type);
return booktype;
}
②修改BookPressServiceImpl.java类的内容
@Override
public List<BookPress> list() {
List<BookPress> bookpress = this.pressDAO.findAll();
BookPress press = new BookPress();
press.setPressName("--请选择--");
press.setPressId(0);
bookpress.add(0, press);
return bookpress;
}
③修改book-mapper.xml文件中的判断条件
<if test=" null != bookTypeId and 0 != bookTypeId"> AND p.book_type_id = #{bookTypeId}</if>
<if test=" null != bookPressId and 0 != bookPressId"> AND p.book_press_id = #{bookPressId}</if>
④为类型和出版社设置值,并且建立user_search()方法
$("#bookTypeId").combobox({
url:'${base}/booktype/listAll',
valueField:'typeId',
textField:'typeName'
});
$("#bookPressId").combobox({
url:'${base}/bookpress/listAll',
valueField:'pressId',
textField:'pressName'
});
//搜索
function user_search(search_type) {
var bookName = $("#bookName").textbox("getValue");
var bookTypeId = $("#bookTypeId").combobox("getValue");
var bookPressId = $("#bookPressId").combobox("getValue");
var bookStatus = $("[name='bookStatus']:checked").val();
var startTime = $("#startTime").datebox("getValue");
var endTime = $("#endTime").datebox("getValue");
var labels = "";
$("[name='bookLabel']:checked").each(function(){
labels += "," + $(this).val();
});
var data = {
bookName:bookName,
bookTypeId:bookTypeId,
bookPressId:bookPressId,
bookStatus:bookStatus,
startTime:startTime,
endTime:endTime,
bookLabel:labels,
};
//考虑到修改成功之后可能需要在原页面停留 null和undefined是一致的
if(null == search_type ){
search_type = "load"
}
$("#tbcon").datagrid(search_type,data);
}
其中的作用已经描述的非常清楚了。至此,条件查询以及列表展示都已经修改完成。然后开始设置添加数据,和修改数据,以及状态修改,删除,批量删除操作。
删除和批量删除操作使用的是同一个方法,所以在此处将其合并,不在分开使用,并且,也不需要自己手动的设置全选反选的操作,只需要在datagrid初始化的columns中添加新的行“ {field:'suibian',checkbox:true}”,其中的“field”名字随意,如果要添加其他的与具体数据库列无关之类的操作,也可以按照类似的方式。 批删操作 首先需要在datagrid中的toolbar中继续添加一个新的按钮
'-',{
text:"删除",
iconCls: 'icon-remove',
handler: function(){
del_all();
}
注意,按钮之间使用“ '_' ”间隔,然后实现del_all()方法
//批量删除操作
function del_all() {
//是否选中了数据
var dataarrry = $("#tbcon").datagrid("getSelections");
if (0 == dataarrry.length) {
$.messager.alert("提示", "请至少选中一条数据");
} else {
$.messager.confirm('确认','您确认想要删除记录吗?',function(bool){
if (bool){
//删除操作
var ids = "";
for (var i = 0; i < dataarrry.length; i++) {
ids = ids + "," + dataarrry.bookId;
}
if (0 < ids.length) {
ids = ids.substr(1);
}
$.ajax({
url:"${base}/book/rm",
data:{ids:ids},
type:"post",
success:function(data) {
user_search();
}
});
}
});
}
}
用户的上下架操作 在datagrid的toolbar中添加新的工具
,'-',{
text:"更新状态",
iconCls: 'icon-update',
handler: function(){
edit_status();
}
}
编辑edit_status()方法
//修改状态操作
function edit_status() {
var dataarrry = $("#tbcon").datagrid("getSelections");
if (1 == dataarrry.length) {
var bookid = dataarrry[0].bookId;
var status = 0;
if(1 == dataarrry[0].bookStatus){
status = 2;
}else{
status = 1
}
$.ajax({
url:"${base}/book/editStatus",
data:{bookId:bookid,bookStatus:status},
type:"post",
dataType:"json",
success:function(data) {
user_search("reload");
}
});
} else {
$.messager.alert("提示", "只能更新一条数据");
}
}
本来希望为每一行数据都添加一个按钮,然后通过onclick()事件来完成操作的,可是,加了linkbutton的方式不太懂,而且即使加上了,按钮在主题中并不会显示为一个button的样式。而下载图片的判断与此操作完全相同,所以略过。 增加和修改数据功能 在listBooks.ftl文件中添加datagrid中的toolBar中添加新的工具
,'-',{
text:"添加",
iconCls: 'icon-add',
handler: function(){
open_add_dialog();
}
},'-',{
text:"修改",
iconCls: 'icon-edit',
handler: function(){
open_edit_dialog()
}
}
①完成open_add_dialog()方法
function open_add_dialog(){
var add_dialog = $("<div></div>").dialog({
title:"添加信息",
width:500,
height:380,
modal:true,
onClose:function(){
$(this).dialog("destroy");
},
href:"${base}/book/toAddftl",
buttons:[
{
text:'保存',
handler:function(){
//ajax提交表单textbox textbox-invalid
data_sync();
$('#add_my_form').form('submit', {
url:"${base}/book/add",
type:"post",
success: function(data){
//回掉函数中关闭对话框
add_dialog.dialog("destroy");
//刷新datagrid列表
user_search();
}
});
}
},{
text:'关闭',
handler:function(){
add_dialog.dialog("destroy");
}
}
]
});
}
然后修改addBook.ftl文件,该页面不需要提交表单,所以不需要提交按钮,同时下拉框可以使用easyui的组合框读取完成自动设置相应的内容,与listBooks.ftl文件中的条件查询中的下拉框生成类似。 ②完成open_edit_dialog()方法
function open_edit_dialog(){
//是否选中了数据
var edit_arrry = $("#tbcon").datagrid("getSelections");
if (1 == edit_arrry.length) {
var bookId = edit_arrry[0].bookId;
var edit_dialog = $("<div></div>").dialog({
title:"编辑信息",
width:500,
height:380,
modal:true,
onClose:function(){
$(this).dialog("destroy");
},
href:"${base}/book/editPre?bookId=" + bookId,
buttons:[{
text:'保存',
handler:function(){
//ajax提交表单
data_sync();
$('#edit_my_form').form('submit', {
url:"${base}/book/edit",
success: function(data){
//回掉函数中关闭对话框
edit_dialog.dialog("destroy");
//刷新datagrid列表
user_search("reload");
}
});
}
},{
text:'关闭',
handler:function(){
edit_dialog.dialog("destroy");
}
}]
});
} else {
$.messager.alert('提示', '只能编辑一条数据');
}
}
至此,基本的内容改造,就已经完成了。在改造的过程中发现,真正的MVC中,前后台是完全独立的,修改前台页面的展示,并不会修改很多的后天代码,只是参数不合适的时候,才可能出现,不过这也可能是设计的不合理所造成的耦合。
|