vue前台十(1)

 

一,订单交易页trade的数据展示

1.trade组件静态页面完成,创建trade.js的vuex,在总vuex中引入,注册

2.封装请求订单交易信息的函数接口

//请求订单交易信息 /api/order/auth/trade
export const reqTradeInfo = () => Ajax.get('/order/auth/trade')

3.在trade.js的vuex中发送请求

import {reqTradeInfo} from '@/api'
const state = {
  tradeInfo:{}
}
const mutations = {
  RECEIVETRADEINFO(state,tradeInfo){
    state.tradeInfo = tradeInfo
  }
}

const actions = {
  async getTradeInfo({commit}){
    const result = await reqTradeInfo()
    if(result.code === 200){
      commit('RECEIVETRADEINFO',result.data)
    }
  }
}

const getters = {
  detailArrayList(state){
    return state.tradeInfo.detailArrayList || []
  },
  userAddressList(state){
    return state.tradeInfo.userAddressList || []
  }
}

export default {
  state,
  mutations,
  actions,
  getters
}

 

4.在trade组件中,dispatch到vuex, 然后获取vuex中的数据
  mounted() {
    this.getTradeInfo();
  },
  getTradeInfo() {
      this.$store.dispatch("getTradeInfo");
    },
 computed: {
    ...mapGetters(["userAddressList", "detailArrayList"]),
    ...mapState({
      tradeInfo: state => state.trade.tradeInfo
    }),
    deaultAddress() {
      return this.userAddressList.find(item => item.isDefault === "1") || {}; //找到默认的地址那一项
    }
  }

 

5.在html模板中填充数据
 <div class="address clearFix" v-for="(address, index) in userAddressList" :key="address.id">
        <span class="username" :class="{selected:address.isDefault === '1'}">{{address.consignee}}</span>
        <p @click="changeDefaultAddress(index)">
          <span class="s1">{{address.userAddress}}</span>
          <span class="s2">{{address.phoneNum}}</span>
          <span class="s3" v-if="address.isDefault === '1'">默认地址</span>
        </p>
      </div>

 

 

注;isDefault是判断默认地址是否显示的一个值,1,为显示, 0,为不显示,用v-if去判断
 
 
 
6,对于收件地址,点击那一个就应该那一个是默认地址, 在p标签中添加一个点击事件changeDefaultAddress,需要传递一个index,
 
js代码
利用排他法
  changeDefaultAddress(index) {
      this.userAddressList.forEach(item => {
        item.isDefault = "0";
      });
      this.userAddressList[index].isDefault = "1";
    },

 

7,左边还有一个选中的边框按钮需要调整,点击哪个地址,选中框就是哪个,对selected类需要判断

 

<div class="address clearFix" v-for="(user, index) in userAddressList" :key="user.id">
        <span class="username " :class="{selected:user.isDefault === '1'}">{{user.consignee}}</span>
        <p @click="changeDefaultAddress(index)">
          <span class="s1">{{user.userAddress}}</span>
          <span class="s2">{{user.phoneNum}}</span>
          <span class="s3" v-if="user.isDefault === '1'">默认地址</span>
        </p>
      </div>

 

8.在底部还有个地址信息,需要根据顶部选中的地址变化而变化

 

 

 
 <div class="receiveInfo">
        寄送至:
        <span>{{deaultAddress.userAddress}}</span>
        收货人:
        <span>{{deaultAddress.consignee}}</span>
        <span>{{deaultAddress.phoneNum}}</span>
      </div>

此时需要计算属性,找到那个isDefault为1的对象

deaultAddress() {
      return this.userAddressList.find(item => item.isDefault === "1") || {}; //找到默认的地址那一项
    }

 

二,提交订单分析及接口请求函数封装

逻辑分析,此时在订单页面,底部有个提交订单按钮,点击提交按钮,这里是要发送提交订单的请求,这个订单需要携带请求体对象,而且所有的数据都在订单页面,那么就不需要在vuex中发送ajax请求,

只在订单trade组件中发送即可,此时,需要根据api接口的请求体参数,
来收集各种参数,去发送请求,

请求体参数,我们需要收集这些参数

{
    "consignee": "admin",
    "consigneeTel": "15011111111",
    "deliveryAddress": "北京市昌平区2",
    "paymentWay": "ONLINE",
    "orderComment": "xxx",
    "orderDetailList": [
        {
            "id": null,
            "orderId": null,
            "skuId": 6,
            "skuName": " Apple iPhone 11 (A2223) 128GB 红色 移动联通电信22",
            "imgUrl": "http://182.92.128.115:8080//rBFUDF6V0JmAG9XGAAGL4LZv5fQ163.png",
            "orderPrice": 4343,
            "skuNum": 2,
            "hasStock": null
        },
        {
            "id": null,
            "orderId": null,
            "skuId": 4,
            "skuName": "Apple iPhone 11 (A2223) 128GB 红色",
            "imgUrl": "http://182.92.128.115:80800/rBFUDF6VzaeANzIOAAL1X4gVWEE035.png",
            "orderPrice": 5999,
            "skuNum": 1,
            "hasStock": null
        }
    ]
}

 

