一个菜鸟的互联网技术分享博客
您的位置: 主页 > 使用vue全家桶高仿小米商城--订单结算
advertisement

使用vue全家桶高仿小米商城--订单结算

1、首先我们需要再components下面新建两个vue文件命名分别为:Loading.vue(用于支付宝支付时候跳转过渡)和ScanPayCode.vue(用于微信支付时候生成二维码页面)
Loading.vue代码如下:
  1. <template>  
  2.     <div class="loading">  
  3.         <img src="./../../public/images/loading-svg/loading-bars.svg" alt="">  
  4.     </div>  
  5. </template>  
  6. <script>  
  7.     export default {  
  8.         name: 'loading'  
  9.     }  
  10. </script>  
  11. <style lang="scss">  
  12.     .loading {  
  13.         height: 80px;  
  14.         line-height: 80px;  
  15.         text-align: center;  
  16.         padding: 30px 0;  
  17.   
  18.         img {  
  19.             height: 100%;  
  20.         }  
  21.     }  
  22. </style>  
ScanPayCode.vue代码如下:
  1. <template>  
  2.     <div class="scan">  
  3.         <div class="mask"></div>  
  4.         <div class="item-wrap">  
  5.             <div class="img-scan"></div>  
  6.             <div class="img-pay">  
  7.                 <div class="title">微信支付<em @click="close"></em></div>  
  8.                 <div class="qrcode"><img :src="img"></div>  
  9.                 <div class="tip">  
  10.                     <p>请使用<span class="theme-color">微信</span>扫一扫</p>  
  11.                     <p>二维码完成支付</p>  
  12.                 </div>  
  13.             </div>  
  14.         </div>  
  15.     </div>  
  16. </template>  
  17. <script>  
  18.     export default {  
  19.         name: 'scan-pay-code',  
  20.         props: ['img'],  
  21.         methods: {  
  22.             close() {  
  23.                 this.$emit('close');  
  24.             }  
  25.         }  
  26.     }  
  27. </script>  
  28. <style lang="scss">  
  29.     @import './../assets/scss/config.scss';  
  30.     @import './../assets/scss/mixin.scss';  
  31.   
  32.     .scan {  
  33.         position: absolute;  
  34.         z-index: 99;  
  35.         top: 0;  
  36.         width: 100%;  
  37.         height: 100%;  
  38.   
  39.         .mask {  
  40.             position: fixed;  
  41.             top: 0;  
  42.             left: 0;  
  43.             right: 0;  
  44.             bottom: 0;  
  45.             opacity: .6;  
  46.             background-color: #000000;  
  47.         }  
  48.   
  49.         .item-wrap {  
  50.             position: fixed;  
  51.             width: 670px;  
  52.             top: 50%;  
  53.             left: 50%;  
  54.             transform: translate(-50%, -50%);  
  55.             display: flex;  
  56.             align-items: center;  
  57.   
  58.             .img-scan {  
  59.                 @include bgImg(296px, 485px, './../../public/images/pay/icon-scan.png');  
  60.             }  
  61.   
  62.             .img-pay {  
  63.                 width: 370px;  
  64.                 height: 440px;  
  65.                 display: inline-block;  
  66.                 background-color: #ffffff;  
  67.   
  68.                 .title {  
  69.                     position: relative;  
  70.                     height: 60px;  
  71.                     line-height: 60px;  
  72.                     color: #333333;  
  73.                     font-size: 20px;  
  74.                     padding: 0 18px;  
  75.                     background-color: #F5F5F5;  
  76.   
  77.                     em {  
  78.                         position: absolute;  
  79.                         top: 23.5px;  
  80.                         right: 20px;  
  81.                         @include bgImg(13px, 13px, './../../public/images/icon-close.png');  
  82.                         cursor: pointer;  
  83.                     }  
  84.                 }  
  85.   
  86.                 .qrcode {  
  87.                     text-align: center;  
  88.                     padding: 44px 0 26px;  
  89.   
  90.                     img {  
  91.                         width: 237px;  
  92.                         height: 240px;  
  93.                     }  
  94.                 }  
  95.   
  96.                 .tip {  
  97.                     text-align: center;  
  98.                     font-size: 14px;  
  99.                     color: #333333;  
  100.                 }  
  101.             }  
  102.         }  
  103.     }  
  104. </style>
