一、商品详情页与购物车对接:

1.1 新建zyg-page-web工程:

在resources/templates/item.html文件中添加如下代码:

  1. <div class="summary-wrap">
  2. <div class="fl title">
  3. <div class="control-group">
  4. <div class="controls">
  5. <input autocomplete="off" type="text" value="1" id="num" minnum="1" class="itxt" />
  6. <a href="javascript:void(0)" class="increment plus">+</a>
  7. <a href="javascript:void(0)" class="increment mins">-</a>
  8. </div>
  9. </div>
  10. </div>
  11. <div class="fl">
  12. <ul class="btn-choose unstyled">
  13. <li>
  14. <a href="javascript:;" target="_blank"
  15. class="sui-btn btn-danger addshopcar"
  16. onclick="addCart()"
  17. >加入购物车</a>
  18. </li>
  19. </ul>
  20. </div>
  21. </div>
  22. //添加到购物车
  23. function addCart(){
  24. let itemId = sku.id + "";
  25. let num = $("#num").val();
  26. location.href = "http://cart.zeyigou.com/cart/addCart?itemId=1420726543731773441&num="+num;
  27. }

注意:因为我们使用了nginx处理了跨域请求,所以,这里遇不到跨域问题,后面项目中再来处理!

二、订单管理功能实现:

2.1 新建两个模块zyg-order-interface与zyg-order-service:

image.png

2.2 在zyg-cart-web工程中引入zyg-order-interface:

  1. <dependency>
  2. <groupId>com.zelin</groupId>
  3. <artifactId>zyg-order-interface</artifactId>
  4. <version>2.0</version>
  5. </dependency>

2.3 在nginx中添加cart相关的模块:

2.3.1 在/mydata/nginx/html/static/下新建order目录,复制相关的资源:

image.png

2.3.2 在/mydata/nginx/conf/conf.d/zeyigou.conf下添加配置:

  1. server {
  2. listen 80;
  3. server_name order.zeyigou.com;
  4. location / {
  5. proxy_pass http://order;
  6. proxy_set_header Host $host:$server_port;
  7. }
  8. include /etc/nginx/static.conf;
  9. }

2.3.3 在/mydata/nginx/conf/nginx.conf下添加配置:

  1. upstream order{
  2. server 192.168.56.1:9008;
  3. }

2.4 在zyg-cart-web中的/resources/templates中添加如下文件:

image.png

2.5 在zyg-cart-web中的/resources/tempaltes中的getOrderInfo.html