1,封装提交订单接口的函数

//请求提交订单(其实本质就是创建订单,返回的是订单编号)
// /api/order/auth/submitOrder?tradeNo={tradeNo}   post  
export const reqSubmitOrder = (tradeNo,tradeInfo) =>Ajax.post(`/order/auth/submitOrder?tradeNo=${tradeNo}`,tradeInfo)

 

 2.提交按钮绑定点击事件
<a href="javascript:;" class="subBtn" @click="submitOrder">提交订单</a>

js代码,发送请求,跳转到支付页面,此时接口函数在入口文件main.js配置下,在原型配置,让组件可以自动获取

import * as API from '@/api'
new Vue({
  beforeCreate() {
    Vue.prototype.$bus = this
    Vue.prototype.$API = API
  },
  el:'#app',
  render: h => h(App),
  router,
  store
})

 

 //提交按钮,发送请求,跳转到支付页面,携带订单编号到支付页面
    async submitOrder() {
      //准备query参数和data参数
      let tradeNo = this.tradeInfo.tradeNo;
      let tradeInfo = {
        consignee: this.deaultAddress.consignee,
        consigneeTel: this.deaultAddress.phoneNum,
        deliveryAddress: this.deaultAddress.userAddress,
        paymentWay: "ONLINE",
        orderComment: this.message,
        orderDetailList: this.detailArrayList
      };

      //调用接口请求函数去发送请求创建订单
      const result = await this.$API.reqSubmitOrder(tradeNo, tradeInfo);
      if(result.code === 200){
        //请求提交创建订单成功,会返回一个订单编号,有了这个订单编号,再去跳转到支付页面
        //接下来就可以携带这个订单编号去到支付页面
        alert('创建订单成功,自动跳转到支付页面')
        this.$router.push('/pay?orderNo='+result.data)
      }
    }

注;此时返回的响应信息有个订单编号,需要路由到t支付页面pay, 订单编号需要传递过去 

响应信息的事例

{
    "code": 200,
    "message": "成功",
    "data": 71,   // orderId 订单号
    "ok": true
}

注;关于API模块的配置,将API配置成vue的原型,可以让组件实例直接访问到,在入口文件main.js配置

