修复bug

This commit is contained in:
2026-03-09 09:05:21 +08:00
parent 9f2d2f8764
commit 4da4d165cb
17 changed files with 467 additions and 181 deletions
+324 -108
View File
@@ -58,7 +58,8 @@ function confirmPhone(data: { phone: string; areaCode: string }) {
}
// 配送时间 1 即刻配送 2 预约配送
const deliveryTimeType = ref(1);
// 当前业务仅支持预约配送,默认值设置为 2
const deliveryTimeType = ref(2);
// 配送时间配置
const deliveryMinutes = ref(0); // 预计送达时间(分钟)
// 自取时间配置
@@ -92,21 +93,22 @@ const showDeliveryTime = computed(() => {
}
return "";
});
// 切换配送时间点击事件
// 切换配送时间点击事件(目前仅支持预约配送)
function toggleDeliveryTimeType(type: number) {
if (type === 2) {
if (userSelectedDeliveryTimeDate.value) {
deliveryTimeType.value = type;
}
// 跳转到时间选择页面
console.log(storeDetail.value.merch);
uni.navigateTo({
url: "/pages/address/reservation-time?storeBusinessHours=" + storeDetail.value.businessHours,
});
} else {
deliveryTimeType.value = type;
}
// 统一设置为预约配送
deliveryTimeType.value = 2;
// 跳转到时间选择页面
const businessHours = (storeDetail.value as any)?.businessHours;
const url = businessHours
? `/pages/address/reservation-time?storeBusinessHours=${encodeURIComponent(
businessHours
)}`
: "/pages/address/reservation-time";
uni.navigateTo({
url,
});
}
const diyTime = ref({})
@@ -118,9 +120,13 @@ useEventEmit(EventEnum.CHOOSE_APPOINTMENT_TIME, (data) => {
// 配送还是自取
if(deliveryMethod.value === 0) {
userSelectedDeliveryTimeDate.value = dayjs(data.date).format('MM-DD') + ' ' + data.timeSlot;
userSelectedDeliveryTimeDate.value =
dayjs(data.date).format('MM-DD') +
(data.timeSlot ? ' ' + data.timeSlot : '');
} else {
userSelectedSelfPickupTimeDate.value = dayjs(data.date).format('MM-DD') + ' ' + data.timeSlot;
userSelectedSelfPickupTimeDate.value =
dayjs(data.date).format('MM-DD') +
(data.timeSlot ? ' ' + data.timeSlot : '');
}
}
})
@@ -161,8 +167,8 @@ function handleClickSegmented(index: number) {
if(index !== deliveryMethod.value) {
deliveryMethod.value = index
// 重置配送类型
deliveryTimeType.value = 1
// 重置配送类型为预约配送
deliveryTimeType.value = 2
appMerchantOrderCalculatePriceCart()
}
}
@@ -170,33 +176,70 @@ function handleClickSegmented(index: number) {
// 折叠面板
const collapseValue = ref([""]);
// 当前选中的小费
const selectedTipIndex = ref(5);
// 单个订单的小费
const selectedTipIndex = ref(0);
const diyTipValue = ref('')
// 批量订单:每个店铺的小费索引映射 merchantId -> tipIndex
const merchantTipIndexMap = ref<Record<string, number>>({})
// 批量订单:每个店铺的自定义小费值映射 merchantId -> diyTipValue
const merchantDiyTipValueMap = ref<Record<string, string>>({})
const tipOptions = ref([
{
label: "5%",
label: "$3",
value: 3,
},
{
label: "$5",
value: 5,
},
{
label: "10%",
label: "$10",
value: 10,
},
{
label: "15%",
value: 15,
},
]);
// 单个订单的小费选择
function selectedTipChange(item: any) {
if(item.value === selectedTipIndex.value) return
diyTipValue.value = ''
selectedTipIndex.value = item.value
appMerchantOrderCalculatePriceCart()
}
// 批量订单:选择某个店铺的小费
function selectedTipChangeForMerchant(merchantId: string, item: any) {
if(item.value === merchantTipIndexMap.value[merchantId]) return
merchantDiyTipValueMap.value[merchantId] = ''
merchantTipIndexMap.value[merchantId] = item.value
appMerchantOrderCalculatePriceCart()
}
// 单个订单的自定义小费确认(金额,单位:美元)
function handleConfirmTip() {
if(diyTipValue.value) {
appMerchantOrderCalculatePriceCart()
// 如果未填写其他小费金额,失去焦点时默认填充为 0
const val = String(diyTipValue.value || '').trim()
if (!val) {
diyTipValue.value = '0'
}
// 使用自定义小费时,选中"其他"这一项
if (selectedTipIndex.value !== 0) {
selectedTipIndex.value = 0
}
appMerchantOrderCalculatePriceCart()
}
// 批量订单:确认某个店铺的自定义小费(金额,单位:美元)
function handleConfirmTipForMerchant(merchantId: string) {
const val = String(merchantDiyTipValueMap.value[merchantId] || '').trim()
if (!val) {
merchantDiyTipValueMap.value[merchantId] = '0'
}
// 使用自定义小费时,选中"其他"这一项
if (merchantTipIndexMap.value[merchantId] !== 0) {
merchantTipIndexMap.value[merchantId] = 0
}
appMerchantOrderCalculatePriceCart()
}
// 是否选择了配送周卡
@@ -486,13 +529,44 @@ function appMerchantOrderCalculatePriceCart() {
// 批量模式使用批量计算价格接口
if(orderType.value == 'batch') {
// 构建 merchantCouponMap: { merchantId: couponId }
const couponMap: Record<string, number> = {}
Object.keys(merchantCouponMap.value).forEach(merchantId => {
if(merchantCouponMap.value[merchantId]?.id) {
couponMap[merchantId] = merchantCouponMap.value[merchantId].id
}
})
// 构建 merchantTipMap: { merchantId: tipAmount } (小费金额,单位:美元)
const tipMap: Record<string, number> = {}
cartDataList.value.forEach((merchant: any) => {
const merchantId = String(merchant.id)
if(deliveryMethod.value === 1) {
// 自取订单不需要小费
tipMap[merchantId] = 0
} else {
// 配送订单需要小费
const diyTip = merchantDiyTipValueMap.value[merchantId]
const tipIndex = merchantTipIndexMap.value[merchantId] || 0
if(diyTip) {
// 自定义小费金额(美元)
tipMap[merchantId] = Number(diyTip) || 0
} else if(tipIndex > 0) {
// 选择固定金额选项
tipMap[merchantId] = tipIndex
} else {
tipMap[merchantId] = 0
}
}
})
appMerchantOrderCalculatePriceCartBatchPost({
body: {
addressId: targetAddressId,
cartIds: cartIds,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2,
couponId: couponInfo.value ? couponInfo.value.id : '',
tipDiscount: deliveryMethod.value === 1 ? 0 : (diyTipValue.value ? Number(diyTipValue.value) / 100 : (selectedTipIndex.value || 0) / 100), // 小费比例,自取订单不需要小费
merchantCouponMap: couponMap,
merchantTipMap: tipMap, // 小费金额(美元)
phone: formData.value.phone,
areaCode: contact.value.areaCode,
}
@@ -502,13 +576,24 @@ function appMerchantOrderCalculatePriceCart() {
})
} else {
// 普通模式使用单店铺计算价格接口
// 计算小费金额(美元)
let tipAmount = 0
if(deliveryMethod.value === 0) {
// 配送订单需要小费
if(diyTipValue.value) {
tipAmount = Number(diyTipValue.value) || 0
} else if(selectedTipIndex.value > 0) {
tipAmount = selectedTipIndex.value
}
}
appMerchantOrderCalculatePriceCartPost({
body: {
addressId: targetAddressId,
cartIds: cartIds,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2,
couponId: couponInfo.value ? couponInfo.value.id : '',
tipDiscount: deliveryMethod.value === 1 ? 0 : (diyTipValue.value ? Number(diyTipValue.value) / 100 : (selectedTipIndex.value || 0) / 100), // 小费比例,自取订单不需要小费
tipDiscount: tipAmount, // 小费金额(美元),自取订单不需要小费
// weeklyDeliveryFee: isWeeklyDelivery.value ? 1 : 2, // 是否支付周配送费(1-是 2-否)
phone: formData.value.phone,
areaCode: contact.value.areaCode,
@@ -633,23 +718,63 @@ function handleGoSettle() {
})
return
}
// 仅支持预约配送:必须先选择预约时间
if (deliveryTimeType.value === 2 && (!diyTime.value.startTime || !diyTime.value.endTime)) {
uni.showToast({
title: t('pages-store.checkout.chooseTime'),
icon: 'none'
})
return
}
// 批量下单
if(orderType.value == 'batch') {
if(resOrderIds.value.length === 0) {
// 构建 merchantCouponMap: { merchantId: couponId }
const couponMap: Record<string, number> = {}
Object.keys(merchantCouponMap.value).forEach(merchantId => {
if(merchantCouponMap.value[merchantId]?.id) {
couponMap[merchantId] = merchantCouponMap.value[merchantId].id
}
})
// 构建 merchantTipMap: { merchantId: tipAmount } (小费金额,单位:美元)
const tipMap: Record<string, number> = {}
cartDataList.value.forEach((merchant: any) => {
const merchantId = String(merchant.id)
if(deliveryMethod.value === 1) {
// 自取订单不需要小费
tipMap[merchantId] = 0
} else {
// 配送订单需要小费
const diyTip = merchantDiyTipValueMap.value[merchantId]
const tipIndex = merchantTipIndexMap.value[merchantId] || 0
if(diyTip) {
// 自定义小费金额(美元)
tipMap[merchantId] = Number(diyTip) || 0
} else if(tipIndex > 0) {
// 选择固定金额选项
tipMap[merchantId] = tipIndex
} else {
tipMap[merchantId] = 0
}
}
})
let data = {
addressId: targetAddressId,
phone: formData.value.phone,
areaCode: contact.value.areaCode,
cartIds: batchCartIds.value,
couponId: couponInfo.value ? couponInfo.value.id : '',
merchantCouponMap: couponMap,
merchantTipMap: tipMap,
deliveryMethod: visitMethod.value.label, // 派送方式(如放门口或者交到顾客手中)
deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付
orderRemark: formData.value.orderRemark,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
tipDiscount: deliveryMethod.value === 1 ? 0 : (diyTipValue.value ? Number(diyTipValue.value) / 100 : (selectedTipIndex.value || 0) / 100), // 小费比例,自取订单不需要小费
needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否
}
@@ -686,6 +811,17 @@ function handleGoSettle() {
} else {
// 普通下单
if(!resOrderId.value) {
// 计算小费金额(美元)
let tipAmount = 0
if(deliveryMethod.value === 0) {
// 配送订单需要小费
if(diyTipValue.value) {
tipAmount = Number(diyTipValue.value) || 0
} else if(selectedTipIndex.value > 0) {
tipAmount = selectedTipIndex.value
}
}
let data = {
addressId: targetAddressId,
phone: formData.value.phone,
@@ -698,7 +834,7 @@ function handleGoSettle() {
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
tipDiscount: deliveryMethod.value === 1 ? 0 : (diyTipValue.value ? Number(diyTipValue.value) / 100 : (selectedTipIndex.value || 0) / 100), // 小费比例,自取订单不需要小费
tipDiscount: tipAmount, // 小费金额(美元),自取订单不需要小费
// weeklyDeliveryFee: isWeeklyDelivery.value ? 1 : 2, // 是否支付周配送费(1-是 2-否)
needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否
}
@@ -899,16 +1035,31 @@ export interface CreateOrderCartBo {
[property: string]: any;
}
// 单个订单的优惠券信息
const couponInfo = ref(null)
function navigateToCoupon() {
// 批量订单:每个店铺的优惠券映射 merchantId -> couponInfo
const merchantCouponMap = ref<Record<string, any>>({})
// 批量订单:每个店铺的小费映射 merchantId -> tipAmount (小费金额,单位:美元)
const merchantTipMap = ref<Record<string, number>>({})
// 批量订单:每个店铺的小费比例映射 merchantId -> tipPercent (小费比例,0-100)
const merchantTipPercentMap = ref<Record<string, number>>({})
function navigateToCoupon(merchantId?: string) {
const targetMerchantId = merchantId || storeId.value
uni.navigateTo({
url: '/pages-user/pages/coupon/list?id=' + storeId.value,
url: '/pages-user/pages/coupon/list?id=' + targetMerchantId,
events: {
// 为指定事件添加一个监听器,获取被打开页面传送到当前页面的数据
selectedCoupon: function(data) {
console.log(data)
if(data) {
couponInfo.value = data
if(orderType.value === 'batch' && merchantId) {
// 批量模式:存储到对应店铺的优惠券映射
merchantCouponMap.value[merchantId] = data
} else {
// 单个订单模式
couponInfo.value = data
}
// 重新计算价格
appMerchantOrderCalculatePriceCart()
}
@@ -916,8 +1067,14 @@ function navigateToCoupon() {
},
})
}
function handleClose() {
couponInfo.value = null
function handleClose(merchantId?: string) {
if(orderType.value === 'batch' && merchantId) {
// 批量模式:清除对应店铺的优惠券
delete merchantCouponMap.value[merchantId]
} else {
// 单个订单模式
couponInfo.value = null
}
// 重新计算价格
appMerchantOrderCalculatePriceCart()
}
@@ -1111,25 +1268,13 @@ function handleClose() {
</template>
</view>
</view>
<!--配送-->
<template v-if="storeIsDeliveryService && deliveryMethod === 0">
<view class="flex-center-sb pb-36rpx px-30rpx gap-22rpx">
<!--配送当前业务仅支持预约配送batch 模式也要展示预约入口-->
<template v-if="(storeIsDeliveryService || orderType === 'batch') && deliveryMethod === 0">
<view class="pb-36rpx px-30rpx">
<view
@click="toggleDeliveryTimeType(1)"
:class="[deliveryTimeType === 1 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
>
<view class="text-center">
<view class="text-#333 mb-12rpx">
{{ t("pages-store.checkout.immediateDelivery") }}
</view>
<view class="text-#7D7D7D">{{ storeDetail?.deliveryTime }}{{ t('common.minutes') }}</view>
</view>
</view>
<view
@click="toggleDeliveryTimeType(2)"
:class="[deliveryTimeType === 2 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
@click="toggleDeliveryTimeType(2)"
:class="[deliveryTimeType === 2 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
>
<view class="text-center">
<view class="text-#333 mb-12rpx">
@@ -1147,25 +1292,13 @@ function handleClose() {
</view>
</view>
</template>
<!--自取-->
<template v-if="storeIsSelfPickup && deliveryMethod === 1">
<view class="flex-center-sb pb-36rpx px-30rpx gap-22rpx">
<!--自取当前业务仅支持预约自取batch 模式同样展示预约入口 -->
<template v-if="(storeIsSelfPickup || orderType === 'batch') && deliveryMethod === 1">
<view class="pb-36rpx px-30rpx">
<view
@click="toggleDeliveryTimeType(1)"
:class="[deliveryTimeType === 1 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
>
<view class="text-center">
<view class="text-#333 mb-12rpx">
{{ t('pages-store.checkout.immediatePickup') }}
</view>
<view class="text-#7D7D7D">{{ storeDetail?.pickupTime }}{{ t('common.minutes') }}</view>
</view>
</view>
<view
@click="toggleDeliveryTimeType(2)"
:class="[deliveryTimeType === 2 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
@click="toggleDeliveryTimeType(2)"
:class="[deliveryTimeType === 2 ? 'border-#333' : 'border-#D8D8D8']"
class="w-full h-152rpx text-28rpx lh-28rpx border-solid border-1px rounded-20rpx center"
>
<view class="text-center">
<view class="text-#333 mb-12rpx">
@@ -1331,6 +1464,87 @@ function handleClose() {
</view>
</view>
</view>
<!-- 批量模式每个店铺的优惠券和小费选择 -->
<view v-if="merchant.id" class="px-20rpx pb-20rpx border-top border-[#F2F2F2] mt-20rpx">
<!-- 优惠券 -->
<view @click="navigateToCoupon(String(merchant.id))" class="flex-center-sb py-24rpx gap-20rpx">
<view class="flex-center-sb flex-1">
<view class="flex items-center">
<image
src="@img/chef/105.png"
mode="aspectFill"
class="w-36rpx h-36rpx relative z-1"
/>
<view class="ml-20rpx text-26rpx lh-26rpx font-500 text-#333">
{{ merchantCouponMap[String(merchant.id)] ? merchantCouponMap[String(merchant.id)].snapshotNameZh : t('pages-store.checkout.addCoupon') }}
</view>
</view>
<view v-if="merchantCouponMap[String(merchant.id)]" @click.stop="handleClose(String(merchant.id))" class="i-carbon:close-filled text-32rpx text-#7D7D7D"></view>
</view>
<image
src="@img/chef/142.png"
mode="aspectFill"
class="w-24rpx h-24rpx shrink-0"
/>
</view>
<!-- 小费仅配送时显示 -->
<view v-if="deliveryMethod === 0" class="border-top border-[#F2F2F2] pt-24rpx">
<view class="flex items-center mb-20rpx">
<image
src="@img/chef/1335.png"
mode="aspectFill"
class="w-36rpx h-36rpx relative z-1"
/>
<view class="ml-20rpx text-26rpx lh-26rpx font-500 text-#333">
{{ t('pages-store.checkout.chooseTips') }}
</view>
</view>
<view class="flex-center-sb gap-16rpx">
<view
v-for="(item, index) in tipOptions"
:key="index"
@click="selectedTipChangeForMerchant(String(merchant.id), item)"
:class="[
merchantTipIndexMap[String(merchant.id)] === item.value
? 'border-#333'
: 'border-#D8D8D8',
]"
class="flex-1 h-64rpx text-24rpx lh-64rpx text-#333 rounded-16rpx border-solid border-1px center"
>
{{ item.label }}
</view>
<view
@click="selectedTipChangeForMerchant(String(merchant.id), { value: 0 })"
:class="[
merchantTipIndexMap[String(merchant.id)] === 0
? 'border-#333'
: 'border-#D8D8D8',
]"
class="flex-1 h-64rpx text-24rpx lh-64rpx text-#333 rounded-16rpx border-solid border-1px center"
>
<view class="px-10rpx center">
<wd-input
no-border
use-prefix-slot
@blur="handleConfirmTipForMerchant(String(merchant.id))"
custom-class="!center !text-24rpx !bg-transparent flex-1 !text-center"
placeholderStyle="font-size: 24rpx;color: #333; text-align: center;"
:placeholder="t('pages-store.checkout.other')"
v-model="merchantDiyTipValueMap[String(merchant.id)]"
@confirm="handleConfirmTipForMerchant(String(merchant.id))"
>
<template #suffix>
<text v-if="merchantDiyTipValueMap[String(merchant.id)] && merchantDiyTipValueMap[String(merchant.id)].length > 0">$</text>
</template>
</wd-input>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</view>
@@ -1347,31 +1561,32 @@ function handleClose() {
</view>
<view class="pt-36rpx pb-36rpx" >
<!-- 优惠券 -->
<view @click="navigateToCoupon" class="flex-center-sb border-bottom py-36rpx px-30rpx gap-20rpx">
<view class="flex-center-sb flex-1">
<view class="flex items-center">
<image
src="@img/chef/105.png"
mode="aspectFill"
class="w-44rpx h-44rpx relative z-1"
/>
<view class="ml-28rpx text-32rpx lh-32rpx font-500 text-#333">
{{ couponInfo? couponInfo.snapshotNameZh : t('pages-store.checkout.addCoupon') }}
<!-- 单个订单模式优惠券 -->
<template v-if="orderType === 'normal'">
<view @click="navigateToCoupon()" class="flex-center-sb border-bottom py-36rpx px-30rpx gap-20rpx">
<view class="flex-center-sb flex-1">
<view class="flex items-center">
<image
src="@img/chef/105.png"
mode="aspectFill"
class="w-44rpx h-44rpx relative z-1"
/>
<view class="ml-28rpx text-32rpx lh-32rpx font-500 text-#333">
{{ couponInfo ? couponInfo.snapshotNameZh : t('pages-store.checkout.addCoupon') }}
</view>
</view>
<view v-if="couponInfo" @click.stop="handleClose()" class="i-carbon:close-filled text-36rpx text-#7D7D7D"></view>
</view>
<view v-if="couponInfo" @click.stop="handleClose" class="i-carbon:close-filled"></view>
<image
src="@img/chef/142.png"
mode="aspectFill"
class="w-32rpx h-32rpx shrink-0"
/>
</view>
<image
src="@img/chef/142.png"
mode="aspectFill"
class="w-32rpx h-32rpx shrink-0"
/>
</view>
</template>
<template v-if="deliveryMethod === 0">
<!-- 小费 -->
<!-- 单个订单模式小费仅配送时显示 -->
<template v-if="orderType === 'normal' && deliveryMethod === 0">
<view class="border-bottom py-36rpx px-30rpx">
<view class="flex items-center mb-28rpx">
<image
@@ -1385,19 +1600,19 @@ function handleClose() {
</view>
<view class="flex-center-sb gap-22rpx">
<template v-for="(item, index) in tipOptions">
<view
@click="selectedTipChange(item)"
:class="[
<view
v-for="(item, index) in tipOptions"
:key="index"
@click="selectedTipChange(item)"
:class="[
selectedTipIndex === item.value
? 'border-#333'
: 'border-#D8D8D8',
]"
class="w-full h-72rpx text-28rpx lh-28rpx text-#333 rounded-20rpx border-solid border-1px center"
>
{{ item.label }}
</view>
</template>
class="w-full h-72rpx text-28rpx lh-28rpx text-#333 rounded-20rpx border-solid border-1px center"
>
{{ item.label }}
</view>
<view
@click="selectedTipChange({ value: 0 })"
:class="[
@@ -1419,13 +1634,14 @@ function handleClose() {
@confirm="handleConfirmTip"
>
<template #suffix>
<text v-if="diyTipValue.length > 0">%</text>
<text v-if="diyTipValue.length > 0">$</text>
</template>
</wd-input>
</view>
</view>
</view>
</view>
</template>
<!-- 配送费周卡 -->
<!-- <view v-if="isShowWeeklyDelivery" class="border-bottom px-30rpx py-36rpx">-->
@@ -1471,7 +1687,7 @@ function handleClose() {
<!-- {{ t('pages-store.checkout.tipsDesc') }}-->
<!-- </view>-->
<!-- </view>-->
</template>
<!-- </template> -->
<!-- 费用明细 -->
<view class="border-bottom px-30rpx py-32rpx">