修改样式,修复bug

This commit is contained in:
2026-06-11 10:44:31 +08:00
parent 3421b7006f
commit 8ed9bf2e1a
6 changed files with 198 additions and 64 deletions
+1
View File
@@ -222,6 +222,7 @@
"browse": { "browse": {
"brandTag": "CHEFLINK Selected", "brandTag": "CHEFLINK Selected",
"moreRecipes": "More Recipes", "moreRecipes": "More Recipes",
"nearbyEmpty": "No nearby data",
"titleCuisine": "Nearby Cuisine", "titleCuisine": "Nearby Cuisine",
"titleRecipes": "Selected Recipes" "titleRecipes": "Selected Recipes"
}, },
+2 -1
View File
@@ -222,7 +222,8 @@
"browse": { "browse": {
"brandTag": "CHEFLINK 严选", "brandTag": "CHEFLINK 严选",
"moreRecipes": "更多食谱", "moreRecipes": "更多食谱",
"titleCuisine": "附近美食", "nearbyEmpty": "附近暂无美食",
"titleCuisine": "附近美食",
"titleRecipes": "选择食谱" "titleRecipes": "选择食谱"
}, },
"home": { "home": {
+2 -2
View File
@@ -2,8 +2,8 @@
"name" : "CHEFLINK delivery", "name" : "CHEFLINK delivery",
"appid" : "__UNI__06509BE", "appid" : "__UNI__06509BE",
"description" : "", "description" : "",
"versionName" : "3.2.3", "versionName" : "3.2.4",
"versionCode" : 323, "versionCode" : 324,
"transformPx" : false, "transformPx" : false,
/* 5+App */ /* 5+App */
"app-plus" : { "app-plus" : {
+43 -19
View File
@@ -971,7 +971,7 @@ function handleGoSettle() {
} }
}) })
let data = { const data: Record<string, any> = {
addressId: targetAddressId, addressId: targetAddressId,
phone: formData.value.phone, phone: formData.value.phone,
areaCode: contact.value.areaCode, areaCode: contact.value.areaCode,
@@ -982,8 +982,6 @@ function handleGoSettle() {
deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付 deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付
orderRemark: formData.value.orderRemark, orderRemark: formData.value.orderRemark,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取) receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否 needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否
} }
@@ -992,24 +990,21 @@ function handleGoSettle() {
data.startScheduledTime = result.startTimestamp data.startScheduledTime = result.startTimestamp
data.endScheduledTime = result.endTimestamp data.endScheduledTime = result.endTimestamp
} else { } else {
const startMap: Record<string, number> = {} const scheduled = buildScheduledTimePayload(
const endMap: Record<string, number> = {} cartDataList.value as any[],
cartDataList.value.forEach((m: any) => { merchantAppointmentMap.value
const ap = merchantAppointmentMap.value[String(m.id)] )
if (ap?.startTime && ap?.endTime) { data.startScheduledTime = scheduled.startScheduledTime
startMap[String(m.id)] = ap.startTime data.endScheduledTime = scheduled.endScheduledTime
endMap[String(m.id)] = ap.endTime data.merchantStartScheduledTimeMap = scheduled.startMap
} data.merchantEndScheduledTimeMap = scheduled.endMap
})
data.merchantStartScheduledTimeMap = startMap
data.merchantEndScheduledTimeMap = endMap
} }
console.log('批量下单参数', data) console.log('批量下单参数', data)
appMerchantOrderCreateOrderCartBatchPost({ appMerchantOrderCreateOrderCartBatchPost({
body: data body: data
}).then(res=> { }).then(res=> {
console.log('批量下单成功', res) console.log('批量下单成功', res)
resOrderIds.value = res.data.orderIds || [] resOrderIds.value = res.data?.orderIds || res.data || []
// 如果是余额支付,弹出支付密码弹窗 // 如果是余额支付,弹出支付密码弹窗
if(payMethodOptions.value.payMethod === 2) { if(payMethodOptions.value.payMethod === 2) {
passwordInputRef.value?.showPasswordInput() passwordInputRef.value?.showPasswordInput()
@@ -1019,6 +1014,11 @@ function handleGoSettle() {
} else { } else {
appMerchantOrderPayOrderBatch() appMerchantOrderPayOrderBatch()
} }
}).catch((err: any) => {
uni.showToast({
title: err?.msg || err?.message || '下单失败',
icon: 'none',
})
}) })
} else { } else {
// 如果是余额支付,弹出支付密码弹窗 // 如果是余额支付,弹出支付密码弹窗
@@ -1045,7 +1045,7 @@ function handleGoSettle() {
} }
} }
let data = { const data: Record<string, any> = {
addressId: targetAddressId, addressId: targetAddressId,
phone: formData.value.phone, phone: formData.value.phone,
areaCode: contact.value.areaCode, areaCode: contact.value.areaCode,
@@ -1055,14 +1055,11 @@ function handleGoSettle() {
deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付 deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付
orderRemark: formData.value.orderRemark, orderRemark: formData.value.orderRemark,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取) receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
tipDiscount: tipAmount, // 小费金额(美元),自取订单不需要小费 tipDiscount: tipAmount, // 小费金额(美元),自取订单不需要小费
// weeklyDeliveryFee: isWeeklyDelivery.value ? 1 : 2, // 是否支付周配送费(1-是 2-否) // weeklyDeliveryFee: isWeeklyDelivery.value ? 1 : 2, // 是否支付周配送费(1-是 2-否)
needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否 needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否
} }
// 如果是预约派送
if (deliveryTimeType.value === 1) { if (deliveryTimeType.value === 1) {
const result = getTimeStamps(showDeliveryTime.value); const result = getTimeStamps(showDeliveryTime.value);
data.startScheduledTime = result.startTimestamp data.startScheduledTime = result.startTimestamp
@@ -1178,6 +1175,33 @@ function appMerchantOrderPayOrderBatch() {
}) })
} }
/** 从商户预约映射中提取创单所需的顶层预约时间(文档要求 deliveryType=2 必传) */
function buildScheduledTimePayload(
merchants: Array<{ id?: string | number }>,
appointmentMap: Record<string, MerchantAppointmentSlot>
) {
const startMap: Record<string, number> = {};
const endMap: Record<string, number> = {};
let startScheduledTime: number | undefined;
let endScheduledTime: number | undefined;
merchants.forEach((m) => {
const ap = appointmentMap[String(m.id)];
if (!ap?.startTime || !ap?.endTime) return;
const merchantId = String(m.id);
const start = Number(ap.startTime);
const end = Number(ap.endTime);
startMap[merchantId] = start;
endMap[merchantId] = end;
if (startScheduledTime === undefined) {
startScheduledTime = start;
endScheduledTime = end;
}
});
return { startScheduledTime, endScheduledTime, startMap, endMap };
}
function getTimeStamps(timeStr: string) { function getTimeStamps(timeStr: string) {
// 验证输入是否为空 // 验证输入是否为空
if (!timeStr || typeof timeStr !== 'string') { if (!timeStr || typeof timeStr !== 'string') {
+58 -6
View File
@@ -38,15 +38,28 @@ const storeShareTopStyle = computed(() => ({
top: `${configStore.statusBarHeight + uni.upx2px(16)}px`, top: `${configStore.statusBarHeight + uni.upx2px(16)}px`,
})) }))
const storeBannerSrc = computed(() => { const storeBannerImages = computed(() => {
const raw = storeDetail.value?.shopImages const raw = storeDetail.value?.shopImages
if (typeof raw === 'string' && raw.trim()) { if (typeof raw === 'string' && raw.trim()) {
return raw.split(',')[0].trim() const list = raw.split(',').map((item) => item.trim()).filter(Boolean)
if (list.length > 0) return list
} }
const logo = storeDetail.value?.logo const logo = storeDetail.value?.logo
return typeof logo === 'string' ? logo : '' return typeof logo === 'string' && logo.trim() ? [logo.trim()] : []
}) })
const storeBannerCurrent = ref(0)
function onStoreBannerChange(e: { detail?: { current?: number } }) {
storeBannerCurrent.value = e.detail?.current ?? 0
}
watch(
() => storeDetail.value?.id,
() => {
storeBannerCurrent.value = 0
},
)
const deliveryNoticeTexts = computed(() => { const deliveryNoticeTexts = computed(() => {
const texts: string[] = [] const texts: string[] = []
if (+storeDetail.value?.deliveryService === 1 && deliveryMethod.value === 0) { if (+storeDetail.value?.deliveryService === 1 && deliveryMethod.value === 0) {
@@ -672,13 +685,34 @@ function handleShare() {
> >
<view class="store-main__inner"> <view class="store-main__inner">
<view class="store-banner"> <view class="store-banner">
<swiper
v-if="storeBannerImages.length > 0"
class="store-banner__swiper"
:circular="storeBannerImages.length > 1"
:autoplay="storeBannerImages.length > 1"
:indicator-dots="storeBannerImages.length > 1"
indicator-color="rgba(255,255,255,0.45)"
indicator-active-color="#ffffff"
@change="onStoreBannerChange"
>
<swiper-item
v-for="(img, idx) in storeBannerImages"
:key="`${img}-${idx}`"
>
<image <image
v-if="storeBannerSrc" :src="img"
:src="storeBannerSrc"
class="store-banner__img" class="store-banner__img"
mode="aspectFill" mode="scaleToFill"
/> />
</swiper-item>
</swiper>
<view v-else class="store-banner__img store-banner__img--empty" /> <view v-else class="store-banner__img store-banner__img--empty" />
<view
v-if="storeBannerImages.length > 1"
class="store-banner__counter"
>
{{ storeBannerCurrent + 1 }}/{{ storeBannerImages.length }}
</view>
</view> </view>
<view <view
@@ -1034,6 +1068,11 @@ page {
background: #e8e8e8; background: #e8e8e8;
} }
.store-banner__swiper {
width: 100%;
height: 100%;
}
.store-banner__img { .store-banner__img {
width: 100%; width: 100%;
height: 100%; height: 100%;
@@ -1044,6 +1083,19 @@ page {
background: #e8e8e8; background: #e8e8e8;
} }
.store-banner__counter {
position: absolute;
right: 24rpx;
bottom: 20rpx;
z-index: 2;
padding: 6rpx 16rpx;
border-radius: 999rpx;
background: rgba(0, 0, 0, 0.45);
color: #fff;
font-size: 22rpx;
line-height: 28rpx;
}
.store-delivery-notice { .store-delivery-notice {
background: #fff7ed; background: #fff7ed;
border-bottom: 1rpx solid #ffe8cc; border-bottom: 1rpx solid #ffe8cc;
@@ -3,7 +3,7 @@ import Search from "../tabbar-home/components/search.vue";
import { useConfigStore, useUserStore } from "@/store"; import { useConfigStore, useUserStore } from "@/store";
import BrowseSkeleton from "./components/browse-skeleton.vue"; import BrowseSkeleton from "./components/browse-skeleton.vue";
import { import {
appMerchantDishNearbyListPost, appMerchantNearbyListPost,
appSearchSearchRecipePost, appSearchSearchRecipePost,
} from "@/service"; } from "@/service";
import {thumbnailImg} from "@/utils/utils"; import {thumbnailImg} from "@/utils/utils";
@@ -28,8 +28,7 @@ async function initData() {
loading.value = true; loading.value = true;
} }
getRecipeData() getRecipeData()
// 获取菜品数据 getNearbyStoreList()
appMerchantDishNearbyList()
} }
// 获取菜谱数据 // 获取菜谱数据
@@ -56,38 +55,44 @@ function navigateToRecipeList() {
navigateTo('/pages-user/pages/recipe/list') navigateTo('/pages-user/pages/recipe/list')
} }
// 获取附近的菜品 // 获取附近店铺
const dishData = ref<any[]>([]); const nearbyStoreList = ref<any[]>([]);
function appMerchantDishNearbyList() { const nearbyStoreLoaded = ref(false);
appMerchantDishNearbyListPost({ function getNearbyStoreList() {
params: { nearbyStoreLoaded.value = false;
pageNum: 1, appMerchantNearbyListPost({
pageSize: 10,
},
body: { body: {
lat: String(userStore.userLocation.latitude ?? ''), lat: userStore.userLocation.latitude,
lng: String(userStore.userLocation.longitude ?? ''), lng: userStore.userLocation.longitude,
} },
}).then(res=> {
console.log('菜品数据', res)
dishData.value = res.rows;
}) })
} .then((res) => {
function handleClickDish(item: any) { console.log("附近店铺", res);
navigateTo(`/pages-store/pages/store/index?id=${item.merchantId}`) nearbyStoreList.value = res.data || [];
})
.catch(() => {
nearbyStoreList.value = [];
})
.finally(() => {
nearbyStoreLoaded.value = true;
});
} }
function getMerchantName(item: any) { function handleClickStore(item: any) {
return item?.merchantVo?.merchantName || item?.merchantName||item?.dishName || '--' navigateTo(`/pages-store/pages/store/index?id=${item.id}`);
} }
function getMerchantLogo(item: any) { function getStoreName(item: any) {
return item?.merchantVo?.logo || item?.logo || item?.dishImage?.split?.(',')?.[0] || item?.dishImage || '' return item?.merchantName || "--";
} }
function getMerchantRate(item: any) { function getStoreLogo(item: any) {
const rating = Number(item?.merchantVo?.rating ?? item?.rating ?? 0) return item?.logo || "";
return Number.isFinite(rating) && rating > 0 ? rating.toFixed(1) : '5.0' }
function getStoreRate(item: any) {
const rating = Number(item?.rating ?? 0);
return Number.isFinite(rating) && rating > 0 ? rating.toFixed(1) : "5.0";
} }
function getPreviewRecipeList() { function getPreviewRecipeList() {
@@ -161,17 +166,28 @@ defineExpose({
</view> </view>
<view class="section-title mt-54rpx">{{ t("pages.browse.titleCuisine") }}</view> <view class="section-title mt-54rpx">{{ t("pages.browse.titleCuisine") }}</view>
<scroll-view scroll-x class="store-scroll mt-28rpx pb-40rpx" :show-scrollbar="false" :enable-flex="true"> <scroll-view
v-if="nearbyStoreList.length > 0"
scroll-x
class="store-scroll mt-28rpx pb-40rpx"
:show-scrollbar="false"
:enable-flex="true"
>
<view class="store-track"> <view class="store-track">
<view v-for="item in dishData" :key="item.id" @click="handleClickDish(item)" class="store-card"> <view
v-for="item in nearbyStoreList"
:key="item.id"
@click="handleClickStore(item)"
class="store-card"
>
<image <image
:src="thumbnailImg(getMerchantLogo(item))" :src="thumbnailImg(getStoreLogo(item))"
class="store-card__cover" class="store-card__cover"
mode="aspectFill" mode="aspectFill"
/> />
<view class="store-card__right"> <view class="store-card__right">
<view class="store-card__name line-clamp-2">{{ getMerchantName(item) }}</view> <view class="store-card__name line-clamp-2">{{ getStoreName(item) }}</view>
<view class="store-card__rating"> {{ getMerchantRate(item) }}</view> <view class="store-card__rating"> {{ getStoreRate(item) }}</view>
<view class="store-card__brand">{{ t("pages.browse.brandTag") }}</view> <view class="store-card__brand">{{ t("pages.browse.brandTag") }}</view>
<view class="store-card__arrow center"> <view class="store-card__arrow center">
<i class="i-carbon:chevron-right text-30rpx text-white"></i> <i class="i-carbon:chevron-right text-30rpx text-white"></i>
@@ -180,6 +196,15 @@ defineExpose({
</view> </view>
</view> </view>
</scroll-view> </scroll-view>
<view
v-else-if="nearbyStoreLoaded && !loading"
class="store-empty mt-28rpx pb-40rpx"
>
<view class="store-empty__icon-wrap center">
<i class="i-carbon:location-off store-empty__icon"></i>
</view>
<text class="store-empty__text">{{ t("pages.browse.nearbyEmpty") }}</text>
</view>
</view> </view>
</view> </view>
@@ -335,4 +360,35 @@ defineExpose({
border-radius: 50%; border-radius: 50%;
background: #111; background: #111;
} }
.store-empty {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 220rpx;
padding: 48rpx 32rpx;
border-radius: 20rpx;
background: #f7f7f7;
}
.store-empty__icon-wrap {
width: 96rpx;
height: 96rpx;
border-radius: 50%;
background: #ececec;
}
.store-empty__icon {
font-size: 44rpx;
color: #b0b0b0;
}
.store-empty__text {
margin-top: 24rpx;
font-size: 28rpx;
line-height: 40rpx;
color: #8a8a8a;
text-align: center;
}
</style> </style>