new Vue({
  beforeCreate() {
    Vue.prototype.$bus = this
    Vue.prototype.$API = API
  },

此时组件实例访问,

const result = await this.$API.reqSubmitOrder(tradeNo, tradeInfo);
 
 
 
三,支付页面的信息请求及展示
1.在支付组件页面,对于订单编号,需要从路由参数中获取
    <span class="fl">
            请您在提交订单
            <em class="orange time">4小时</em>之内完成支付,超时订单会自动取消。订单号:
            <em>{{$route.query.orderNo}}</em>
          </span>

2.而对支付的总金额,需要发送请求获取

配置接口函数, orderId是订单编号,作为请求参数

//请求获取订单信息 /api/payment/weixin/createNative/{orderId}  get
export const reqOrderInfo = (orderId) => Ajax.get(`/payment/weixin/createNative/${orderId}`)

3.在pay支付组件中,发送请求,我们可以不在vuex中发送请求,而直接在组件中发送请求,更方便。页面加载完后,即可发送请求

  mounted() {
    this.getOrderInfo();
  },
  methods: {
    async getOrderInfo() {
      const result = await this.$API.reqOrderInfo(this.$route.query.orderNo);
      if (result.code === 200) {
        this.orderInfo = result.data;
      }
    },

响应信息事例, orderId为订单编号。 totalFee为支付总费用

{
    "code": 200,
    "message": "成功",
    "data": {
        "codeUrl": "weixin://wxpay/bizpayurl?pr=P0aPBJK",
        "orderId": 71,
        "totalFee": 23996,
        "resultCode": "SUCCESS"
    },
    "ok": true
}

 

在html中填充支付费用

<span class="fr">
            <em class="lead">应付金额:</em>
            <em class="orange money">¥{{orderInfo.totalFee}}</em>
          </span>

 

 

 四, element-ui的引入消息盒子,弹出alert,message消息提示

element-ui库:https://element.eleme.cn/#/zh-CN/component/quickstart

1.安装element-ui, npm i element-ui -S

2.按需引入组件,可参考官网

支付整体逻辑

点击立即支付
        1、我们需要根据codeUrl 使用qrcode生成要显示的微信二维码url
        2、使用element-ui的this.$alert 弹出消息框显示二维码图片,使用需要显示html的消息框
        3、弹出消息框的时候,我们需要循环定时器去查询支付状态
        4、如果支付成功,那么把支付成功的状态码保存在data当中,并且清除定时器,自动跳转到支付成功页面
        5、如果点击我已经支付成功,那么需要判断状态码是不是成功,如果成功那就关闭提示框,不成功就提示不关闭
            (需要放在messageBox的beforeClose回调当中去,判断 然后手动关闭)
        6、如果点击支付失败,那么需要提示信息 清除定时器  关闭提示框 关闭也要去手动关闭
            (需要放在messageBox的beforeClose回调当中去,判断 然后手动关闭)
        7、支付成功才能到支付成功页面,那么我们都要去花钱,所以把支付功能简化,直接点击就能跳

 

import { MessageBox, Message } from 'element-ui';

Vue.prototype.$msgbox = MessageBox; //消息盒子
Vue.prototype.$alert = MessageBox.alert; //弹出框
Vue.prototype.$message = Message; //提示信息

注;将element-ui组件挂载在vue原型上,组件对象可以直接访问

 

,使用qrcode生成微信支付二维码,npm install --save qrcode  ,github去搜索的时候,搜索node-qrcode

1.点击立即支付按钮,弹出一个支付框,需要element-ui来创建,并且有一个二维码图片,需要借助qrcode来完成

 引入qrcode,      import QRCode from 'qrcode'
 <div class="submit">
          <!-- <router-link class="btn" to="/paysuccess">立即支付</router-link> -->
          <a href="javascript:;" class="btn" @click="pay">立即支付</a>
        </div>

2. js逻辑代码, 点击立即支付, 弹出一个框。需要对返回的微信连接,转换成二维码。 发送一个查看支付信息的请求,搞个定时器去实时查看,

async pay() {
      //1、弹出一个消息盒子

      //2、这个消息盒子内部需要二维码,所以得去准备二维码
      //codeUrl:"weixin://wxpay/bizpayurl?pr=DcuIayu" 是微信官方返回的支付链接信息
      //我们需要把这个信息转化为一张二维码图片的路径
      //使用qrcode可以把这个支付链接信息转化为二维码

      //3、this.$alert返回的也是一个promise,而且这个promise成功代表点了确认按钮  失败代表点了取消按钮,必须处理
      //哪怕什么都不做

      // 4、 二维码显示成功后,我们需要时时刻刻去查看订单的支付状态信息,如果支付状态信息是成功那么就自动跳转。,如果是失败继续查看

      // 5、 处理用户点击行为  点击确认和点击取消  在beforeClose当中去处理,可以让我们选择的去关闭消息盒子



      // With promises
      try {
        const imgUrl = await QRCode.toDataURL(this.orderInfo.codeUrl); //会把支付链接信息转化为二维码图片的路径
        this.$alert(`<img src="${imgUrl}" />`, "请使用微信扫码支付", {
          dangerouslyUseHTMLString: true,
          showClose: false,
          showCancelButton: true,
          cancelButtonText: "支付中遇到了问题",
          confirmButtonText: "我已经成功支付",
          center: true,
      //取消弹框之前的操作   beforeClose: (action, instance, done) => { if (action === "confirm") { //确认按钮 if (this.status !== 200) { clearInterval(this.timer); this.timer = null; this.$router.push("/paysuccess"); done(); //手动关闭消息盒子,如果不调,那么就永远不关闭 } else { this.$message.warning("请确保支付成功"); } } else if (action === "cancel") { //取消按钮 clearInterval(this.timer); this.timer = null; this.$message.warning("请联系前台小姐姐"); done() } } }) .then(() => {}) //代表你点了确认按钮后的逻辑 都会强制关闭消息盒子 .catch(() => {}); //代表你点了取消按钮后的逻辑 都会强制关闭消息盒子 } catch (error) { this.$message.error(error.message); } // 循环定时器 每3秒发请求查看支付状态信息 // 定时器设置后返回的是一个编号,是一个数字,我们使用变量存储的是这个数字 // 定时器又是一个异步操作,所以会有对应得管理模块去管理 ,依赖的是编号 // 清除定时器,其实是把这个编号的定时器任务清除,但是这个编号还是存在你之前保存的变量当中 // 因此以后清除定时器 记得把保存编号的变量也去置为null,代表彻底清除 if (!this.timer) { this.timer = setInterval(async () => { const result = await this.$API.reqPayStatus(this.orderInfo.orderId); if (result.code === 200) { //支付成功 //支付成功的状态码保存一下,为了用户点击成功支付按钮的时候去判断 this.status = 200; clearInterval(this.timer); //取消定时器 this.timer = null; this.$router.push("/paysuccess"); this.$msgbox.close(); //手动关闭消息盒子 } }, 3000); } }

 

 注;1,qrcode的git连接: https://github.com/soldair/node-qrcode

2.QRCode.toDataURL(this.orderInfo.codeUrl) 是一个promise,返回的是一个二维码图片路径

3, codeUrl:"weixin://wxpay/bizpayurl?pr=DcuIayu" 是之前返回的响应数据

 

 

 3, 封装请求查看订单的支付状态信息接口,需要查看订单支付是否成功,

//请求查看订单的支付状态信息 /api/payment/weixin/queryPayStatus/{orderId}  get
// 返回状态200代表支付成功   205代表支付中

export const reqPayStatus = (orderId) => Ajax.get(`/payment/weixin/queryPayStatus/${orderId}`)

 

 
 
 
 
 
 
 
 
 
 
 
 
posted @ 2020-08-10 20:53  全情海洋  阅读(243)  评论(0编辑  收藏  举报