Files
frontend-app/pages/order_submit/order_submit.vue
T
2025-05-23 18:03:45 +08:00

667 lines
19 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">
<Header :leftTitle="$t('order.submit.title')" leftPathType="switchTab" leftPath="/pages/shopping_cart/shopping_cart"/>
<!-- 收件人信息 -->
<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>
<view style="margin-top: 10rpx;">
<up-image src="/static/common/right.png" width="14" height="14" bgColor="#f1f6ff00"></up-image>
</view>
</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" shape="circle"></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" @click="jumpProductInfo(pItem)"></up-image>
<view class="content_info_right">
<view class="content_info_left_total" @click="jumpProductInfo(pItem)">
<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="wayShowFun(true)">
<view>支付方式</view>
<view class="order_way_right">
{{getValue(wayOption,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 v-for="item in wayOption" :key="item.id" style="margin-bottom: 10rpx;">
<view class="way_item" >
<view class="way_item_">
<view class="way_item_val">{{item.name}}<text v-if="item.balance">&nbsp;&nbsp;({{item.balance}})</text></view>
</view>
<view v-if="item.type === 'balance' && isShowBalance" class="go_balance_comm_warp" @click="goRechargeFun(item)">去充值</view>
<up-radio
v-else
:name="item.type"
activeColor="#03AD27"
>
</up-radio>
</view>
<view class="balance_comm_msg" v-if="item.type === 'balance' && isShowBalance">当前现金余额不足,如需支付请前往充值</view>
</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">
<view class="address_popup_content_add" @click="addAdress"> + 新增地址</view>
<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,WAY_LIST } from '@/utils/enumUtils.js';
import { getSettleList,settle,updateGoodsNum } from '@/api/cart.js';
import { getSupportPay } from '@/api/order.js';
import { feedback } from '@/api/payment.js';
import { assembleAddress } from '@/utils/index.js'
import Header from '@/components/header.vue';
import { appWxpayFun,zfbPayFun,jumpWayOk,jumpWayError } from '@/utils/payUtils.js'
export default {
computed: {
PRODUCT_DELIVERY_TIME() {
return PRODUCT_DELIVERY_TIME;
},
},
components: {
Address,
Header,
},
data() {
return {
ids:0,
orderInfo:{
// coupon:2,//优惠卷
paymentMethod:PAYMENT_WAY.ALIPAY,// 支付方式,暂时默认用支付宝
total:4000,// 需要支付的总金额
address:{},// 选中的地址
store:[],
},
wayShow:false,
addressShow:false,// 收件地址选择
addressType:'',// 收件地址数据类型
addressIndex:0,// 收件地址数据类型
shopsIndex:0,// 收件地址数据类型
selectAddress:{},// 收件地址选择
wayOption:[],
isShowBalance:false,
};
},
onLoad(option) {
const ids = option.ids;
if(ids && ids!=="null"){
this.ids = ids;
this.getOrder();
}
const addressShow = option.addressShow;
if(addressShow && addressShow !=="null"){
this.addressShow = addressShow;
}
// 支付弹框
const payOpen = option.payOpen;
if(payOpen && payOpen !=="null"){
this.getWayOption();
this.wayShow = payOpen;
}
},
mounted() {
},
methods: {
getValue,
assembleAddress,
// 增加收货地址
addAdress(){
const ids = this.ids;
// addressShow = true;
uni.navigateTo({
url:"/pages/mine_address_add/mine_address_add?ids="+ids,
})
},
wayShowFun(type){
if(type){
this.getWayOption();
}
this.wayShow=type;
},
async getWayOption(){
const result = await getSupportPay();
if(result && result.bizcode === 100){
const data = result.data || [];
const amount = this.orderInfo.amount;
let flag = data.some(item => ['wechat','alipay'].includes(item.type));
// 没有支付宝和微信支付
if(flag){
this.isShowBalance = false;
}else{
const balanceFlag = data.some(item => item.type === "balance" && item.balance < amount);
this.isShowBalance = balanceFlag;
}
this.wayOption = data;
}
},
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 需要修改的数据节点
*/
async quantityFun(type,index,addIndex,pIndex){
const data = this.orderInfo.shops[index].addrTimes[addIndex].goods[pIndex];
let currentQuantity = Number(data.num);// 当前数量
let currentTotalPrice = Number(data.totalPrice);// 当前金额
let currentAmount = Number(this.orderInfo.amount);// 总金额
if(type === "minus"){
if(currentQuantity === 1){
this.$refs.uToastRef.show({
type: 'error',
message: "不能再减拉,不能小于最低购买数量~",
});x3
}else{
currentQuantity = currentQuantity - 1;
currentAmount = currentAmount - data.unitPrice;
currentTotalPrice = currentTotalPrice - data.unitPrice;
}
}else if(type === "add"){
// 需要判断一下库存
currentQuantity = currentQuantity + 1;
currentAmount = currentAmount + data.unitPrice;
currentTotalPrice = currentTotalPrice + data.unitPrice;
}
const params={
id:data.id,
goodsNum:currentQuantity,
}
const result = await updateGoodsNum(params);
if(result && result.bizcode === 100){
this.orderInfo.shops[index].addrTimes[addIndex].goods[pIndex].num = currentQuantity;
this.orderInfo.shops[index].addrTimes[addIndex].goods[pIndex].totalPrice = currentTotalPrice.toFixed(2);
this.orderInfo.amount = currentAmount.toFixed(2);
}
},
// 获取备注
getRemark(){
const orderInfo = this.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);
}
return remarkArr;
},
/**
* 去支付
*/
async goPay(){
const orderInfo = this.orderInfo;
if(!orderInfo.address || Object.keys(orderInfo.address).length === 0){
this.$refs.uToastRef.show({
type: 'error',
message: "请选择收货地址",
});
return;
}
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(item.status === 1){
jumpWayOk();
return;
}
if(item.wechat && Object.keys(item.wechat).length !==0){
this.appWxpay(item.wechat,item.orderId,item.orderNum);
}else if(item.alipay && Object.keys(item.alipay).length !==0 && item.alipay){
this.zfbPay(item.alipay,item.orderId,item.orderNum);
}else{
this.$refs.uToastRef.show({
type: 'error',
message: "订单支付失败",
});
setTimeout(()=>{
jumpWayError()
},2000)
}
}else{
this.getOrder();
}
},
// app 微信支付
async appWxpay(alipay,orderId,orderNum){
try {
const result = await appWxpayFun(alipay,orderId,orderNum);
console.log('支付成功', result);
// 处理支付成功后的逻辑,如更新订单状态等
} catch (error) {
console.error('支付失败', error);
// 处理支付失败后的逻辑,如提示用户等
}
},
// 支付宝支付
async zfbPay(alipay,orderId,orderNum){
try {
const result = await zfbPayFun(alipay,orderId,orderNum);
console.log('支付成功', result);
// 处理支付成功后的逻辑,如更新订单状态等
} catch (error) {
console.error('支付失败', error);
// 处理支付失败后的逻辑,如提示用户等
}
},
// 地址选中
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;
},
jumpProductInfo(item){
uni.navigateTo({
url:"/pages/productInfo/productInfo?id="+item.goodsId,
})
},
/**
* 去充值
*/
goRechargeFun (item){
uni.navigateTo({
url:"/pages/mine_purse_recharge/mine_purse_recharge?category=balance&amount="+item.balance+"&back=submit&id="+this.ids,
})
}
}
}
</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;
margin-top: 20rpx;
.content_info_right{
margin-left: 20rpx;
display: grid;
width: calc(100% - 160rpx);
}
.content_info_left_total{
}
.content_info_title {
width: 460rpx;
}
.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_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;
}
}
</style>