选购好商品后,从购物车进入到订单页面,而安城订单页面的逻辑处理,和页面完善。在前面我们已经将订单页面的布局进行了说明。
订单页面包含几个栏目,第一个是我们的快递方式,存在自提和外送,包含选择用户的默认地址;
第二是我们商品页面,购物车中商品的展示;第三个就是支付方式,有微信和支付宝;第四个就是确认支付页面。
本文介绍了电商平台订单支付页面的开发实现,主要包含以下内容:1. 从购物车跳转到订单支付页面的流程;2. 订单页面的四大模块:配送方式、商品列表、支付方式和支付确认;3. 商品列表组件的复用设计,通过props参数实现灵活调用;4. 支付页面核心代码实现,包括支付方式选择、地址获取、订单创建和支付处理等功能;5. 通过Vuex管理购物车数据,实现数据共享和状态管理。整个支付流程采用模块化设计思路,注重组件复用性和数据交互处理。
1、从shop中购物车页面跳转到订单页面
1.1 shop的购物车页面
1.2 购物车的选好了,点击后跳转到订单页面
//跳转至确认订单也买那
goPay(){
uni.navigateTo({
url:”/pagesub/pageshop/paypage/paypage”
})
},
1.3 订单支付页面
2、订单支付paypage页面
2.1 物流方式页面
2.2 商品列表页面
2.3 支付方式界面
默认就是微信,如不是微信就然如下的方式运行
2.4 支付确认
3、支付页面paypage的商品列表(2.2小节)
<!– 购物列表 –>
<view class=”goodsList”>
<goods-list :goodsList=”carsList” :totalPrice=”totalPrice” :prePrice=”preferentialPrice”
:totalNum=”buyNum”></goods-list>
</view>
3.1 使用组件 good-list
<template>
<view class="goodsLayout">
<view class="wrapper">
<!-- 描述数量多少 buyNum 来至于父级,父级来自于vuex -->
<view class="title">共{
{goodsList.length}}类商品 {
{buyNum}}件</view>
<!-- 选购商品列表 -->
<view class="list">
<!-- goodsList父传来的值 -->
<view class="row" v-for="(item,index) in goodsList" key="index">
<!-- 左边是商品的缩略图 名称 -->
<view class="left">
<image :src="item.thumb[0].url">{item.name}}</view>
</view>
<!-- 中间是商品数量 -->
<view class="center">×{
{item.numvalue}}</view>
<!-- 商品的价格 -->
<view class="right">
<view class="big">¥{
{priceFormat(item.price)}}</view>
<view class="small" v-if="item.before_price">¥{
{priceFormat(item.before_price)}}</view>
</view>
</view>
</view>
<!-- 商品的价格合计-->
<view class="total">
<text>
已优惠¥{
{priceFormat(prePrice)}},
</text> 合计 <text class="big">¥{
{priceFormat(totalPrice)}}</text>
</view>
</view>
</view>
</template>
3.1.1 其中priceFormat来自于公共方法中的价格格式化
import {
priceFormat
} from “@/utils/tools.js”
记得在方法里面要定义:
methods: {
priceFormat
}
3.2 订单支付页面paypage 的处理
从good-list中来看,有部分值来至于父级也就是 paypage页面。
为了goodlist 组件能被很多页面调用,我们就把里面的参数进行了传值处理。避免写得不灵活。
在这个订单支付页面要使用,在订单查看页面也要使用。但是值是不一样得。通过那个调用,那个传值得方式,灵活定义参数需要得值。
<!– 购物列表 –>
<view class=”goodsList”>
<goods-list :goodsList=”carsList” :totalPrice=”totalPrice” :prePrice=”preferentialPrice”
:totalNum=”buyNum”></goods-list>
</view>
上面是该页面调用,需要传得数值。
<goods-list :goodsList=”carsList” :totalPrice=”totalPrice” :prePrice=”preferentialPrice”
:totalNum=”buyNum”></goods-list>
goodsList来自于 vuex cars 中的值 carsList
totalPrice来自于 vuex cars 中的计算值 totalPrice
prePrice 来自于 vuex cars 中的计算值 preferentialPrice
totalNum 来自于 vuex cars 中的计算值 buyNum
4、代码
<template>
<view>
<u-notice-bar text="本商城产品为学习交流使用, 下单概不发货, 请谨慎下单~~"></u-notice-bar>
<view class="paypage">
<!-- 确认订单,支付订单 -->
<!-- 配送方式 -->
<delivery-layout :deliveryInfo="deliveryInfo"></delivery-layout>
<!-- 购物列表 -->
<view class="goodsList">
<goods-list :goodsList="carsList" :totalPrice="totalPrice" :prePrice="preferentialPrice"
:totalNum="buyNum"></goods-list>
</view>
<!-- #ifndef MP-WEIXIN -->
<view class="paytype">
<view class="box" :class="item.value == payDefValue ? 'active':''" v-for="item in payType"
@click="clickPayBtn(item.value)">
<u-icon :name="item.icon" :color="item.color" class="icon" size="26"></u-icon>
<text class="font">{
{item.name}}</text>
</view>
</view>
<!-- #endif -->
<view class="payTabbar">
<car-layout type="pay" :payBtnState="payBtnState" @confirmPay="onConfirmPay"></car-layout>
</view>
<uni-pay ref="uniPay" returnUrl="/pages/order/order" @success="paySuccess" @cancel="payCancel"
@create="payCreate"></uni-pay>
</view>
</view>
</template>
<script>
import {
mapGetters,
mapMutations
} from "vuex"
const addressCloudObj = uniCloud.importObject("green-mall-address");
const orderCloudObj = uniCloud.importObject("green-mall-order", {
customUI: true
});
export default {
data() {
return {
deliveryInfo: {
address: "",
username: "",
mobile: ""
},
// #ifdef APP-PLUS || H5
payDefValue: "alipay",
// #endif
// #ifdef MP-WEIXIN
payDefValue: 'wxpay',
// #endif
payType: [{
name: "支付宝",
value: "alipay", //必须写这个值,后面要用到
color: "#1578FF",
icon: "zhifubao" //:color="item.value==payDefValue ? item.color :''"
}, {
name: "微信",
value: "wxpay",
color: "#04C15F",
icon: "weixin-fill"
}],
payLoading: true
};
},
computed: {
...mapGetters(['carsList', 'totalPrice', 'preferentialPrice', "buyNum"]),
payBtnState() {
let bool = Object.keys(this.deliveryInfo).every(item => {
return this.deliveryInfo[item] != ""
})
return this.carsList.length > 0 && this.totalPrice > 0 && bool && this.payLoading
}
},
onLoad() {
this.getDefAddressData();
uni.$on("selectAddressEvent", (e) => {
this.deliveryInfo = e;
})
},
onUnload() {
uni.$off("selectAddressEvent")
},
methods: {
...mapMutations(["SET_CARS_LIST"]),
//点击支付按钮发起支付
async onConfirmPay() {
this.payLoading = false;
let obj = {
deliveryInfo: this.deliveryInfo,
carsList: this.carsList,
createTime: Date.now(),
payType: this.payDefValue,
status: 0,
total_fee: this.totalPrice,
done: false
}
let order_no = await orderCloudObj.createOrder(obj);
let out_trade_no = order_no + "_" + String(Math.random()).substring(3, 9)
this.$refs.uniPay.createOrder({
provider: this.payDefValue, // 支付供应商
total_fee: this.totalPrice, // 支付金额,单位分 100 = 1元
type: "goods", // 支付回调类型
order_no, // 业务系统订单号
out_trade_no, // 插件支付单号
description: "购买商品的支付", // 支付描述
})
},
//支付成功的回调
paySuccess(e) {
this.payLoading = true;
this.SET_CARS_LIST();
console.log(e);
},
payCancel(e) {
console.log(e);
},
payCreate(e) {
console.log(e);
},
//选择支付类型
clickPayBtn(value) {
this.payDefValue = value
},
//获取默认地址
async getDefAddressData() {
let res = await addressCloudObj.getDefAddress();
if (!res.data.length) return;
let {
address,
area_name,
username,
mobile
} = res.data[0];
this.deliveryInfo = {
address: area_name + address,
username,
mobile
}
}
}
}
</script>
<style lang="scss" scoped>
page {
background: $page-bg-color; //页面背景色
}
.paypage {
padding: 30rpx;
.goodsList {
margin-top: 30rpx;
}
.paytype {
@include flex-box();
.box {
//box 就两个支付方式
width: 49%; //一个支付方式站49 剩下中间的2的空格
height: 75rpx;
background: #fff;
border-radius: 10rpx;
@include flex-box-set();
border: 1px solid #fff;
//filter: grayscale(100%); //滤镜效果 100%把颜色全滤掉 我们已经用了 :color="item.value==payDefValue ? item.color :''" 就不用滤镜了
filter: grayscale(100%);
.font {
padding-left: 10rpx;
}
}
//可以这样 当用text时,若用view + style 就不用下面的方式
.box:first-child.active {
border-color: #1578FF; //边框颜色
color: #1578FF;
filter: grayscale(0%);
//filter: grayscale(0%)
}
.box:last-child.active {
border-color: #04C15F;
color: #04C15F;
filter: grayscale(0%);
//filter: grayscale(0%)
}
}
.payTabbar {
position: fixed;
width: 100%;
bottom: 0;
left: 0;
}
}
</style>
暂无评论内容