【 前端提交数据方式一: 采用地址栏传参方式 】

  1. <!DOCTYPE html>
  2. <html xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=9; IE=8; IE=7; IE=EDGE">
  6. <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
  7. <title>结算页</title>
  8. <link rel="stylesheet" type="text/css" href="/static/order/css/webbase.css" />
  9. <link rel="stylesheet" type="text/css" href="/static/order/css/pages-getOrderInfo.css" />
  10. <script th:inline="javascript">
  11. //0. 得到所有地址列表
  12. let addressList = [[${addressList}]];
  13. let addrs = addressList.filter(f=>f.isDefault=='1');
  14. let url = "/order/add";
  15. //定义方法调用的变量
  16. let flag = false;
  17. window.onload=function(){
  18. setAddr(addrs[0]);
  19. }
  20. //1. 设置地址的勾选样式
  21. function setStyle(address){
  22. //1.1 取消addr-item下所有div的selected样式
  23. $(".addr-item div").removeClass("selected");
  24. setAddr(address)
  25. }
  26. function setAddr(address) {
  27. url = "/order/add";
  28. //1.1 在最下面的地址栏显示地址信息
  29. let addr = "寄送至:" + address.address + " 收货人:" + address.contact + " " + address.mobile;
  30. $("#address").html(addr);
  31. //1.2 为url连接字符串
  32. url += "?receiverAreaName="+address.address;
  33. url += "&receiverMobile="+address.mobile;
  34. url += "&receiver="+address.contact;
  35. //1.3 如果setPaymentType()方法未调用,我们调用一次
  36. if(!flag){
  37. setPaymentType(1);
  38. }
  39. }
  40. //设置paymentType的值
  41. function setPaymentType(type){
  42. if(url.indexOf("paymentType") == -1){
  43. url += "&paymentType=" + type;
  44. }
  45. flag = true;
  46. }
  47. //提交订单
  48. function submitOrder(){
  49. let ser = $("#form1").serialize();
  50. console.log("ser:",ser)
  51. console.log("url:",url);
  52. //1. 提交表单
  53. location.href = url;
  54. }
  55. </script>
  56. </head>
  57. <body>
  58. <!--head-->
  59. <div class="top">
  60. <div class="py-container">
  61. <div class="shortcut">
  62. <ul class="fl">
  63. <li class="f-item">泽易购欢迎您!</li>
  64. <li class="f-item">请登录 <span><a href="#">免费注册</a></span></li>
  65. </ul>
  66. <ul class="fr">
  67. <li class="f-item">我的订单</li>
  68. <li class="f-item space"></li>
  69. <li class="f-item">我的泽易购</li>
  70. <li class="f-item space"></li>
  71. <li class="f-item">泽易购会员</li>
  72. <li class="f-item space"></li>
  73. <li class="f-item">企业采购</li>
  74. <li class="f-item space"></li>
  75. <li class="f-item">关注泽易购</li>
  76. <li class="f-item space"></li>
  77. <li class="f-item">客户服务</li>
  78. <li class="f-item space"></li>
  79. <li class="f-item">网站导航</li>
  80. </ul>
  81. </div>
  82. </div>
  83. </div>
  84. <div class="cart py-container">
  85. <!--logoArea-->
  86. <div class="logoArea">
  87. <div class="fl logo"><span class="title">结算页</span></div>
  88. <div class="fr search">
  89. <form class="sui-form form-inline">
  90. <div class="input-append">
  91. <input type="text" class="input-error input-xxlarge" placeholder="泽易购自营" />
  92. <button class="sui-btn btn-xlarge btn-danger" type="button">搜索</button>
  93. </div>
  94. </form>
  95. </div>
  96. </div>
  97. <!--主内容-->
  98. <div class="checkout py-container">
  99. <div class="checkout-tit">
  100. <h4 class="tit-txt">填写并核对订单信息</h4>
  101. </div>
  102. <div class="checkout-steps">
  103. <!--收件人信息-->
  104. <div class="step-tit">
  105. <h5>收件人信息<span><a data-toggle="modal" data-target=".edit" data-keyboard="false" class="newadd">新增收货地址</a></span></h5>
  106. </div>
  107. <div class="step-cont">
  108. <div class="addressInfo">
  109. <ul class="addr-detail">
  110. <li class="addr-item">
  111. <div th:each="address : ${addressList}">
  112. <div th:class=" ${address.isDefault=='1'}?'con name selected':'con name'">
  113. <a href="javascript:;" th:onclick="setStyle([[${address}]])">[[${address.contact}]]<span title="点击取消选择">&nbsp;</a></div>
  114. <div class="con address">[[${address.contact}]] [[${address.address}]] <span>[[${address.mobile}]]</span>
  115. <span class="base" th:if="${address.isDefault=='1'}">默认地址</span>
  116. <span class="edittext"><a data-toggle="modal" data-target=".edit" data-keyboard="false" >编辑</a>&nbsp;&nbsp;<a href="/static/order/javascript:;">删除</a></span>
  117. </div>
  118. <div class="clearfix"></div>
  119. </div>
  120. </li>
  121. </ul>
  122. <!--添加地址-->
  123. <div tabindex="-1" role="dialog" data-hasfoot="false" class="sui-modal hide fade edit">
  124. <div class="modal-dialog">
  125. <div class="modal-content">
  126. <div class="modal-header">
  127. <button type="button" data-dismiss="modal" aria-hidden="true" class="sui-close">×</button>
  128. <h4 id="myModalLabel" class="modal-title">添加收货地址</h4>
  129. </div>
  130. <div class="modal-body">
  131. <form action="" class="sui-form form-horizontal">
  132. <div class="control-group">
  133. <label class="control-label">收货人:</label>
  134. <div class="controls">
  135. <input type="text" class="input-medium">
  136. </div>
  137. </div>
  138. <div class="control-group">
  139. <label class="control-label">详细地址:</label>
  140. <div class="controls">
  141. <input type="text" class="input-large">
  142. </div>
  143. </div>
  144. <div class="control-group">
  145. <label class="control-label">联系电话:</label>
  146. <div class="controls">
  147. <input type="text" class="input-medium">
  148. </div>
  149. </div>
  150. <div class="control-group">
  151. <label class="control-label">邮箱:</label>
  152. <div class="controls">
  153. <input type="text" class="input-medium">
  154. </div>
  155. </div>
  156. <div class="control-group">
  157. <label class="control-label">地址别名:</label>
  158. <div class="controls">
  159. <input type="text" class="input-medium">
  160. </div>
  161. <div class="othername">
  162. 建议填写常用地址:<a href="#" class="sui-btn btn-default">家里</a> <a href="#" class="sui-btn btn-default">父母家</a> <a href="#" class="sui-btn btn-default">公司</a>
  163. </div>
  164. </div>
  165. </form>
  166. </div>
  167. <div class="modal-footer">
  168. <button type="button" data-ok="modal" class="sui-btn btn-primary btn-large">确定</button>
  169. <button type="button" data-dismiss="modal" class="sui-btn btn-default btn-large">取消</button>
  170. </div>
  171. </div>
  172. </div>
  173. </div>
  174. <!--确认地址-->
  175. </div>
  176. <div class="hr"></div>
  177. </div>
  178. <div class="hr"></div>
  179. <!--支付和送货-->
  180. <div class="payshipInfo">
  181. <div class="step-tit">
  182. <h5>支付方式</h5>
  183. </div>
  184. <div class="step-cont">
  185. <ul class="payType">
  186. <li class="selected" onclick="setPaymentType(1)">微信付款<span title="点击取消选择"></span></li>
  187. <li onclick="setPaymentType(2)">货到付款<span title="点击取消选择"></span></li>
  188. </ul>
  189. </div>
  190. <div class="hr"></div>
  191. <div class="step-tit">
  192. <h5>送货清单</h5>
  193. </div>
  194. <div class="step-cont">
  195. <ul class="send-detail">
  196. <li th:each="cart : ${cartList}">
  197. <div class="sendGoods">
  198. <span th:text="${cart.sellerName}" style="padding:5px 10px;background-color: red;color:white"></span>
  199. <ul class="yui3-g" th:each="item : ${cart.orderItemList}">
  200. <li class="yui3-u-1-6">
  201. <span><img th:src="${item.picPath}"/></span>
  202. </li>
  203. <li class="yui3-u-7-12">
  204. <div class="desc" th:text="${item.title}"></div>
  205. <div class="seven">7天无理由退货</div>
  206. </li>
  207. <li class="yui3-u-1-12">
  208. <div class="price" th:text="${item.price}">¥5399.00</div>
  209. </li>
  210. <li class="yui3-u-1-12">
  211. <div class="num">X[[${item.num}]]</div>
  212. </li>
  213. <li class="yui3-u-1-12">
  214. <div class="exit">有货</div>
  215. </li>
  216. </ul>
  217. </div>
  218. </li>
  219. <li>aa</li>
  220. <li>bb</li>
  221. </ul>
  222. </div>
  223. <div class="hr"></div>
  224. </div>
  225. <div class="linkInfo">
  226. <div class="step-tit">
  227. <h5>发票信息</h5>
  228. </div>
  229. <div class="step-cont">
  230. <span>普通发票(电子)</span>
  231. <span>个人</span>
  232. <span>明细</span>
  233. </div>
  234. </div>
  235. <div class="cardInfo">
  236. <div class="step-tit">
  237. <h5>使用优惠/抵用</h5>
  238. </div>
  239. </div>
  240. </div>
  241. </div>
  242. <div class="order-summary">
  243. <div class="static fr">
  244. <div class="list">
  245. <span><i class="number">1</i>件商品,总商品金额</span>
  246. <em class="allprice">¥5399.00</em>
  247. </div>
  248. <div class="list">
  249. <span>返现:</span>
  250. <em class="money">0.00</em>
  251. </div>
  252. <div class="list">
  253. <span>运费:</span>
  254. <em class="transport">0.00</em>
  255. </div>
  256. </div>
  257. </div>
  258. <div class="clearfix trade">
  259. <div class="fc-price">应付金额: <span class="price">¥5399.00</span></div>
  260. <div class="fc-receiverInfo" id="address">寄送至:</div>
  261. </div>
  262. <div class="submit">
  263. <a class="sui-btn btn-danger btn-xlarge" href="javascript:void(0)" onclick="submitOrder()">提交订单</a>
  264. </div>
  265. </div>
  266. <!-- 底部栏位 -->
  267. ...

