JavaEE练习项目–快递e栈(第五天)
内容 | 地址 |
---|---|
需求分析 | 链接地址 |
建表,工具类书写 | 链接地址 |
Jdbc工具类 | 链接地址 |
三层架构,阿里云短信 | 链接地址 |
前端Ajax | 链接地址 |
前面我们已经将后端的代码都编写完成了,实际上对于一个人而言,不能在独立完成后端逻辑之后就能去睡大觉了,前端也得去写啊!
本系统的使用Ajax的返回来降低前后端的耦合度,使用layui工具来简化前端的开发难度。
登录功能
这是之前写好的登录功能,我们知道前端界面只是为了将结果展示的更好看一点,我们可以直接通过网址来验证登录功能
@ResponseBody("/admin/login.do")
public String courierLogin(HttpServletRequest request,HttpServletResponse response){
//1. 接参数
String username = request.getParameter("username");
String password = request.getParameter("password");
Message msg = null;
Courier courier=null;
if ((courier=CourierService.login(username,password))!=null){
//{status:0,result:"登录成功"}
msg = new Message(0,"登录成功");
//登录时间 和 ip的更新
CourierService.updateLoginTime(username);
request.getSession().setAttribute("adminUserName",courier);
WebUtil.setLoginUser(courier);
}else {
msg = new Message(-1, "登录失败");
}
return WebUtil.toJson(msg);
}
登录成功
登录失败
前端模板,网上很多,随便找一份
代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="assets/css/layui.css">
<link rel="stylesheet" href="assets/css/login.css">
<link rel="icon" href="/favicon.ico">
<title>快递e栈管理后台</title>
</head>
<body class="login-wrap">
<div class="login-container">
<h3>快递e栈后台管理</h3>
<form class="login-form" action="index.html">
<div class="input-group">
<input type="text" id="username" class="input-field">
<label for="username" class="input-label">
<span class="label-title">用户名</span>
</label>
</div>
<div class="input-group">
<input type="password" id="password" class="input-field">
<label for="password" class="input-label">
<span class="label-title">密码</span>
</label>
</div>
<button type="submit" class="login-button">登录<i class="ai ai-enter"></i></button>
</form>
</div>
</body>
<script src="assets/layui.js"></script>
<script src="js/index.js" data-main="login"></script>
<script src="js/login.js" data-main="login"></script>
</html>
这里是一个表单,然后提交之后跳转到index.html主页,我们可以在form表单的onsubmit的时候触发我们的登录方法,由于表单提交之后会刷新数据,对于我们登录失败时,会把数据给刷新,所以我们应该让这个表单无法提交,总是return false,使用我们自己的方式来跳转界面而不是表单来跳转。
给相应的字段添加id标识,先正则验证表单,然后发出Ajax请求,最后判断返回结果如果登录成功,跳转到index.html,失败则可以看到layer.msg()的登录失败的提示!
$("#form").submit(function () {
if (!checkLoginUsername($("#username").val()) ||
!checkPassword($("#password").val())) {
return false;
}
//1.先使用layer,弹出load(提示加载中...)
var windowId = layer.load();
//2.ajax与服务器交互
$.post("/admin/login.do", {
username: $("#username").val(),
password: $("#password").val()
}, function (data) {
//3.关闭load窗口
layer.close(windowId);
//4.将服务器回复的结果进行显示
layer.msg(data.result);
if (data.status === 0) {
$(window).attr('location', 'index.html');
}
}, "JSON");
return false;
});
效果演示
主页数据
我们看到控制台有很多数据,当然这些数据不是写死在页面上的。
数据库
这些数据都是数据库查询出来的,效果是主页一加载就发出Ajax请求,然后将查询结果返回给主页。
js代码
查询方法没有参数,所以参数列表为null
$(function () {
$.getJSON("/express/console.do", null, function (data) {
$("#totalExpress").html(data.data[0].totalExpress);
$("#dayExpress").html(data.data[0].dayExpress);
$("#needTakeExpress").html(data.data[0].needTakeExpress);
$("#insertExpress").html(data.data[0].insertExpress);
});
$.getJSON("/user/console.do", null, function (data) {
$("#totalUser").html(data.data[0].totalUser);
$("#dayUser").html(data.data[0].dayUser);
});
$.getJSON("/courier/console.do", null, function (data) {
$("#totalCourier").html(data.data[0].totalCourier);
$("#dayCourier").html(data.data[0].dayCourier);
});
});
显示所有
好几千的快递,所以我们需要分页,分页的手段有很多,这里使用BootStrapTable的分页功能进行分页。
创建分页对象
由于我们数据库中的一些数据并不是我们要展示的,比如录入人电话原来是通过id外键关联的,状态在数据库中是0和1,所以我们需要创建一个对象
除了添加几个字段以外,其他的成员变量类型都差不多,注意的是时间类型要转换成String,因为BootStrapTable会对时间类型这种类型有独特的样式处理,这里我们只需要展示String的字符串类型即可
public class BootStrapTableExpress {
private int id;
private String number;
private String username;
private String userPhone;
private String company;
private String code;
private String inTime;
private String outTime;
private String status;
private String sysPhone;
public BootStrapTableExpress() {
}
public BootStrapTableExpress(int id, String number, String username, String userPhone, String company, String code, String inTime, String outTime, String status, String sysPhone) {
this.id = id;
this.number = number;
this.username = username;
this.userPhone = userPhone;
this.company = company;
this.code = code;
this.inTime = inTime;
this.outTime = outTime;
this.status = status;
this.sysPhone = sysPhone;
}
控制层逻辑
对于分页有两个重要的参数,查询数据的起始索引值和当前页要查询的数据量,然后将原来的Express的对象的属性转换为我们要展示的值,比如status=0表示待取件,1表示已取件。
@ResponseBody("/express/list.do")
public String list(HttpServletRequest request, HttpServletResponse response){
//1. 获取查询数据的起始索引值
int offset = Integer.parseInt(request.getParameter("offset"));
//2. 获取当前页要查询的数据量
int pageNumber = Integer.parseInt(request.getParameter("pageNumber"));
//3. 进行查询
List<Express> list = ExpressService.findAll(true, offset, pageNumber);
List<BootStrapTableExpress> list2 = new ArrayList<>();
for(Express e:list){
String inTime = WebUtil.format(e.getInTime());
String outTime = e.getOutTime()==null?"未出库":WebUtil.format(e.getOutTime());
String status = e.getStatus()==0?"待取件":"已取件";
String code = e.getCode()==null?"已取件":e.getCode();
BootStrapTableExpress e2 = new BootStrapTableExpress(e.getId(),e.getNumber(),e.getUsername(),e.getUserPhone(),e.getCompany(),code,inTime,outTime,status,e.getSysPhone());
list2.add(e2);
}
List<Map<String, Integer>> console = ExpressService.console();
Integer total = console.get(0).get("totalExpress");
//4. 将集合封装为 bootstrap-table识别的格式
ResultData<BootStrapTableExpress> data = new ResultData<>();
data.setRows(list2);
data.setTotal(total);
return WebUtil.toJson(data);
}
前端代码
代码很长,但是这是BootStrap规定的没办法呀!
- 定义一个table标签,给一个id标识,其他的一切都交给BootStrapTable处理
- pageNumber默认值是1,也就是展示第一页,合乎情理。
sidePagination: 'server'
表示是服务器分页,什么意思呢?我们分页有两种情况:服务器每次查询一页的数据让BootStrapTable来展示;服务器查询所有数据,让BootStrapTable,来调整每页的数据。对于数据量比较大的情况,知道用哪一种了吧。- 缺乏查询的方法,后序实现。
<body>
<table id="courier_list"></table>
<script>
$(function () {
$("#courier_list").bootstrapTable({
url: "/courier/list.do",
striped: true,
pageNumber: 1,
pagination: true,
sidePagination: 'server',
pageSize: 8,
pageList: [5, 10, 20],
showRefresh: true,
queryParams: function (params) {
var temp = {
offset: params.offset,
pageNumber: params.limit
};
return temp;
},
columns: [
{
title: "编号",
field: "id",
sortable: true
},
{
title: "姓名",
field: "name",
sortable: true
},
{
title: "手机号码",
field: "sysPhone",
sortable: true
},
{
title: "身份证",
field: "idCardNumber",
sortable: true
},
{
title: "派件数",
field: "sendNumber",
sortable: true
},
{
title: "注册时间",
field: "registerTime",
sortable: true
},
{
title: "上次登录时间",
field: "loginTime",
sortable: true
},
]
});
});
</script>
</body>
</html>
快递录入
基本逻辑还是表单提交数据,然后Ajax请求响应,嗯!
js代码
<script>
$(function () {
$("#form").submit(function () {
if (!checkExpressNumber($("input:eq(0)").val()) ||
!checkerUsername($("input:eq(2)").val()) ||
!checkPhone($("input:eq(3)").val())) {
return false;
}
var windowId = layer.load();
var number = $("input:eq(0)").val();
var company = $("input:eq(1)").val();
var username = $("input:eq(2)").val();
var userPhone = $("input:eq(3)").val();
$.getJSON("/express/insert.do", {
number: number,
company: company,
username: username,
userPhone: userPhone
}, function (data) {
layer.close(windowId);
if (data.status === 0) {
$("input").val("");
$("input:eq(1)").val("顺丰速运");
}
if (data.status === -1) {
}
layer.msg(data.result);
});
return false;
});
});
</script>
快递修改和删除
这两个方法都差不多,有一些小区别:
- 修改时,页面数据应该可以动,删除时数据不能动,只是负责展示
- 修改要提交修改后的数据,而删除只需要提供id即可
查询
删除
删除界面查询时,数据都是不能动的,只负责展示
黄忠快递-1
其他功能大部分都差不多的,就动图演示一波!