新峰商城订单从生成到处理结束,主要以下几个流程:
(1)提交订单(商城用户发起)
(2)订单入库(后台逻辑)
(3)支付订单(商城用户发起)
(4)订单处理(确认订单、取消订单、修改订单)
一、订单确认的前置步骤
通过购物车页面的结算按钮进入订单确认页面,如果购物车中无数据,则提示“购物车中无数据”,数据正常则执行settle()方法并进跳转,跳转路径为/shop-cart/settle,并在此控制器方法中进行订单确认页面中数据的查询和整合,其代码如下所示:
<div class="order_button fr">
<th:block th:if="${itemsTotal == 0}">
<input class="order_button_c" type="button" name="tip"
onclick="tip()"
value="去结算"/>
</th:block>
<th:block th:unless="${itemsTotal == 0}">
<input class="order_button_d" type="button" name="settle"
onclick="settle()"
value="去结算"/>
</th:block>
</div>
其中tip()方法和settle()方法代码如下所示:
/**
* 购物车中数量为0时提示
*/
function tip() {
Swal.fire({
text: "购物车中无数据,无法结算",
icon: "error",iconColor:"#f05b72",
});
}
/**
* 跳转至结算页面
*/
function settle() {
window.location.href = '/shop-cart/settle'
}
二、订单确认页面显示主要数据
订单确认页不同于购物车中商品数据,还包括用户数据和支付数据,其详细信息如下图所示:
三、订单确认页面控制层
在ShoppingCartController类中增加settlePage()方法,用于处理/shop-cart/settle请求,并将数据带到订单确认页面进行渲染,代码如下所示:
@GetMapping("/shop-cart/settle")
public String settlePage(HttpServletRequest request,
HttpSession httpSession) {
int priceTotal = 0;
//从session中获取用户信息,包括收货信息
NewBeeMallUserVO user = (NewBeeMallUserVO) httpSession.getAttribute(Constants.MALL_USER_SESSION_KEY);
List<NewBeeMallShoppingCartItemVO> myShoppingCartItems = newBeeMallShoppingCartService.getMyShoppingCartItems(user.getUserId());
if (CollectionUtils.isEmpty(myShoppingCartItems)) {
//无数据则不跳转至结算页
return "/shop-cart";
} else {
//总价
for (NewBeeMallShoppingCartItemVO newBeeMallShoppingCartItemVO : myShoppingCartItems) {
priceTotal += newBeeMallShoppingCartItemVO.getGoodsCount() * newBeeMallShoppingCartItemVO.getSellingPrice();
}
if (priceTotal < 1) {
NewBeeMallException.fail("购物项价格异常");
}
}
request.setAttribute("priceTotal", priceTotal);
request.setAttribute("myShoppingCartItems", myShoppingCartItems);
return "mall/order-settle";
}
此方法查询商品信息并计算总价,然后将priceTotal和myShoppingCartItems两个对象放入request请求中,再跳转到order-settle页面。
四、订单确认页面制作
在resources/templates/mall目录中新增订单确认页order-settle.html,模板代码如下所示:
<!-- Copyright (c) 2019-2020 十三 all rights reserved. -->
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head th:replace="mall/header::head-fragment('NewBee商城-订单结算','order-detail')">
</head>
<link th:href="@{/mall/css/bootstrap-modal.css}" rel="stylesheet">
<body>
<header th:replace="mall/header::header-fragment"></header>
<!-- nav -->
<nav th:replace="mall/header::nav-fragment"></nav>
<!-- personal -->
<div id="personal">
<div class="self-info center">
<!-- sidebar -->
<div th:replace="mall/personal-sidebar::sidebar-fragment"></div>
<div class="intro fr">
<div class="uc-box uc-main-box">
<div class="uc-content-box order-view-box">
<div class="box-hd">
<h1 class="title">填写并核对订单信息</h1>
<div class="more clearfix">
<div class="actions">
<a id="saveOrder" class="btn btn-small btn-primary" title="提交订单">提交订单</a>
</div>
</div>
</div>
<div class="box-bd">
<div class="uc-order-item uc-order-item-pay">
<div class="order-detail">
<div class="order-summary">
<div class="order-progress">
<ol class="progress-list clearfix progress-list-5">
<li class="step step-done">
<div class="progress"><span class="text">购物车</span></div>
<div class="info"></div>
</li>
<li class="step step-active">
<div class="progress"><span class="text">下单</span></div>
<div class="info"></div>
</li>
<li class="step">
<div class="progress"><span class="text">付款</span></div>
<div class="info"></div>
</li>
<li class="step">
<div class="progress"><span class="text">出库</span></div>
<div class="info"></div>
</li>
<li class="step">
<div class="progress"><span class="text">交易成功</span></div>
<div class="info"></div>
</li>
</ol>
</div>
</div>
<table class="order-items-table">
<tbody>
<th:block th:each="item : ${myShoppingCartItems}">
<tr>
<td class="col col-thumb">
<div class="figure figure-thumb">
<a target="_blank" th:href="@{'/goods/detail/'+${item.goodsId}}">
<img th:src="@{${item.goodsCoverImg}}"
width="80" height="80" alt="">
</a>
</div>
</td>
<td class="col col-name">
<p class="name">
<a target="_blank" th:href="@{'/goods/detail/'+${item.goodsId}}"
th:text="${item.goodsName}">newbee</a>
</p>
</td>
<td class="col col-price"><p class="price"
th:text="${item.sellingPrice+'元 x '+item.goodsCount}">
1299元 × 1</p></td>
<td class="col col-actions">
</td>
</tr>
</th:block>
</tbody>
</table>
</div>
<div id="editAddr" class="order-detail-info">
<h3>收货信息</h3>
<table class="info-table">
<tbody>
<tr>
<th>收货地址:</th>
<td class="user_address_label"
th:text="${session.newBeeMallUser.address==''?'无':session.newBeeMallUser.address}">
newbee
</td>
</tr>
</tbody>
</table>
<div class="actions">
<a class="btn btn-small btn-line-gray J_editAddr"
href="javascript:openUpdateModal();">修改</a>
</div>
</div>
<div id="editTime" class="order-detail-info">
<h3>支付方式</h3>
<table class="info-table">
<tbody>
<tr>
<th>支付方式:</th>
<td>在线支付</td>
</tr>
</tbody>
</table>
<div class="actions">
</div>
</div>
<div class="order-detail-total">
<table class="total-table">
<tbody>
<tr>
<th>商品总价:</th>
<td><span class="num" th:text="${priceTotal+'.00'}">1299.00</span>元</td>
</tr>
<tr>
<th>运费:</th>
<td><span class="num">0</span>元</td>
</tr>
<tr>
<th class="total">应付金额:</th>
<td class="total"><span class="num" th:text="${priceTotal+'.00'}">1299.00</span>元
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="personalInfoModal" tabindex="-1" role="dialog"
aria-labelledby="personalInfoModalLabel">
<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>
<h6 class="modal-title" id="personalInfoModalLabel">地址修改</h6>
</div>
<div class="modal-body">
<form id="personalInfoForm">
<div class="form-group">
<input type="hidden" id="userId" th:value="${session.newBeeMallUser.userId}">
<label for="address" class="control-label">收货地址:</label>
<input type="text" class="form-control" id="address" name="address"
placeholder="请输入收货地址" th:value="${session.newBeeMallUser.address}"
required="true">
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary" id="saveButton">确认</button>
</div>
</div>
</div>
</div>
<div class="clear"></div>
</div>
</div>
<div th:replace="mall/footer::footer-fragment"></div>
<!-- jQuery -->
<script th:src="@{/admin/plugins/jquery/jquery.min.js}"></script>
<script th:src="@{/mall/js/search.js}" type="text/javascript"></script>
<script th:src="@{/admin/plugins/sweetalert2/sweetalert2.all.min.js}"></script>
<script th:src="@{/mall/js/bootstrap3.js}"></script>
<script type="text/javascript">
$('#saveOrder').click(function () {
var userAddress = $(".user_address_label").html();
if (userAddress == '' || userAddress == '无') {
Swal.fire({
text: "请填写收货信息",
icon: "error",iconColor:"#f05b72",
});
return;
}
if (userAddress.trim().length < 10) {
Swal.fire({
text: "请输入正确的收货信息",
icon: "error",iconColor:"#f05b72",
});
return;
}
window.location.href = '../saveOrder';
});
function openUpdateModal() {
$('#personalInfoModal').modal('show');
}
//绑定modal上的保存按钮
$('#saveButton').click(function () {
var address = $("#address").val();
var userId = $("#userId").val();
var data = {
"userId": userId,
"address": address
};
$.ajax({
type: 'POST',//方法类型
url: '/personal/updateInfo',
contentType: 'application/json',
data: JSON.stringify(data),
success: function (result) {
if (result.resultCode == 200) {
$('#personalInfoModal').modal('hide');
window.location.reload();
} else {
$('#personalInfoModal').modal('hide');
Swal.fire({
text: result.message,
icon: "error",iconColor:"#f05b72",
});
}
;
},
error: function () {
Swal.fire({
text: '操作失败',
icon: "error",iconColor:"#f05b72",
});
}
});
});
</script>
</body>
</html>
此页面中主要渲染的数据有收货信息、商品信息、价格信息等数据,收货信息直接读取session对象中的数据,商品信息获取同购物车中的商品数据获取类似,页面读取myShoppingCartItems数据,使用th:each循环语法将商品信息进行渲染。价格信息中运费为0,总价字段直接读取priceTotal字段。