点击提交订单–跳到支付页面—是要发请求的 带参数过去
pay的静态组件拆分好
路由配置好
import Pay from '@/pages/Pay'
{
path: '/pay',
component: Pay,
// 将query参数映射成props传递给路由组件
props: route => ({orderId: route.query.orderId}),
/* 只能从交易界面, 才能跳转到支付界面 */
beforeEnter (to, from, next) {
if (from.path==='/trade') {
next()
} else {
next('/trade')
}
}
},
跳到支付页面—是要发请求的 带参数过去
//1 api
//提交订单的接口
//URL:/api/order/auth/submitOrder?tradeNo={tradeNo} method:post
export const reqSubmitOrder = (tradeNo,data)=>requests({url:`/order/auth/submitOrder?tradeNo=${tradeNo}`,data,method:'post'});
//2 发请求 拿数据 这次不用vuex 直接组件接管数据进行展示
//所有暴露的接口 同一接收api中的请求函数 就不用一个一个引 main.js
import * as API from '@/api';
//挂在vue的proto原型对象身上---所有组件直接找这个对象用-- Vue.prototype.$API = API;
beforeCreate() {
Vue.prototype.$bus = this;
Vue.prototype.$API = API;
},
//点击提交订单组件中
<a class="subBtn" @click="submitOrder">提交订单</a>
//提交订单
async submitOrder() {
//交易编码
let { tradeNo } = this.orderInfo;
//其余的六个参数
let data = {
consignee: this.userDefaultAddress.consignee, //最终收件人的名字
consigneeTel: this.userDefaultAddress.phoneNum, //最终收件人的手机号
deliveryAddress: this.userDefaultAddress.fullAddress, //收件人的地址
paymentWay: "ONLINE", //支付方式
orderComment: this.msg, //买家的留言信息
orderDetailList: this.orderInfo.detailArrayList, //商品清单
};
//需要带参数的:tradeNo
let result = await this.$API.reqSubmitOrder(tradeNo, data);
//提交订单成功
if (result.code == 200) {
//orderId在前面定义一下 ----orderId: "",
this.orderId = result.data;
//路由跳转 + 路由传递参数---这边支付页面要用
this.$router.push('/pay?orderId='+this.orderId);
//提交的订单失败
} else {
alert(result.data);
}
},
支付页面中
//计算完之后用
computed: {
orderId() {
return this.$route.query.orderId;
},
},
//支付金额需要拿着获取的订单号发请求的--捞到订单支付信息
//api
//获取支付信息
//URL:/api/payment/weixin/createNative/{orderId} GET
export const reqPayInfo = (orderId) => requests({ url: `/payment/weixin/createNative/${orderId}`, method: 'get' });
//在组件的mounted中发请求
//工作的时候:尽量别再生命周期函数中async|await
mounted() {
//不允许给生命周期函数加async,所以可以封装成一个函数
this.getPayInfo();
},
//获取支付信息---methods
async getPayInfo() {
let result = await this.$API.reqPayInfo(this.orderId);
//如果成功:组件当中存储支付信息
if (result.code == 200) {
//先在data中定义payInfo: {},
this.payInfo = result.data;
}
},
//然后在结构中进行展示就ok
支付时跳出来的浮窗,用element-ui做
按需引入注意配置文件发送变化,需要重启项目
//main.js中
import { Button,MessageBox} from 'element-ui';
//注册全局组件
Vue.component(Button.name,Button);
//ElementUI注册组件的时候,还有一种写法,挂在原型上
Vue.prototype.$msgbox = MessageBox;
Vue.prototype.$alert = MessageBox.alert;
//在立即支付按钮组件中
<a class="btn" @click="open">立即支付</a>
//点击立即支付弹出二维码
open() {
this.$alert("<strong>这是 <i>HTML</i> 片段</strong>", "HTML 片段", {
dangerouslyUseHTMLString: true,
center: true,
showCancelButton: true,
cancelButtonText: "支付遇见问题",
confirmButtonText: "支付成功",
});
},
生成二维码的插件
npm i qrcode
//组件中用起来
import QRCode from "qrcode";
//获取支付订单状态
//URL:/api/payment/weixin/queryPayStatus/{orderId} get
export const reqPayStatus = (orderId) => requests({ url: `/payment/weixin/queryPayStatus/${orderId}`, method: 'get' });
//支付状态码
code: "",
//弹出框
async open() {
//生成二维(地址)
let url = await QRCode.toDataURL(this.payInfo.codeUrl);
this.$alert(`<img src=${url} />`, "请你微信支付", {
dangerouslyUseHTMLString: true,
//中间布局
center: true,
//是否显示取消按钮
showCancelButton: true,
//取消按钮的文本内容
cancelButtonText: "支付遇见问题",
//确定按钮的文本
confirmButtonText: "已支付成功",
//右上角的叉子没了
showClose: false,
//关闭弹出框的配置值
beforeClose: (type, instance, done) => {
//type:区分取消|确定按钮
//instance:当前组件实例
//done:关闭弹出框的方法
if (type == "cancel") {
alert("请联系管理员豪哥");
//清除定时器
clearInterval(this.timer);
this.timer = null;
//关闭弹出框
done();
} else {
//判断是否真的支付了
//开发人员:为了自己方便,这里判断先不要了
if (this.code == 200) {
clearInterval(this.timer);
this.timer = null;
done();
this.$router.push("/paysuccess");
}
}
},
});
//你需要知道支付成功|失败
//支付成功,路由的跳转,如果支付失败,提示信息
//定时器没有,开启一个新的定时器
if (!this.timer) {
this.timer = setInterval(async () => {
//发请求获取用户支付状态
let result = await this.$API.reqPayStatus(this.orderId);
//如果code==200
if (result.code == 200) {
//第一步:清除定时器
clearInterval(this.timer);
this.timer = null;
//保存支付成功返回的code---防止没有扫码支付就点击支付成功
this.code = result.code;
//关闭弹出框
this.$msgbox.close();
//跳转到下一路由---写一下这个
this.$router.push("/paysuccess");
}
}, 1000);
}
},
在二维码弹出之后,要一直发请求问服务器成功了吗
//获取订单支付状态
//URL:/api/payment/weixin/queryPayStatus/{orderId} method:get
export const reqPayStatus = (orderId) => requests({ url: `/payment/weixin/queryPayStatus/${orderId}`, method: 'get' });
// paysuccess
import PaySuccess from '@/pages/PaySuccess'
{
path: '/paysuccess',
component: PaySuccess,
/* 只有从支付界面, 才能跳转到支付成功的界面 */
beforeEnter (to, from, next) {
if (from.path==='/pay') {
next()
} else {
next('/pay')
}
}
},
个人中心—二级路由
将个人订单中右侧的内容拆成两个子组件,我的订单和团购订单—变成路由展示出来(不用标签展示
//注册路由组件
import Center from '@/pages/Center'
//引入二级路由组件
import myOrder from '@/pages/Center/myOrder'
import groupOrder from '@/pages/Center/groupOrder'
{
path: '/center',
component: Center,
children: [
{
// path: '/center/myorder',
path: 'myorder',
component: MyOrder,
},
{
path: 'groupbuy',
component: GroupBuy,
},
{
//重定向
path: '',
redirect: 'myorder'
}
]
},
<router-link to="/center/myorder">我的订单</router-link>
<router-link to="/center/grouporder">团购订单</router-link>
<!-- 路由组件出口的位置 -->
<router-view></router-view>
获取个人中心的数据
//获取个人中心的数据
//api/order/auth/{page}/{limit} get
export const reqMyOrderList = (page, limit) => requests({ url: `/order/auth/${page}/${limit}`, method: 'get' });
mounted() {
//获取我的订单的数据方法
this.getData();
},
//获取我的订单的方法
async getData() {
//解构出参数
const { page, limit } = this;
let result = await this.$API.reqMyOrderList(page, limit);
if (result.code == 200) {
this.myOrder = result.data;
}
},
//初始化参数
//当前第几页
page: 1,
//每一页展示数据个数
limit: 3,
//存储我的订单的数据
myOrder: {},
<!-- 每一笔订单 -->
<table
class="order-item"
v-for="(order, index) in myOrder.records"
:key="order.id"
>
<tr v-for="(cart, index) in order.orderDetailList" :key="cart.id">
//接下来替换真实数据
//注意:order.orderDetailList.length 根据订单条数变化
//v-if="index == 0",相同订单中的用户信息进行合并
<td
:rowspan="order.orderDetailList.length"
v-if="index == 0"
width="8%"
class="center"
>{{ order.consignee }}
</td>
//分页器
<Pagination
:pageNo="page"
:pageSize="limit"
:total="myOrder.total"
:continues="5"
@getPageNo="getPageNo"
/>
//获取当前点击那一页
getPageNo(page){
//修改组件响应式数据page
this.page = page;
this.getData();
}
未登入的路由守卫判断
//Header组件
<router-link to="/center/myorder">我的订单</router-link>
<router-link to="/shopcart">我的购物车</router-link>
//没登入只能去首页搜索详情页购物车页
else {
//未登录:不能去交易相关、不能去支付相关【pay|paysuccess】、不能去个人中心
//未登录去上面这些路由-----登录
let toPath = to.path;
if (toPath.indexOf('/trade') != -1 || toPath.indexOf('/pay') != -1 || toPath.indexOf('/center') != -1) {
//把未登录的时候向去而没有去成的信息,存储于地址栏中【路由】
next('/login?redirect=' + toPath);
} else {
//去的不是上面这些路由(home|search|shopCart)---放行
next();
}
}
//login中
//登录的路由组件:看路由当中是否包含query参数,有:调到query参数指定路由,没有:调到home
let toPath = this.$route.query.redirect||"/home";
this.$router.push(toPath);
路由独享守卫
只能从购物车跳到交易页面
只能从交易页面跳到支付页面
只能从支付页面跳到支付成功页面
//trade路由中
{
path: '/trade',
component: Trade,
/* 只能从购物车界面, 才能跳转到交易界面 */
beforeEnter (to, from, next) {
if (from.path==='/shopcart') {
next()
} else {
next('/shopcart')
}
}
},
{
path: '/pay',
component: Pay,
// 将query参数映射成props传递给路由组件
props: route => ({orderId: route.query.orderId}),
/* 只能从交易界面, 才能跳转到支付界面 */
beforeEnter (to, from, next) {
if (from.path==='/trade') {
next()
} else {
next('/trade')
}
}
},
组件内守卫
//支付成功路由组件内
//组件内守卫
beforeRouteEnter(to, from, next) {
// 在渲染该组件的对应路由被 confirm 前调用
// 不!能!获取组件实例 `this`
// 因为当守卫执行前,组件实例还没被创建
if (from.path == "/pay") {
next();
} else {
next(false);
}
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是该组件被复用时调用
// 举例来说,对于一个带有动态参数的路径 /foo/:id,在 /foo/1 和 /foo/2 之间跳转的时候,
// 由于会渲染同样的 Foo 组件,因此组件实例会被复用。而这个钩子就会在这个情况下被调用。
// 可以访问组件实例 `this`
console.log("12313131311313");
},
beforeRouteLeave(to, from, next) {
// 导航离开该组件的对应路由时调用
// 可以访问组件实例 `this`
next();
},