既然是支付页面,那么要改变代码的页面就是:orderPay.vue页面啦,代码如下:
  1. <template>  
  2.     <div class="order-pay">  
  3.         <div class="wrapper">  
  4.             <div class="container">  
  5.                 <div class="order-wrap">  
  6.                     <div class="item-order">  
  7.                         <div class="icon-succ"></div>  
  8.                         <div class="order-info">  
  9.                             <h2>订单提交成功!去付款咯~</h2>  
  10.                             <p>请在<span>30分</span>内完成支付, 超时后将取消订单</p>  
  11.                             <p>收货信息:{{addressInfo}}</p>  
  12.                         </div>  
  13.                         <div class="order-total">  
  14.                             <p>应付总额:<span>{{payment}}</span>元</p>  
  15.                             <p>订单详情<em class="icon-down" :class="{'up':showDetail}" @click="showDetail=!showDetail"></em></p>  
  16.                         </div>  
  17.                     </div>  
  18.                     <div class="item-detail" v-if="showDetail">  
  19.                         <div class="item">  
  20.                             <div class="detail-title">订单号:</div>  
  21.                             <div class="detail-info theme-color">{{orderId}}</div>  
  22.                         </div>  
  23.                         <div class="item">  
  24.                             <div class="detail-title">收货信息:</div>  
  25.                             <div class="detail-info">{{addressInfo}}</div>  
  26.                         </div>  
  27.                         <div class="item good">  
  28.                             <div class="detail-title">商品名称:</div>  
  29.                             <div class="detail-info">  
  30.                                 <ul>  
  31.                                     <li v-for="(item,index) in orderDetail" :key="index">  
  32.                                         <img v-lazy="item.productImage" />{{item.productName}}  
  33.                                     </li>  
  34.                                 </ul>  
  35.                             </div>  
  36.                         </div>  
  37.                         <div class="item">  
  38.                             <div class="detail-title">发票信息:</div>  
  39.                             <div class="detail-info">电子发票 个人</div>  
  40.                         </div>  
  41.                     </div>  
  42.                 </div>  
  43.                 <div class="item-pay">  
  44.                     <h3>选择以下支付方式付款</h3>  
  45.                     <div class="pay-way">  
  46.                         <p>支付平台</p>  
  47.                         <div class="pay pay-ali" :class="{'checked':payType==1}" @click="paySubmit(1)"></div>  
  48.                         <div class="pay pay-wechat" :class="{'checked':payType==2}" @click="paySubmit(2)"></div>  
  49.                     </div>  
  50.                 </div>  
  51.             </div>  
  52.         </div>  
  53.         <scan-pay-code v-if="showPay" @close="closePayModal" :img="payImg"></scan-pay-code>  
  54.         <modal   
  55.         title="支付确认"   
  56.         btnType="3"   
  57.         :showModal="showPayModal"   
  58.         sureText="查看订单"   
  59.         cancelText="未支付"   
  60.         @cancel="showPayModal=false"  
  61.         @submit="goOrderList">  
  62.             <template v-slot:body>  
  63.                 <p>您确认是否完成支付?</p>  
  64.             </template>  
  65.         </modal>  
  66.     </div>  
  67. </template>  
  68. <script>  
  69.     import QRCode from 'qrcode'  
  70.     import { Message } from 'element-ui';  
  71.     import ScanPayCode from './../components/ScanPayCode'  
  72.     import Modal from './../components/Modal'  
  73.     export default {  
  74.         name: 'order-pay',  
  75.         data() {  
  76.             return {  
  77.                 orderId: this.$route.query.orderNo,  
  78.                 addressInfo: ''//收货人地址  
  79.                 orderDetail: [], //订单详情,包含商品列表  
  80.                 showDetail: false//是否显示订单详情  
  81.                 payType: ''//支付类型  
  82.                 showPay: false//是否显示微信支付弹框  
  83.                 payImg: ''//微信支付的二维码地址  
  84.                 showPayModal: false//是否显示二次支付确认弹框  
  85.                 payment: 0//订单总金额  
  86.                 T: '' //定时器ID  
  87.             }  
  88.         },  
  89.         components: {  
  90.             ScanPayCode,  
  91.             Modal  
  92.         },  
  93.         mounted() {  
  94.             this.getOrderDetail();  
  95.         },  
  96.         methods: {  
  97.             getOrderDetail() {  
  98.                 this.axios.get(`/orders/${this.orderId}`).then((res) => {  
  99.                     let item = res.shippingVo;  
  100.                     this.addressInfo =  
  101.                         `${item.receiverName} ${item.receiverMobile} ${item.receiverProvince} ${item.receiverCity} ${item.receiverDistrict} ${item.receiverAddress}`;  
  102.                     this.orderDetail = res.orderItemVoList;  
  103.                     this.payment = res.payment;  
  104.                 })  
  105.             },  
  106.             paySubmit(payType) {  
  107.                 if (payType == 1) {  
  108.                     window.open('/#/order/alipay?orderId=' + this.orderId, '_blank');  
  109.                 } else {  
  110.                     this.axios.post('/pay', {  
  111.                         orderId: this.orderId,  
  112.                         orderName: 'Vue高仿小米商城',  
  113.                         amount: 0.01//单位元  
  114.                         payType: 2 //1支付宝,2微信  
  115.                     }).then((res) => {  
  116.                         QRCode.toDataURL(res.content)  
  117.                             .then(url => {  
  118.                                 this.showPay = true;  
  119.                                 this.payImg = url;  
  120.                                 this.loopOrderState();  
  121.                             })  
  122.                             .catch(() => {  
  123.                                 Message.error('微信二维码生成失败,请稍后重试');  
  124.                             })  
  125.                     })  
  126.                 }  
  127.             },  
  128.             // 关闭微信弹框  
  129.             closePayModal() {  
  130.                 this.showPay = false;  
  131.                 this.showPayModal = true;  
  132.                 clearInterval(this.T);  
  133.             },  
  134.             // 轮询当前订单支付状态  
  135.             loopOrderState() {  
  136.                 this.T = setInterval(() => {  
  137.                     this.axios.get(`/orders/${this.orderId}`).then((res) => {  
  138.                         if (res.status == 20) {  
  139.                             clearInterval(this.T);  
  140.                             this.goOrderList();  
  141.                         }  
  142.                     })  
  143.                 }, 1000);  
  144.             },  
  145.             goOrderList() {  
  146.                 this.$router.push('/order/list');  
  147.             }  
  148.         }  
  149.     }  
  150. </script>  
  151. <style lang="scss">  
  152.     .order-pay {  
  153.         .wrapper {  
  154.             background-color: #F5F5F5;  
  155.             padding-top: 30px;  
  156.             padding-bottom: 61px;  
  157.   
  158.             .order-wrap {  
  159.                 padding: 62px 50px;  
  160.                 background-color: #fff;  
  161.                 font-size: 14px;  
  162.                 margin-bottom: 30px;  
  163.   
  164.                 .item-order {  
  165.                     display: flex;  
  166.                     align-items: center;  
  167.   
  168.                     .icon-succ {  
  169.                         width: 90px;  
  170.                         height: 90px;  
  171.                         border-radius: 50%;  
  172.                         background: url('./../../public/images/icon-gou.png') #80c58a no-repeat center;  
  173.                         background-size: 60px;  
  174.                         margin-right: 40px;  
  175.                     }  
  176.   
  177.                     .order-info {  
  178.                         margin-right: 248px;  
  179.   
  180.                         h2 {  
  181.                             font-size: 24px;  
  182.                             color: #333333;  
  183.                             margin-bottom: 20px;  
  184.                         }  
  185.   
  186.                         p {  
  187.                             color: #666666;  
  188.   
  189.                             span {  
  190.                                 color: #FF6700;  
  191.                             }  
  192.                         }  
  193.                     }  
  194.   
  195.                     .order-total {  
  196.                         &>p:first-child {  
  197.                             margin-bottom: 30px;  
  198.                         }  
  199.   
  200.                         span {  
  201.                             font-size: 28px;  
  202.                             color: #FF6700;  
  203.                         }  
  204.   
  205.                         .icon-down {  
  206.                             display: inline-block;  
  207.                             width: 14px;  
  208.                             height: 10px;  
  209.                             background: url('./../../public/images/icon-down.png') no-repeat center;  
  210.                             background-size: contain;  
  211.                             margin-left: 9px;  
  212.                             transition: all .5s;  
  213.                             cursor: pointer;  
  214.   
  215.                             &.up {  
  216.                                 transform: rotate(180deg);  
  217.                             }  
  218.                         }  
  219.   
  220.                         .icon-up {  
  221.                             transform: rotate(180deg);  
  222.                         }  
  223.                     }  
  224.                 }  
  225.   
  226.                 .item-detail {  
  227.                     border-top: 1px solid #D7D7D7;  
  228.                     padding-top: 47px;  
  229.                     padding-left: 130px;  
  230.                     font-size: 14px;  
  231.                     margin-top: 45px;  
  232.   
  233.                     .item {  
  234.                         margin-bottom: 19px;  
  235.   
  236.                         .detail-title {  
  237.                             float: left;  
  238.                             width: 100px;  
  239.                         }  
  240.   
  241.                         .detail-info {  
  242.                             display: inline-block;  
  243.   
  244.                             img {  
  245.                                 width: 30px;  
  246.                                 vertical-align: middle;  
  247.                             }  
  248.                         }  
  249.                     }  
  250.                 }  
  251.             }  
  252.   
  253.             .item-pay {  
  254.                 padding: 26px 50px 72px;  
  255.                 background-color: #ffffff;  
  256.                 color: #333333;  
  257.   
  258.                 h3 {  
  259.                     font-size: 20px;  
  260.                     font-weight: 200;  
  261.                     color: #333333;  
  262.                     padding-bottom: 24px;  
  263.                     border-bottom: 1px solid #D7D7D7;  
  264.                     margin-bottom: 26px;  
  265.                 }  
  266.   
  267.                 .pay-way {  
  268.                     font-size: 18px;  
  269.   
  270.                     .pay {  
  271.                         display: inline-block;  
  272.                         width: 188px;  
  273.                         height: 64px;  
  274.                         border: 1px solid #D7D7D7;  
  275.                         cursor: pointer;  
  276.   
  277.                         &:last-child {  
  278.                             margin-left: 20px;  
  279.                         }  
  280.   
  281.                         &.checked {  
  282.                             border: 1px solid #FF6700;  
  283.                         }  
  284.                     }  
  285.   
  286.                     .pay-ali {  
  287.                         background: url('./../../public/images/pay/icon-ali.png') no-repeat center;  
  288.                         background-size: 103px 38px;  
  289.                         margin-top: 19px;  
  290.                     }  
  291.   
  292.                     .pay-wechat {  
  293.                         background: url('./../../public/images/pay/icon-wechat.png') no-repeat center;  
  294.                         background-size: 103px 38px;  
  295.                     }  
  296.                 }  
  297.             }  
  298.         }  
  299.     }  
  300. </style>
