订单生成后在个人中心的订单列表中就可以看到各种状态的订单,此文简述订单列表的制作。
一、订单列表数据格式
订单列表OrderListVO对象编码如下所示:
/**
* 订单列表页面VO
*/
public class NewBeeMallOrderListVO implements Serializable {
private Long orderId;
private String orderNo;
private Integer totalPrice;
private Byte payType;
private Byte orderStatus;
private String orderStatusString;
private String userAddress;
private Date createTime;
private List<NewBeeMallOrderItemVO> newBeeMallOrderItemVOS;
在此List对象中即有订单表中的字段,也有订单项表中的字段,包括订单状态、订单交易时间、订单总价、商品标题、商品预览图、商品价格等属性,一个订单可含有多个订单项,所以其中也有一订单项VO列表对象。
二、订单列表数据的获取
在OrderService业务类中新增getMyOrders()方法,代码如下所示:
@Override
public PageResult getMyOrders(PageQueryUtil pageUtil) {
int total = newBeeMallOrderMapper.getTotalNewBeeMallOrders(pageUtil);
List<NewBeeMallOrder> newBeeMallOrders = newBeeMallOrderMapper.findNewBeeMallOrderList(pageUtil);
List<NewBeeMallOrderListVO> orderListVOS = new ArrayList<>();
if (total > 0) {
//数据转换 将实体类转成vo
orderListVOS = BeanUtil.copyList(newBeeMallOrders, NewBeeMallOrderListVO.class);
//设置订单状态中文显示值
for (NewBeeMallOrderListVO newBeeMallOrderListVO : orderListVOS) {
newBeeMallOrderListVO.setOrderStatusString(NewBeeMallOrderStatusEnum.getNewBeeMallOrderStatusEnumByStatus(newBeeMallOrderListVO.getOrderStatus()).getName());
}
List<Long> orderIds = newBeeMallOrders.stream().map(NewBeeMallOrder::getOrderId).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(orderIds)) {
List<NewBeeMallOrderItem> orderItems = newBeeMallOrderItemMapper.selectByOrderIds(orderIds);
Map<Long, List<NewBeeMallOrderItem>> itemByOrderIdMap = orderItems.stream().collect(groupingBy(NewBeeMallOrderItem::getOrderId));
for (NewBeeMallOrderListVO newBeeMallOrderListVO : orderListVOS) {
//封装每个订单列表对象的订单项数据
if (itemByOrderIdMap.containsKey(newBeeMallOrderListVO.getOrderId())) {
List<NewBeeMallOrderItem> orderItemListTemp = itemByOrderIdMap.get(newBeeMallOrderListVO.getOrderId());
//将NewBeeMallOrderItem对象列表转换成NewBeeMallOrderItemVO对象列表
List<NewBeeMallOrderItemVO> newBeeMallOrderItemVOS = BeanUtil.copyList(orderItemListTemp, NewBeeMallOrderItemVO.class);
newBeeMallOrderListVO.setNewBeeMallOrderItemVOS(newBeeMallOrderItemVOS);
}
}
}
}
PageResult pageResult = new PageResult(orderListVOS, total, pageUtil.getLimit(), pageUtil.getPage());
return pageResult;
}
这里定义了getMyOrders()方法并传入PageUtil对象作为参数。PageUtil对象中有分页参数和用户的userId,并且通过SQL语句查询出当前userId下的订单列表数据和每个订单所关联的订单项列表数据。之后填充数据,即将相关字段封装到NewBeeMallOrderListVO对象中,并将封装好的List对象返回。
在OrderController控制类中新增OrderListPage()方法,代码如下所示:
@GetMapping("/orders")
public String orderListPage(@RequestParam Map<String, Object> params, HttpServletRequest request, HttpSession httpSession) {
NewBeeMallUserVO user = (NewBeeMallUserVO) httpSession.getAttribute(Constants.MALL_USER_SESSION_KEY);
params.put("userId", user.getUserId());
if (ObjectUtils.isEmpty(params.get("page"))) {
params.put("page", 1);
}
params.put("limit", Constants.ORDER_SEARCH_PAGE_LIMIT);
//封装我的订单数据
PageQueryUtil pageUtil = new PageQueryUtil(params);
request.setAttribute("orderPageResult", newBeeMallOrderService.getMyOrders(pageUtil));
request.setAttribute("path", "orders");
return "mall/my-orders";
}
该方法首先将分页参数和当前用户的userId封装到PageQueryUtil对象中并调用了业务层的方法。然后把当前用户的订单数据按照不同的分页参数查询出来并将返回结果放到request对象中。最后跳转到mall目录下的my-orders.html模板页面进行数据渲染。
三、订单列表页面渲染
在resources/templates/mall目录中新增模板my-orders.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商城-订单列表','my-orders')">
</head>
<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-list-box">
<div class="box-hd">
<h1 class="title">我的订单
<small>请谨防钓鱼链接或诈骗电话,<a href="##">了解更多></a>
</small>
</h1>
</div>
<div class="box-bd">
<div id="J_orderList">
<ul class="order-list">
<th:block th:if="${#lists.isEmpty(orderPageResult.list)}">
<img style="margin-top: 16px;"
th:src="@{/mall/image/null-content.png}">
<small><a th:href="@{/index}"> 去购物></a>
</small>
</th:block>
<th:block th:unless="${#lists.isEmpty(orderPageResult.list)}">
<th:block th:each="order : ${orderPageResult.list}">
<li class="uc-order-item uc-order-item-list">
<div class="order-detail">
<div class="order-summary">
<th:block th:if="${order.orderStatus<0}">
<div class="order-status-closed">
</th:block>
<th:block th:if="${order.orderStatus==0}">
<div class="order-status-need-pay">
</th:block>
<th:block th:if="${order.orderStatus>0}">
<div class="order-status-success">
</th:block>
<th:block th:text="${' '+order.orderStatusString}"></th:block>
</div>
</div>
<table class="order-detail-table">
<thead>
<tr>
<th class="col-main"><p class="caption-info">
下单时间:<th:block th:text="${#dates.format(order.createTime, 'yyyy-MM-dd HH:mm:ss')}">02月07日</th:block>
<span class="sep">|</span>订单号:<a
th:href="@{${'/orders/'+order.orderNo}}"
th:text="${order.orderNo}">201908121807</a></p></th>
<th class="col-sub"><p class="caption-price">应付金额:<span
class="num"
th:text="${order.totalPrice+'.00'}">1299.00</span>元
</p></th>
</tr>
</thead>
<tbody>
<tr>
<td class="order-items">
<ul class="goods-list">
<th:block
th:each="item : ${order.newBeeMallOrderItemVOS}">
<li>
<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>
<p class="name"><a target="_blank"
th:href="@{'/goods/detail/'+${item.goodsId}}"
th:text="${item.goodsName}">newbee</a>
</p>
<p class="price"
th:text="${item.sellingPrice+'元 x '+item.goodsCount}">
13元 × 1</p></li>
</th:block>
</ul>
</td>
<td class="order-actions"><a class="btn btn-small btn-line-gray"
th:href="@{${'/orders/'+order.orderNo}}">订单详情</a>
</td>
</tr>
</tbody>
</table>
</div>
</li>
</th:block>
</th:block>
</ul>
</div>
<th:block th:unless="${#lists.isEmpty(orderPageResult.list)}">
<div id="J_orderListPages">
<div class="newbee-pagenavi">
<th:block th:if="${orderPageResult.currPage-2 >=1}"><a
class="numbers"
th:href="@{'/orders?page=' + ${orderPageResult.currPage-2}}"
th:text="${orderPageResult.currPage -2}">1</a>
</th:block>
<th:block th:if="${orderPageResult.currPage-1 >=1}"><a
class="numbers"
th:href="@{'/orders?page=' + ${orderPageResult.currPage-1}}"
th:text="${orderPageResult.currPage -1}">1</a>
</th:block>
<a href="##" class="numbers current" th:text="${orderPageResult.currPage}">1</a>
<th:block th:if="${orderPageResult.currPage+1<=orderPageResult.totalPage}"><a
class="numbers"
th:href="@{'/orders?page=' + ${orderPageResult.currPage+1}}"
th:text="${orderPageResult.currPage +1}">1</a></th:block>
<th:block th:if="${orderPageResult.currPage+2<=orderPageResult.totalPage}"><a
class="numbers"
th:href="@{'/orders?page=' + ${orderPageResult.currPage+2}}"
th:text="${orderPageResult.currPage +2}">1</a></th:block>
</div>
</div>
</th:block>
</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>
</body>
</html>
在该页面中主要进行了两部分的数据读取和渲染,分别是订单数据列表渲染和分页区域的渲染。在订单列表区域和分页功能区域对应的位置读取orderPageResult对象中的list数据和分页数据。list数据为订单列表数据。使用th:each循环语法将订单状态、订单交易时间、订单总价、商品标题字段、商品预览图字段、商品价格字段、商品购买数量字段渲染出来。在渲染商品信息的时候用到了一个th:each循环语法和一个a标签。在点击对应按钮后会跳转到订单详情页面。
根据分页字段当前页码currPage、总页码totalPage将下方的分页按钮渲染出来。这里的分页并没有借助插件来实现,而是通过自行编码的方式来生成。