【 前端提交数据方式二: 采用表单隐藏域方式 】

  1. <script th:inline="javascript">
  2. //0. 得到所有地址列表
  3. let addressList = [[${addressList}]];
  4. let addrs = addressList.filter(f=>f.isDefault=='1');
  5. let url = "/order/add";
  6. //定义方法调用的变量
  7. let flag = false;
  8. window.onload=function(){
  9. setAddr2(addrs[0])
  10. }
  11. //1. 设置地址的勾选样式
  12. function setStyle(address){
  13. //1.1 取消addr-item下所有div的selected样式
  14. $(".addr-item div").removeClass("selected");
  15. setAddr2(address)
  16. }
  17. //设置提交数据方式二:直接为表单隐藏域赋值
  18. function setAddr2(address){
  19. //2.1 在最下面的地址栏显示地址信息
  20. let addr = "寄送至:" + address.address + " 收货人:" + address.contact + " " + address.mobile;
  21. $("#address").html(addr);
  22. //2.2 为表单隐藏域赋值
  23. $("#receiverAreaName").val(address.address);
  24. $("#receiverMobile").val(address.mobile);
  25. $("#receiver").val(address.contact);
  26. }
  27. //设置paymentType的值
  28. function setPaymentType(type){
  29. $("#paymentType").val(type);
  30. }
  31. //提交订单
  32. function submitOrder(){
  33. let ser = $("#form1").serialize();
  34. console.log("ser:",ser)
  35. console.log("url:",url);
  36. //1. 提交表单
  37. location.href = url;
  38. }
  39. </script>
  40. <form action="/order/add" th:action="@{/order/add}" method="post" id="form1">
  41. <input type="hidden" name="receiverAreaName" id="receiverAreaName">
  42. <input type="hidden" name="receiverMobile" id="receiverMobile">
  43. <input type="hidden" name="receiver" id="receiver">
  44. <input type="hidden" name="paymentType" id="paymentType" value="1">
  45. </form>
  46. <div class="step-cont">
  47. <ul class="payType">
  48. <li class="selected" onclick="setPaymentType2(1)">微信付款<span title="点击取消选择"></span></li>
  49. <li onclick="setPaymentType2(2)">货到付款<span title="点击取消选择"></span></li>
  50. </ul>
  51. </div>