又由于分为支付宝支付和微信支付,那么alipay.vue这个承载支付宝返回回来的form表单代码就要变化了,代码如下:
  1. <template>  
  2.     <div class="ali-pay">  
  3.         <loading v-if="loading"></loading>  
  4.         <div class="form" v-html="content"></div>  
  5.     </div>  
  6. </template>  
  7. <script>  
  8.     import Loading from './../components/Loading'  
  9.     export default {  
  10.         name: 'alipay',  
  11.         components: {  
  12.             Loading  
  13.         },  
  14.         data() {  
  15.             return {  
  16.                 orderId: this.$route.query.orderId,  
  17.                 content: '',  
  18.                 loading: true  
  19.             }  
  20.         },  
  21.         mounted() {  
  22.             this.paySubmit();  
  23.         },  
  24.         methods: {  
  25.             paySubmit() {  
  26.                 this.axios.post('/pay', {  
  27.                     orderId: this.orderId,  
  28.                     orderName: 'Vue高仿小米商城',  
  29.                     amount: 0.01//单位元  
  30.                     payType: 1 //1支付宝,2微信  
  31.                 }).then((res) => {  
  32.                     this.content = res.content;  
  33.                     setTimeout(() => {  
  34.                         document.forms[0].submit();  
  35.                     }, 100)  
  36.                 })  
  37.             }  
  38.         }  
  39.     }  
  40. </script>  
其实在微信支付的时候还会存在一个问题就是,当我们已经支付订单了,但当返回的支付页面是服务端是有报错提示的(该订单已经支付了),那么我们就得把这个报错提示出来,那么修改接口错误拦截这块的代码:main.js,如下图所示:

另外还得安装转码插件:qrcode(微信支付返回回来的是一个url)==》npm i qrcode --save-dev
部分效果如下图所示:








zhangren.online
上一篇:使用vue全家桶高仿小米商城--订单确认页面
下一篇:使用vue全家桶高仿小米商城--订单列表

您可能喜欢

回到顶部