Files
frontend-app/pages/order_submit/order_submit.vue
T
2025-03-23 20:36:06 +08:00

691 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<view class="order_submit_warp">
<!-- 收件人信息 -->
<view class="order_submit_header_warp" @click="checkAddressShow(true,'data')" v-if="orderInfo.address && Object.keys(orderInfo.address).length !==0">
<view class="header_areaAddress_warp">
<view class="tab-comm areaAddress_default" v-if="orderInfo.address.isDefault">默认</view>
<!-- <view class="tab-comm areaAddress_tab">家</view> -->
<text>{{assembleAddress(orderInfo.address).names}}</text>
</view>
<view class="header_detailedAddress_warp">
<view style="width: 90%;">{{orderInfo.address.address}}</view>
<up-image src="/static/common/right.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
<view class="header_name_warp">
<text style="margin-right: 20rpx;">{{orderInfo.address.name}}</text>
<text>{{orderInfo.address.phone}}</text>
</view>
</view>
<!-- 没有地址 -->
<view v-else class="no_address" @click="checkAddressShow(true,'data')">
<view class="no_address_title">
<view>请填写地址</view>
<up-image src="/static/common/right.png" width="14" height="14" bgColor="#f1f6ff00"></up-image>
</view>
<view class="no_address_msg">您还未添加收货地址,请完善地址!</view>
</view>
<!-- 店铺信息 -->
<view class="order_store_warp order_product_warp" v-for="(item,index) in orderInfo.shops" :key="item.id">
<!-- 头部 -->
<view class="order_product_header">
<up-image :src="item.logo" width="22" height="22" bgColor="#f1f6ff00"></up-image>
<view class="order_product_title">{{item.name}}</view>
</view>
<view v-for="(addItem,addIndex) in item.addrTimes" :key="addIndex">
<!-- 单个地址 -->
<view v-if="addItem.address" class="shops_address_warp" @click="checkAddressShow(true,'addrTimes',addIndex,index)">
<view class="shops_address_warp_title">
<text style="margin-right: 20rpx;">{{addItem.address.name}}</text>
<text>{{addItem.address.address}}</text>
</view>
<view>
<up-image src="/static/common/right.png" width="16" height="16" bgColor="#f1f6ff00"></up-image>
</view>
</view>
<!-- 产品详情 -->
<view class="order_item_content" v-for="(pItem,pIndex) in addItem.goods" :key="pItem.id">
<up-image :src="pItem.img" width="80" height="80" bgColor="#f1f6ff00"></up-image>
<view class="content_info_right">
<view>
<view class="content_info_title">{{pItem.title}}</view>
<view class="content_info_tag">{{pItem.specs}}</view>
</view>
<view class="content_info_right_total">
<view class="content_right_total">
<view>¥<text style="font-size: 36rpx;">{{pItem.totalPrice}}</text></view>
<view>每件到手价¥{{pItem.unitPrice}}</view>
</view>
<view class="shopping_info_quantity">
<view class="quantity_but" @click="quantityFun('minus',index,addIndex,pIndex)">-</view>
<view class="quantity_value">{{pItem.num}}</view>
<view class="quantity_but" @click="quantityFun('add',index,addIndex,pIndex)">+</view>
</view>
</view>
</view>
</view>
<view class="content_info_right_remark">
<view class="title">留言</view>
<up-input
placeholder="建议留言前先与商家沟通确认"
border="surround"
v-model="addItem.remark"
:customStyle="{
'text-align': 'right !important',
'border':'0rpx',
}"
style="text-align: right;"
></up-input>
</view>
<!-- 运费 -->
<view class="order_freight_warp">
<view class="order_freight_item">
<view>运费</view>
<view class="value_">
<text style="color: #9E9E9E;">({{getValue(PRODUCT_DELIVERY_TIME,addItem.deliveryTime)}})</text>包邮
</view>
</view>
<!-- <view class="order_freight_item">
<view>优惠<text class="coupon_">已选优惠券</text></view>
<view class="value_"><text>-¥{{orderInfo.coupon}}</text></view>
</view> -->
</view>
</view>
</view>
<!-- 支付方式 -->
<view class="order_way_warp" @click="wayShow = true;">
<view>支付方式</view>
<view class="order_way_right">
{{getValue(PAYMENT_WAY_,orderInfo.paymentMethod)}}
<up-image src="/static/common/right.png" width="20" height="20" bgColor="#f1f6ff00"></up-image>
</view>
</view>
<!-- 去支付的固定按钮 -->
<view class="order_pay_but">
<view class="price_">¥<text style="font-size: 60rpx;">{{orderInfo.amount}}</text></view>
<view class="_but" @click="goPay">支付</view>
</view>
<!-- 选择支付方式 -->
<up-popup v-model:show="wayShow" :round="10" :closeOnClickOverlay="false" :closeable="true" :safeAreaInsetBottom="false">
<view class="way_popup_warp">
<view class="way_popup_title">支付方式</view>
<up-radio-group
v-model="orderInfo.paymentMethod"
placement="column"
>
<view class="way_item" v-for="item in wayList" :key="item.id">
<view class="way_item_">
<view style="margin-top: 2rpx;"><up-image :src="item.path" width="20" height="20" bgColor="#f1f6ff00"></up-image></view>
<view class="way_item_val">{{item.name}}</view>
</view>
<up-radio
:name="item.id"
:disabled="item.disabled"
activeColor="#FF7C41"
>
</up-radio>
</view>
</up-radio-group>
<view class="popup_but" @click="wayShow=false;">
确认
</view>
</view>
</up-popup>
<!-- 选择地址 -->
<up-popup v-model:show="addressShow" :round="10" :closeOnClickOverlay="false" :closeable="true" :safeAreaInsetBottom="false" @close="checkAddressShow(false,null,0,0)">
<view class="address_popup_warp">
<view class="address_popup_title">收件地址</view>
<view class="address_popup_content">
<Address @valueFunc="getAddressValueFunc"/>
</view>
<view class="popup_but" @click="addressOk">
确认
</view>
</view>
</up-popup>
<up-toast ref="uToastRef"></up-toast>
</view>
</template>
<script>
import Address from '@/components/address.vue';
import { PAYMENT_WAY,PAYMENT_WAY_,PRODUCT_DELIVERY_TIME,getValue } from '@/utils/enumUtils.js';
import { getSettleList,settle } from '@/api/cart.js'
import { feedback } from '@/api/payment.js';
import { assembleAddress } from '@/utils/index.js'
export default {
computed: {
PAYMENT_WAY_() {
return PAYMENT_WAY_;
},
PRODUCT_DELIVERY_TIME() {
return PRODUCT_DELIVERY_TIME;
}
},
components: {
Address,
},
onLoad(option) {
const ids = option.ids;
if(ids){
this.ids = ids;
this.getOrder();
}
},
data() {
return {
ids:0,
orderInfo:{
// coupon:2,//优惠卷
paymentMethod:null,// 支付方式
total:4000,// 需要支付的总金额
address:{},// 选中的地址
store:[],
},
wayList:[
{
disabled:false,
id:PAYMENT_WAY.WECHAT,
name:"微信支付",
path:"/static/product/way_wx.png",
},
{
disabled:false,
id:PAYMENT_WAY.ALIPAY,
name:"支付宝支付",
path:"/static/product/way_zfb.png",
},
],
wayShow:false,
addressShow:false,// 收件地址选择
addressType:'',// 收件地址数据类型
addressIndex:0,// 收件地址数据类型
shopsIndex:0,// 收件地址数据类型
selectAddress:{},// 收件地址选择
};
},
methods: {
getValue,
assembleAddress,
async getOrder(){
const ids = this.ids;
if(!ids || ids ===0){
this.$refs.uToastRef.show({
type: 'error',
message: "暂时没有需要结算的订单",
});
setTimeout(()=>{
uni.switchTab({
url: '/pages/shopping_cart/shopping_cart',
})
},2000)
return;
}
const params = {
cartIds:ids,
}
const resp = await getSettleList(params);
if(resp && resp.bizcode === 100){
const data = resp.data;
const shops = data.shops;
if(shops && shops.length !==0){
shops.map(item=>{
item.addrTimes.map(addItem=>{
addItem.remark=null;
})
})
}
data.shops = shops;
data.paymentMethod = null;// 支付方式
this.orderInfo = data;
}
},
/**
* 数量进行增加删除
* @param {Object} type 区分是 + 还是 -
* @param {Object} pIndex 父节点数据,用作与从新修改数据
* @param {Object} addIndex 需要修改店铺的数据节点
* @param {Object} index 需要修改的数据节点
*/
quantityFun(type,index,addIndex,pIndex){
let currentQuantity = this.orderInfo.shops[index].addrTimes[addIndex].goods[pIndex].num;// 当前数量
if(type === "minus"){
if(currentQuantity === 1){
this.$refs.uToastRef.show({
type: 'error',
message: "不能再减拉,不能小于最低购买数量~",
});
}else{
currentQuantity = currentQuantity - 1;
}
}else if(type === "add"){
// 需要判断一下库存
currentQuantity = currentQuantity + 1;
}
this.orderInfo.shops[index].addrTimes[addIndex].goods[pIndex].num = currentQuantity;
},
// 获取备注
getRemark(){
const orderInfo = this.orderInfo;
console.log("orderInfo",orderInfo);
const remarkArr = [];
if(orderInfo && Object.keys(orderInfo).length!==0){
const remarObj={};
if(orderInfo.shops && orderInfo.shops.length!==0){
orderInfo.shops.map(sItem=>{
if(sItem.addrTimes && sItem.addrTimes.length !==0){
sItem.addrTimes.map(addItem=>{
if(addItem.remark){
remarObj.gkey = addItem.groupKey;
remarObj.rmk = addItem.remark;
}
})
}
})
}
remarkArr.push(remarObj);
}
console.log("remarkArr",remarkArr);
return remarkArr;
},
/**
* 去支付
*/
async goPay(){
const orderInfo = this.orderInfo;
const way = orderInfo.paymentMethod;
if(!way || way === 0){
this.$refs.uToastRef.show({
type: 'error',
message: "请先选择支付方式",
});
return;
}
const params={
addrId:orderInfo.address.id,// 收货地址ID
cartIds:this.ids,//结算的购物车ID,多个以逗号分割,ALL表示全选
payway:way,// 支付方式:1-微信,2-支付宝
remark:JSON.stringify(this.getRemark()),//备注信息'[{"sid":"店铺ID","rmk":"备注内容"},{"sid":"店铺ID","rmk":"备注内容"}]'
}
console.log("params",params);
const resp = await settle(params);
// 提交订单成功,就唤起支付
if(resp && resp.bizcode === 100){
const item = resp.data;
if(params.payway === PAYMENT_WAY.WECHAT){// APP微信支付
if(item.wechat && Object.keys(item.wechat).length !==0){
this.appWxpay(item.wechat);
}else{
this.$refs.uToastRef.show({
type: 'error',
message: "订单支付失败",
});
}
}else if(params.payway === PAYMENT_WAY.ALIPAY){// 支付宝支付
if(item.alipay && Object.keys(item.alipay).length !==0){
this.zfbPay(item.alipay);
}else{
this.$refs.uToastRef.show({
type: 'error',
message: "订单支付失败",
});
}
}
}
},
// app 微信支付
appWxpay(item){
const newThis = this;
const orderInfo = {
"appid": item.appId, // 微信开放平台 - 应用 - AppId,注意和微信小程序、公众号 AppId 可能不一致
"noncestr": item.nonceStr, // 随机字符串
"package": "Sign=WXPay", // 固定值
"partnerid": item.partnerId, // 微信支付商户号
"prepayid": item.prepayId, // 统一下单订单号
"timestamp": item.timeStamp, // 时间戳(单位:秒)
"sign": item.sign // 签名,这里用的 MD5/RSA 签名
};
uni.requestPayment({
provider:"wxpay",
orderInfo: orderInfo,
success: function(res) {
console.log('success:' + res);
newThis.payFeedbackFun(item.orderId,res.orderNum,1);
newThis.jumpWayOk();
},
fail: function(err) {
console.log('fail:',err);
this.$refs.uToastRef.show({
type: 'error',
message: "支付失败",
});
}
});
},
// 支付宝支付
zfbPay(item){
const that = this;
uni.requestPayment({
provider: 'alipay',
orderInfo: item.orderStr,
success(res) {
console.log("res",res);
that.payFeedbackFun(item.orderId,item.orderNum,1);
that.jumpWayOk();
},
//调用失败的回调
fail(err) {
console.log('fail:',err);
this.$refs.uToastRef.show({
type: 'error',
message: "支付失败",
});
}
})
},
// 跳转到支付成功页面
jumpWayOk(){
uni.navigateTo({
url:"/pages/order_submit_ok/order_submit_ok",
})
},
// 支付结果回调
async payFeedbackFun(orderId,orderNum,status){
const params = {
orderId,
orderNum,
status,
}
console.log("params",params);
const response = await feedback(params);
console.log("反馈结果",response);
},
// 地址选中
getAddressValueFunc(item){
const addressObj = item;
addressObj.addressStr = assembleAddress(addressObj).names;
this.selectAddress = addressObj;
},
// 地址选中OK
addressOk(){
const type = this.addressType;
const addressIndex = this.addressIndex;
const shopsIndex = this.shopsIndex;
if(type === 'data'){
this.orderInfo.address = this.selectAddress;
}else if(type === 'addrTimes'){
this.orderInfo.shops[shopsIndex].addrTimes[addressIndex].address = this.selectAddress;
}
this.addressShow = this.false;
},
// 地址类型
checkAddressShow(status,type,addIndex,index){
this.addressShow = status;
this.addressType = type;
this.addressIndex = addIndex;
this.shopsIndex = index;
}
}
}
</script>
<style lang="scss" scoped>
.order_submit_warp{
background-color: $app-bj;
height: calc(100vh - 200rpx);
padding: 20rpx;
overflow-y: auto;
}
.order_submit_header_warp{
background: #FFFFFF;
border-radius: 24rpx;
padding: 30rpx;
.header_areaAddress_warp{
display: flex;
font-weight: 500;
font-size: 26rpx;
color: #222222;
.tab-comm{
color: #FFFFFF;
border-radius: 8rpx;
width: 58rpx;
font-size: 24rpx;
font-weight: 500;
margin-right: 10rpx;
display: flex;
align-items: center;
justify-content: center;
}
.areaAddress_default{
background: #FD2A53;
}
.areaAddress_tab{
background: #4D88FE;
}
}
.header_detailedAddress_warp{
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
font-size: 32rpx;
color: #222222;
margin-top: 10rpx;
}
.header_name_warp{
font-weight: 500;
font-size: 26rpx;
color: #222222;
margin-top: 10rpx;
}
}
.no_address{
background: #FFFFFF;
border-radius: 24rpx;
padding: 30rpx;
.no_address_title{
display: flex;
align-items: center;
font-weight: bold;
font-size: 32rpx;
color: #222222;
}
.no_address_msg{
font-weight: 500;
font-size: 26rpx;
color: #808080;
margin-top: 10rpx;
}
}
.order_store_warp{
margin-top: 30rpx;
background: #FFFFFF;
border-radius: 24rpx;
padding: 30rpx;
}
.order_product_warp{
.order_product_header{
display: flex;
}
.order_product_title{
font-weight: bold;
font-size: 28rpx;
color: #1A1A1A;
margin-left: 10rpx;
}
.shops_address_warp{
display: flex;
justify-content: space-between;
align-items: center;
padding: 20rpx;
background-color: #F5F5F5;
border-radius: 10rpx;
margin: 10rpx;
font-size: 26rpx;
.shops_address_warp_title{
color: #222222;
}
}
.order_item_content{
display: flex;
.content_info_right{
margin-left: 20rpx;
display: grid;
}
.content_info_title {
width: 266px;
}
.content_info_tag{
font-size: 20rpx;
}
.content_info_right_total{
display: flex;
justify-content: space-between;
padding: 0 20rpx 0 0;
}
.content_right_total{
font-weight: 500;
font-size: 22rpx;
color: $app-bt-bj;
}
}
.content_info_right_remark{
display: flex;
justify-content: space-between;
margin-top: 20rpx;
align-items: center;
.title{
font-weight: 500;
font-size: 26rpx;
color: #222222;
}
::v-deep{
input{
text-align: right;
}
}
}
}
.order_freight_warp{
.order_freight_item{
display: flex;
justify-content: space-between;
font-weight: 500;
font-size: 26rpx;
color: #222222;
line-height: 60rpx;
.value_{
color: $app-bt-bj;
}
.coupon_{
margin-left: 20rpx;
height: 32rpx;
border-radius: 5rpx;
border: 1px solid $app-bt-bj;
font-size: 20rpx;
color: $app-bt-bj;
padding: 0rpx 6rpx;
}
}
}
.order_way_warp{
display: flex;
justify-content: space-between;
align-items: center;
background: #FFFFFF;
border-radius: 24rpx;
margin-top: 30rpx;
padding: 30rpx;
font-weight: 500;
font-size: 26rpx;
color: #222222;
.order_way_right{
display: flex;
}
}
.order_pay_but{
position: fixed;
bottom: 0;
height: 144rpx;
background: #FFFFFF;
display: flex;
justify-content: space-between;
width: calc(100% - 34rpx);
padding-top: 20rpx;
._but{
padding: 20rpx 72rpx;
text-align: center;
background: $app-bt-bj;
border-radius: 16rpx 16rpx 16rpx 16rpx;
color: #FFF;
height: 46rpx;
}
.price_{
font-weight: bold;
font-size: 36rpx;
color: $app-bt-bj;
}
}
.way_popup_warp{
padding: 30rpx;
min-height: 800rpx;
width: calc(100% - 60rpx);
.way_popup_title{
text-align: center;
margin-bottom: 60rpx;
}
.way_item{
display: flex;
justify-content: space-between;
line-height: 82rpx;
.way_item_{
display: flex;
align-items: center;
}
.way_item_val{
font-weight: bold;
font-size: 30rpx;
color: #222222;
margin-left: 20rpx;
}
}
}
.popup_but{
position: fixed;
bottom: 64rpx;
background: $app-bt-bj;
border-radius: 16rpx;
color: #FFFFFF;
text-align: center;
padding: 20rpx 0;
width: calc(100% - 60rpx);
}
.address_popup_warp{
padding: 30rpx;
height: 1200rpx;
overflow-y: hidden;
.address_popup_title{
text-align: center;
margin-bottom: 20rpx;
}
.address_popup_content{
height: calc(100% - 180rpx);
overflow-y: auto;
}
}
</style>