注意:这里表单 的action一定要用th:action的形式,否则,报错,原因是: CsrfFilter与Rest服务Post方式的矛盾: 只有GET|HEAD|TRACE|OPTIONS这4类方法会被放行,其它Method的http请求,都要验证_csrf的token是否正确,而通常post方式调用rest服务时,又没有_csrf的token,所以校验失败。 具体解决方案,参考https://blog.csdn.net/wangmate/article/details/106198947

2.6 在zyg-cart-web中的orderController中添加方法:

  1. /**
  2. * 功能: 提交订单
  3. * 参数:
  4. * 返回值: java.lang.String
  5. * 时间: 2021/8/14 16:44
  6. */
  7. @Transactional
  8. @RequestMapping("/add")
  9. public String add(OrderEntity order){
  10. System.out.println("order = " + order);
  11. //1.1 得到订单址列表
  12. //① 获取登录名
  13. String name = SecurityContextHolder.getContext().getAuthentication().getName();
  14. //② 为订单对象设置属性
  15. order.setSourceType("2");
  16. order.setUserId(name);
  17. orderService.add(order);
  18. return "pay";
  19. }

2.7 在zyg-order-service中添加如下方法:

  1. /**
  2. * 功能: 提交订单
  3. * 参数:
  4. * 返回值: void
  5. * 时间: 2021/8/14 16:44
  6. */
  7. @Override
  8. public void add(OrderEntity order) {
  9. //1. 得到购物车列表的字符串
  10. String cartStr = redisTemplate.opsForValue().get(order.getUserId());
  11. //2. 转换为List<Cart>对象并返回
  12. List<Cart> cartList = null;
  13. if(StringUtils.isNotBlank(cartStr)){
  14. cartList = JSON.parseArray(cartStr,Cart.class);
  15. }
  16. //3. 添加订单(一个购物车对应一个订单)
  17. for (Cart cart : cartList) {
  18. //3.1 定义订单对象
  19. OrderEntity orderEntity = new OrderEntity();
  20. //3.2 生成订单id主键
  21. long id = idWorker.nextId();
  22. orderEntity.setOrderId(id);
  23. //3.3 设置订单的其它相关属性
  24. orderEntity.setCreateTime(new Date());
  25. orderEntity.setPaymentType(order.getPaymentType());
  26. orderEntity.setReceiver(order.getReceiver());
  27. orderEntity.setReceiverAreaName(order.getReceiverAreaName());
  28. orderEntity.setReceiverMobile(order.getReceiverMobile());
  29. orderEntity.setSellerId(cart.getSellerId());
  30. orderEntity.setUserId(order.getUserId());
  31. orderEntity.setSourceType(order.getSourceType());
  32. orderEntity.setStatus("1"); //未支付
  33. double sum = 0; //定义订单的总金额
  34. //3.4 得到购物车的购物项数据,向订单项表中添加此数据
  35. for (OrderItemEntity item : cart.getOrderItemList()) {
  36. //3.4.1 计算小计
  37. BigDecimal totalFee = new BigDecimal(item.getNum() * item.getPrice().doubleValue());
  38. item.setTotalFee(totalFee);
  39. //3.4.2 累加总金额
  40. sum += totalFee.doubleValue();
  41. //3.4.3 设置订单的id
  42. item.setOrderId(id);
  43. //3.4.4 设置订单项的id
  44. item.setId(idWorker.nextId());
  45. //3.4.5 添加订单项到tb_ordeItem表
  46. orderItemDao.insert(item);
  47. }
  48. //3.5 计算此订单的总金额
  49. orderEntity.setPayment(new BigDecimal(sum));
  50. //3.6 添加订单
  51. this.save(orderEntity);
  52. }
  53. //4. 清空redis中的购物车
  54. //todo...
  55. }

2.8 程序运行效果如下:

image.png