You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
shop-app/pages/order/submit.vue

376 lines
9.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
* @Author: ch
* @Date: 2022-03-20 14:14:53
* @LastEditors: ch
* @LastEditTime: 2022-04-28 19:55:04
* @Description: file content
-->
<template>
<view>
<UiWhiteBox>
<u-cell class="address" :border="false" isLink @click="selectAddress">
<view slot="title" class="address--title">
{{address.province ? address.province + address.city + address.area : '请选择收货地址'}}
</view>
<image class="address--icon" slot="icon" src="@/static/order/dw.png" />
<view slot="label" class="address--label" v-if="address.province">
<text>收货人:{{address.name}}</text>
<text>{{address.phone}}</text>
</view>
</u-cell>
</UiWhiteBox>
<view class="goods-group">
<view class="goods-group--item" v-for="item in orderInfo.products" :key="item.productId">
<image class="goods-group--item-image" mode="widthFix" :src="item.productImageUrl" />
<view >
<view class="goods-group--item-con">
<text class="goods-group--item-title">{{item.productName}}</text>
<text class="goods-group--item-pirce">¥{{item.productPrice}}</text>
</view>
<view class="goods-group--item-desc">
<text>{{item.skuDescribe}}</text>
<text class="goods-group--item-num">x{{item.quantity}}</text>
</view>
</view>
</view>
</view>
<UiWhiteBox>
<UiCell class="service--cell" title="配送方式" value="快递配送" :rightIcon="false"></UiCell>
<UiCell class="service--cell service--cell__last" title="买家留言" value="快递配送" :rightIcon="false">
<textarea slot="value" class="service--remark" auto-height v-model="userMessage"
maxlength="50" placeholder="填写您想要备注的信息50字以内" />
</UiCell>
</UiWhiteBox>
<UiWhiteBox>
<text class="play--title">支付方式</text>
<radio-group>
<u-cell title="微信支付" :border="false" @click="payType = 'wxpay'">
<image class="play--icon" slot="icon" src="@/static/order/wx.png"/>
<radio class="play--radio" slot="right-icon" color="#FF875B"
:checked="payType == 'wxpay'" ></radio>
</u-cell>
<u-cell title="支付宝支付" :border="false" @click="payType = 'alipay'">
<image class="play--icon" slot="icon" src="@/static/order/zfb.png"/>
<radio class="play--radio" slot="right-icon" color="#FF875B"
:checked="payType == 'alipay'"></radio>
</u-cell>
</radio-group>
</UiWhiteBox>
<UiWhiteBox class="amount">
<u-cell title="商品总额" :value="`¥${orderInfo.totalAmount}`" :border="false"></u-cell>
<u-cell title="运费" :value="`¥${orderInfo.shippingAmount}`" :border="false"></u-cell>
</UiWhiteBox>
<view class="footer">
<view class="footer--total">
<text>合计</text>
<text class="footer--amount">{{orderInfo.payAmount}}</text>
</view>
<UiButton class="footer--btn" type="solid" @click="submit"></UiButton>
</view>
</view>
</template>
<script>
import UiCell from '@/components/UiCell';
import {ApiPostSubmitOrder, ApiGetBeforeOrder, ApiGetBeforeCartOrder} from '@/common/api/order';
import { ApiPostWxH5Pay, ApiPostWxJsApiPay } from '@/common/api/wx';
import UiButton from '@/components/UiButton.vue';
import UiWhiteBox from '../../components/UiWhiteBox.vue';
export default {
components : {UiCell, UiButton, UiWhiteBox },
data(){
return {
address : {},
userMessage : '',
orderInfo : {},
payType : 'wxpay'
}
},
onLoad(){
// 从地址列表页改变了收货地址
uni.$on('changeAddress',(item, type)=>{
if(type == 'submitOrder'){
this.address = item;
}
});
// 默认选择设为默认的地址
this.address = this.$store.state.address.find(i => i.isDefault) || {};
},
onShow(){
this.getBeforeOrder();
},
methods:{
/**
* 获取预订单信息,将要提交的订单信息
*/
async getBeforeOrder(addressId){
const query = this.$Route.query;
let res = {};
// 购物车结算
if(query.mode === 'cart'){
res = await ApiGetBeforeCartOrder({
cartIds: query.ids,
recipientAddressId : addressId
})
}
// 立即购买
if(query.mode === 'buyNow'){
res = await ApiGetBeforeOrder({
productSkuId : query.skuId,
quantity : query.num,
activityId : query.activityId,
activityTimeId : query.activityTimeId,
// 1正常购买 2活动购买
activityType : query.activityType,
recipientAddressId : addressId
});
}
if(res.error){
uni.$u.toast(res.error.message);
return false;
}
this.orderInfo = res.result;
},
selectAddress(){
const selectedId = this.address.id;
const selectedPar = selectedId ? `&id=${selectedId}` : '&status=created';
this.$Router.push(`/addressList?source=submitOrder${selectedPar}`);
},
/**
* 提交订单
*/
async submit(){
const {query} = this.$Route;
if(!this.address.id){
uni.$u.toast('请选择收货地址');
return false;
}
const {error, result} = await ApiPostSubmitOrder({
orderSource : 2,
recipientAddressId : this.address.id,
shoppingCartIds : query.ids ? query.ids.split(',') : [],
products : this.orderInfo.products.map(i => ({
activityId : query.activityId,
activityTimeId : query.activityTimeId,
productId : i.productId,
productSkuId : i.productSkuId,
quantity : i.quantity,
activityType : query.activityType
})),
userMessage : this.userMessage
});
if(error){
uni.$u.toast(error.message);
return false;
}
if(this.payType === 'wxpay'){
this.wxpay(result.orderId);
}else{
uni.$u.toast('暂不支持支付宝支付');
}
},
async wxpay(orderId){
const openId = this.$store.state.openId;
if(openId) {
// 微信JSAPI
const {error, result} = await ApiPostWxJsApiPay({orderId,openId});
if(error){
uni.$u.toast(error.message);
return false;
}
/*
* 公众号id appId 是 String(16) wx8888888888888888
时间戳 timeStamp 是 String(32) 1414561699 当前的时间
随机字符串 nonceStr 是 String(32) 5K8264ILTKCH16CQ2502SI8ZNMTM67VS 随机字符串不长于32位。推荐随机数生成算法
订单详情扩展字符串 package 是 String(128) prepay_id=123456789 统一下单接口返回的prepay_id参数值提交格式如prepay_id=***
签名方式 signType 是 String(32) MD5 签名类型默认为MD5支持HMAC-SHA256和MD5。注意此处需与统一下单的签名类型一致
签名 paySign 是 String(64) C380BEC2BFD727A4B6845133519F3AD6 签名
*/
const par = result.dataInfo;
WeixinJSBridge.invoke('getBrandWCPayRequest', {
appId : par.appId,
timeStamp : par.timeStamp,
nonceStr : par.nonceStr,
package : par.packageValue,
signType : par.signType,
paySign : par.paySign
}, res => {
if(res.err_msg === 'get_brand_wcpay_request:cancel'){
this.$$Router.replace(`/payResult?orderId=${orderId}`);
}else{
this.$$Router.replace(`/orderDetail?id=${orderId}`);
}
})
}else{
// h5支付
const {error, result} = await ApiPostWxH5Pay({orderId});
if(error){
uni.$u.toast(error.message);
return false;
}
const redirect_url = decodeURIComponent(`https://like-app.mashibing.com/payResult?orderId=${orderId}`);
window.location.href = `${result.dataInfo.payUrl}&redirect_url=${redirect_url}`;
}
}
}
}
</script>
<style lang="scss" scoped>
page{
background: $color-grey1;
padding-bottom: 140rpx;
}
.address{
/deep/.u-cell__body__content{
padding: 10rpx 0;
}
&--title{
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 500rpx;
&__grey{
color: $color-grey4;
}
}
&--icon{
width: 28rpx;
height: 34rpx;
margin-right: 30rpx;
}
&--label{
margin-top: 26rpx;
text{
font-size: $font-size-sm;
color: $color-grey4;
margin-right: 40rpx;
}
}
}
.goods-group{
background: $color-grey0;
margin: 20rpx 0;
&--item{
display: flex;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1px solid $color-grey2;
&-image{
width: 180rpx;
height: 180rpx;
margin-right: 30rpx;
}
&-con{
width: 510rpx;
display: flex;
justify-content: space-between;
font-size: $font-size-base;
color: $color-grey6;
line-height: 39rpx;
}
&-title{
overflow:hidden;
text-overflow:ellipsis;
display:-webkit-box;
-webkit-box-orient:vertical;
-webkit-line-clamp:2;
}
&-pirce{
font-size: 22rpx;
margin-left: 60rpx;
}
&-desc{
width: 510rpx;
font-size: $font-size-sm;
color: $color-grey4;
margin-top: 20rpx;
line-height: 39rpx;
display: flex;
justify-content: space-between;
}
&-num{
font-size: $font-size-base;
margin-left: 60rpx;
}
}
}
.service{
&--cell{
border-radius: 16rpx;
padding: 0 30rpx;
&__last{
border: 0;
}
}
&--remark{
font-size: $font-size-base;
width: 500rpx;
text-align: right;
}
}
.play{
background: $color-grey0;
margin: 20rpx 0;
&--title{
font-size: $font-size-base;
padding: 30rpx;
display: block;
}
&--icon{
width: 39rpx;
height: 39rpx;
margin-right: 20rpx;
}
&--radio{
transform: scale(70%);
}
}
.amount{
background: $color-grey0;
}
.footer{
display: flex;
align-items: center;
justify-content: space-between;
height: 120rpx;
background: $color-grey0;
padding: 0 30rpx;
position: fixed;
bottom: 0;
right: 0;
left: 0;
&--total{
color: $color-grey5;
font-size: $font-size-sm;
display: flex;
align-items: center;
}
&--amount{
font-size: $font-size-lg;
color: $color-yellow4;
margin-left: 10rpx;
}
&--btn{
margin: 0;
}
}
</style>