• 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}`)
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    Springboot security cas整合方案-实践篇
    Springboot security cas源码陶冶-ExceptionTranslationFilter
    Springboot security cas源码陶冶-FilterSecurityInterceptor
    Springboot security cas源码陶冶-CasAuthenticationFilter
    Springboot security cas整合方案-原理篇
    Spring源码情操陶冶-AnnotationConfigBeanDefinitionParser注解配置解析器
    Spring源码情操陶冶-PropertyPlaceholderBeanDefinitionParser注解配置解析器
    Spring源码情操陶冶-PathMatchingResourcePatternResolver路径资源匹配溶解器
    Spring源码情操陶冶-ComponentScanBeanDefinitionParser文件扫描解析器
    802.1X技术介绍
  • 原文地址:https://www.cnblogs.com/fsg6/p/13472099.html
Copyright © 2020-2023  润新知