交易页面
1、静态组件及路由跳转
2、获取交易页数据
(1)接口
//获取用户地址信息 地址:/api/user/userAddress/auth/findUserAddressList 请求方式:GET 参数:无
export const reqAddressInfo = ()=> requests({url:'/user/userAddress/auth/findUserAddressList',method:'GET'})
//获取商品清单 地址:/api/order/auth/trade 请求方式:GET 参数:无
export const reqOrderInfo = ()=> requests({url:'/order/auth/trade',method:'GET'})
(2)新建小仓库trade.js书写vuex三连环
import {reqAddressInfo,reqOrderInfo} from '@/api/index'
const state ={
adress:[],
orderInfo:[]
}
const mutations ={
GETUSERADDRESS(state,adress){
state.adress == adress
},
GETORDERINFO(state,orderInfo){
state.orderInfo = orderInfo
}
}
const actions ={
//获取用户地址信息
async getUserAddress({commit}){
let result = await reqAddressInfo()
if(result.code == 200){
commit('GETUSERADDRESS',result.data)
}
},
//获取商品清单
async getOrderInfo({commit}){
let result = await reqOrderInfo()
if(result.code == 200){
commit('GETORDERINFO',result.data)
}
}
}
const getters ={}
export default {
state,
mutations,
actions,
getters
}
(3)路由跳转时派发action,即交易页面挂载完毕
mounted(){
this.$store.dispatch('getUserAddress')
this.$store.dispatch('getOrderInfo')
}
3、映射数据
...mapState({
addressInfo:state => state.trade.address,
orderInfo:state => state.trade.orderInfo
}),
4、展示数据
//提交订单时的地址
userDefaultAddress(){
return this.addressInfo.find(item=> item.isDefault == 1) || {}
}
5、给地址添加点击事件,点击时边框变红并设置为默认地址
//修改默认地址
changeDefault(address,addressInfo){
//全部的isDefault为0
addressInfo.forEach(item => item.isDefault = 0);
address.isDefault = 1
}
find:查找数组中符合条件的元素返回作为最终结果
提交订单
1、路由跳转
2、点击提交订单时,还需要向服务器发起一次请求并将支付的信息传递给服务器
(1)接口
//提交订单 地址:/api/order/auth/submitOrder?tradeNo={tradeNo} 请求方式:POST 参数:有
export const reqSubmitOrder = (tradeNo,data)=> requests({url:`/order/auth/submitOrder?tradeNo=${tradeNo}`,data,method:'POST'})
(2)组件内调用请求函数
- 将api文件夹里面全部请求函数统一引入在main.js文件中
//统一引入api文件夹里的全部请求函数
import * as API from '@/api'
- 全局事件总线所有API挂载到Vue原型上
Vue.prototype.$API = API
支付页面
1、静态组件
2、使用编程式路由跳转
3、在组件内调用请求函数
//提交订单
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
}
let result = await this.$API.reqSubmitOrder(tradeNo,data)
if(result.code == 200){
this.orderId = result.data
//路由跳转+传参
this.$router.push('/pay?orderId='+this.orderId)
}else{
alert(result.data)
}
}
4、数据展示orderId
5、拿着orderId向服务器发请求获取订单信息
(1)接口
//获取支付信息 地址:/api/payment/weixin/createNative/{orderId} 请求方式:GET 参数:有
export const reqPayInfo = (orderId)=> requests({url:`/payment/weixin/createNative/${orderId}`,method:'GET'})
(2)在ThePay组件挂载完毕之后发请求
mounted(){
this.getPayInfo()
},
methods:{
async getPayInfo(){
let result = await this.$API.reqPayInfo(this.orderId)
//如果成功在组件当中存储支付信息
if(result.code == 200){
this.payInfo = result.data
}
}
}
别在生命周期函数中async
6、展示信息
微信支付
1、编程式导航
2、elementUI使用
安装:cnpm install --save element-ui
按需加载:
(1)借助babel-plugin-component,所以需要安装
cnpm install babel-plugin-component -D
(2)将babel.config.js文件修改一下,加入以下内容
'plugins': [
[
'component',
{
'libraryName': 'element-ui',
'styleLibraryName': 'theme-chalk'
}
]
在main.js文件中全局注册想要的组件
重启项目
引入注册:
(1)main.js文件里引入import {MessageBox} from 'element-ui'
(2)注册
Vue.prototype.$msgbox = MessageBox
Vue.prototype.$alert = MessageBox.alert
使用:
//弹出框
open(){
this.$alert('HTML',{
dangerouslyUseHTMLString:true,
center:true,
//是否显示取消按钮
showCancelButton:true,
//取消按钮的文本内容
cancelButtonText:'支付遇见问题',
confirmButtonText:'已完成支付',
//是否保留右上角取消按钮
showClose:false
})
}
React(Vue):antd[PC端]----antd-mobile[移动端]
Vue:ElementUI[PC端]----vant[移动端]
3、利用插件生成二维码
安装:cnpm i qrcode --save
引入: import QRCode from 'qrcode'
使用:
//生成二维码(地址)
let url = await QRCode.toDataURL(this.payInfo.codeUrl)
this.$alert(`<img src=${url} />`,'请你微信支付',{
4、二维码生成之后需要知道成功或失败,如果支付成功就路由跳转如果支付失败弹出提示信息,所以此时需要向服务器发请求。
(1)接口
//获取订单支付状态 地址:/api/payment/weixin/queryPayStatus/{orderId} 请求方式:GET 参数:有
export const reqPayStatus = (orderId)=>requests({url:`/payment/weixin/queryPayStatus/${orderId}`,method:'GET'})
(2)支付成功页面的静态组件已经路由配置
(3)发请求
if(!this.timer){
this.timer = setInterval( async ()=>{
//发请求获取用户状态
let result = await this.$API.reqPayStatus(this.orderId)
console.log(result);
if(result.code==200){
//第一步:清除定时器
clearInterval(this.timer)
this.timer = null
//第二步:保存支付成功返回的code
this.code = result.code
//第三步:关闭弹出框
this.$msgbox.close()
//第四步:跳转到下一个路由
this.$router.push('/paysuccess')
}
},1000)
}
(4)弹出框按钮的相关工作,在element UI 方法里添加beforeClose属性
//关闭弹出框的配置 第一参数:取消或完成 第二参数:当前组件实例 第三参数:关闭弹出框的方法
beforeClose:(type,instance,done)=>{
if(type=='cancel'){
alert('请联系qq账号 3165281613')
//清除定时器
clearInterval(this.timer)
this.timer = null
//关闭弹出框
done()
}else{
//判断是否真的支付了
if(this.code == 200){
//清除定时器
clearInterval(this.timer)
this.timer = null
done()
//路由跳转
this.$router.push('/paysuccess')
}
}
此时需要使用到定时器,当用户没有支付即服务器返回的是未支付成功,此时需要一直向服务器发送请求,直到支付完成或是取消支付
个人中心
1、静态展示以及路由跳转,即从支付成功页面点击查看订单跳转到个人中心页面
2、将个人中心右侧展示拆分成两个子路由,在center文件夹内新建myOrder和groupOrder文件夹
3、注册子路由并且设置访问center时自动访问myorder
//二级路由
children:[
{
path:'myorder',
component:MyOrder,
},
{
path:'grouporder',
component:GroupOrder,
},
{
path:'/center',
redirect:'/center/myorder'
}
]
4、声名式导航
<dd>
<router-link to="/center/myorder">我的订单</router-link>
</dd>
<dd>
<router-link to="/center/grouporder">团购订单</router-link>
</dd>
我的订单
1、接口,获取我的订单列表
//获取个人中心的数据 地址:/api/order/auth/{page}/{limit} 请求方式:GET 参数:有
export const reqMyOrderList = (page,limit)=>requests({url:`/order/auth/${page}/${limit}`,method:'GET'})
2、在MyOrder组件挂载完毕或是点击页码后发送请求
data(){
return{
//当前第几页
page:1,
//每一页展示个数
limit:3,
//存储我的订单的数据
myOrder:{}
}
},
mounted(){
//获取我的订单的数据的方法
this.getData()
},
methods:{
//获取我的订单的数据
async getData(){
//结构参数
const{page,limit} = this
let result = await this.$API.reqMyOrderList(page,limit)
if(result.code == 200){
this.myOrder = result.data
}
}
}
3、数据展示
<div class="orders">
<table class="order-item" v-for="order in myOrder.records" :key="order.id">
<thead>
<tr>
<th colspan="5">
<span class="ordertitle"
>{{order.createTime}} 订单编号:{{order.outTradeNo}}
<span class="pull-right delete"
><img src="../images/delete.png" /></span
></span>
</th>
</tr>
</thead>
<tbody>
<tr v-for="(cart,index) in order.orderDetailList" :key="cart.id">
<td width="60%">
<div class="typographic">
<img :src="cart.imgUrl" style="width:100px;height:100px;"/>
<a href="#" class="block-text">{{cart.skuName}}</a
>
<span>x1</span>
<a href="#" class="service">售后申请</a>
</div>
</td>
<td :rowspan="order.orderDetailList.length" v-if="index == 0" width="8%" class="center">{{order.consignee}}</td>
<td :rowspan="order.orderDetailList.length" v-if="index == 0" width="13%" class="center">
<ul class="unstyled">
<li>总金额¥{{order.totalAmount}}</li>
<li>在线支付</li>
</ul>
</td>
<td :rowspan="order.orderDetailList.length" v-if="index == 0" width="8%" class="center">
<a href="#" class="btn">{{order.orderStatusName}}</a>
</td>
<td :rowspan="order.orderDetailList.length" v-if="index == 0" width="13%" class="center">
<ul class="unstyled">
<li>
<a href="mycomment.html" target="_blank">评价|晒单</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</div>
4、设置分页器
<div class="choose-order">
<!-- 分页器 -->
<PagiNation
:pageNo="page"
:pageSize="limit"
:total="myOrder.total"
:continues="5"
@getPageNo="getPageNo"
/>
</div>
//获取点击哪一页
getPageNo(page){
//修改组件响应式数据
this.page = page
this.getData()
}
面试题:是否封装过组件?即可回答封装过如分页器、日历