修改样式,修复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": {
"brandTag": "CHEFLINK Selected",
"moreRecipes": "More Recipes",
"nearbyEmpty": "No nearby data",
"titleCuisine": "Nearby Cuisine",
"titleRecipes": "Selected Recipes"
},
+2 -1
View File
@@ -222,7 +222,8 @@
"browse": {
"brandTag": "CHEFLINK 严选",
"moreRecipes": "更多食谱",
"titleCuisine": "附近美食",
"nearbyEmpty": "附近暂无美食",
"titleCuisine": "附近美食",
"titleRecipes": "选择食谱"
},
"home": {
+2 -2
View File
@@ -2,8 +2,8 @@
"name" : "CHEFLINK delivery",
"appid" : "__UNI__06509BE",
"description" : "",
"versionName" : "3.2.3",
"versionCode" : 323,
"versionName" : "3.2.4",
"versionCode" : 324,
"transformPx" : false,
/* 5+App */
"app-plus" : {
+44 -20
View File
@@ -971,7 +971,7 @@ function handleGoSettle() {
}
})
let data = {
const data: Record<string, any> = {
addressId: targetAddressId,
phone: formData.value.phone,
areaCode: contact.value.areaCode,
@@ -982,8 +982,6 @@ function handleGoSettle() {
deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付
orderRemark: formData.value.orderRemark,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
needTableware: needTableware.value ? 1 : 2, // 餐具 1是 2否
}
@@ -992,24 +990,21 @@ function handleGoSettle() {
data.startScheduledTime = result.startTimestamp
data.endScheduledTime = result.endTimestamp
} else {
const startMap: Record<string, number> = {}
const endMap: Record<string, number> = {}
cartDataList.value.forEach((m: any) => {
const ap = merchantAppointmentMap.value[String(m.id)]
if (ap?.startTime && ap?.endTime) {
startMap[String(m.id)] = ap.startTime
endMap[String(m.id)] = ap.endTime
}
})
data.merchantStartScheduledTimeMap = startMap
data.merchantEndScheduledTimeMap = endMap
const scheduled = buildScheduledTimePayload(
cartDataList.value as any[],
merchantAppointmentMap.value
)
data.startScheduledTime = scheduled.startScheduledTime
data.endScheduledTime = scheduled.endScheduledTime
data.merchantStartScheduledTimeMap = scheduled.startMap
data.merchantEndScheduledTimeMap = scheduled.endMap
}
console.log('批量下单参数', data)
appMerchantOrderCreateOrderCartBatchPost({
body: data
}).then(res=> {
console.log('批量下单成功', res)
resOrderIds.value = res.data.orderIds || []
resOrderIds.value = res.data?.orderIds || res.data || []
// 如果是余额支付,弹出支付密码弹窗
if(payMethodOptions.value.payMethod === 2) {
passwordInputRef.value?.showPasswordInput()
@@ -1019,6 +1014,11 @@ function handleGoSettle() {
} else {
appMerchantOrderPayOrderBatch()
}
}).catch((err: any) => {
uni.showToast({
title: err?.msg || err?.message || '下单失败',
icon: 'none',
})
})
} else {
// 如果是余额支付,弹出支付密码弹窗
@@ -1045,7 +1045,7 @@ function handleGoSettle() {
}
}
let data = {
const data: Record<string, any> = {
addressId: targetAddressId,
phone: formData.value.phone,
areaCode: contact.value.areaCode,
@@ -1055,15 +1055,12 @@ function handleGoSettle() {
deliveryType: deliveryTimeType.value, // 1-立即交付 2-预约交付
orderRemark: formData.value.orderRemark,
receiveMethod: deliveryMethod.value === 0 ? 1 : 2, // 收货方式(1-派送 2-自取)
startScheduledTime: '', //
endScheduledTime: '', //
tipDiscount: tipAmount, // 小费金额(美元),自取订单不需要小费
// weeklyDeliveryFee: isWeeklyDelivery.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);
data.startScheduledTime = result.startTimestamp
data.endScheduledTime = result.endTimestamp
@@ -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) {
// 验证输入是否为空
if (!timeStr || typeof timeStr !== 'string') {
+58 -6
View File
@@ -38,15 +38,28 @@ const storeShareTopStyle = computed(() => ({
top: `${configStore.statusBarHeight + uni.upx2px(16)}px`,
}))
const storeBannerSrc = computed(() => {
const storeBannerImages = computed(() => {
const raw = storeDetail.value?.shopImages
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
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 texts: string[] = []
if (+storeDetail.value?.deliveryService === 1 && deliveryMethod.value === 0) {
@@ -672,13 +685,34 @@ function handleShare() {
>
<view class="store-main__inner">
<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
v-if="storeBannerSrc"
:src="storeBannerSrc"
:src="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-if="storeBannerImages.length > 1"
class="store-banner__counter"
>
{{ storeBannerCurrent + 1 }}/{{ storeBannerImages.length }}
</view>
</view>
<view
@@ -1034,6 +1068,11 @@ page {
background: #e8e8e8;
}
.store-banner__swiper {
width: 100%;
height: 100%;
}
.store-banner__img {
width: 100%;
height: 100%;
@@ -1044,6 +1083,19 @@ page {
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 {
background: #fff7ed;
border-bottom: 1rpx solid #ffe8cc;
@@ -3,7 +3,7 @@ import Search from "../tabbar-home/components/search.vue";
import { useConfigStore, useUserStore } from "@/store";
import BrowseSkeleton from "./components/browse-skeleton.vue";
import {
appMerchantDishNearbyListPost,
appMerchantNearbyListPost,
appSearchSearchRecipePost,
} from "@/service";
import {thumbnailImg} from "@/utils/utils";
@@ -28,8 +28,7 @@ async function initData() {
loading.value = true;
}
getRecipeData()
// 获取菜品数据
appMerchantDishNearbyList()
getNearbyStoreList()
}
// 获取菜谱数据
@@ -56,38 +55,44 @@ function navigateToRecipeList() {
navigateTo('/pages-user/pages/recipe/list')
}
// 获取附近的菜品
const dishData = ref<any[]>([]);
function appMerchantDishNearbyList() {
appMerchantDishNearbyListPost({
params: {
pageNum: 1,
pageSize: 10,
},
// 获取附近店铺
const nearbyStoreList = ref<any[]>([]);
const nearbyStoreLoaded = ref(false);
function getNearbyStoreList() {
nearbyStoreLoaded.value = false;
appMerchantNearbyListPost({
body: {
lat: String(userStore.userLocation.latitude ?? ''),
lng: String(userStore.userLocation.longitude ?? ''),
}
}).then(res=> {
console.log('菜品数据', res)
dishData.value = res.rows;
lat: userStore.userLocation.latitude,
lng: userStore.userLocation.longitude,
},
})
}
function handleClickDish(item: any) {
navigateTo(`/pages-store/pages/store/index?id=${item.merchantId}`)
.then((res) => {
console.log("附近店铺", res);
nearbyStoreList.value = res.data || [];
})
.catch(() => {
nearbyStoreList.value = [];
})
.finally(() => {
nearbyStoreLoaded.value = true;
});
}
function getMerchantName(item: any) {
return item?.merchantVo?.merchantName || item?.merchantName||item?.dishName || '--'
function handleClickStore(item: any) {
navigateTo(`/pages-store/pages/store/index?id=${item.id}`);
}
function getMerchantLogo(item: any) {
return item?.merchantVo?.logo || item?.logo || item?.dishImage?.split?.(',')?.[0] || item?.dishImage || ''
function getStoreName(item: any) {
return item?.merchantName || "--";
}
function getMerchantRate(item: any) {
const rating = Number(item?.merchantVo?.rating ?? item?.rating ?? 0)
return Number.isFinite(rating) && rating > 0 ? rating.toFixed(1) : '5.0'
function getStoreLogo(item: any) {
return item?.logo || "";
}
function getStoreRate(item: any) {
const rating = Number(item?.rating ?? 0);
return Number.isFinite(rating) && rating > 0 ? rating.toFixed(1) : "5.0";
}
function getPreviewRecipeList() {
@@ -161,17 +166,28 @@ defineExpose({
</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 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
:src="thumbnailImg(getMerchantLogo(item))"
:src="thumbnailImg(getStoreLogo(item))"
class="store-card__cover"
mode="aspectFill"
/>
<view class="store-card__right">
<view class="store-card__name line-clamp-2">{{ getMerchantName(item) }}</view>
<view class="store-card__rating"> {{ getMerchantRate(item) }}</view>
<view class="store-card__name line-clamp-2">{{ getStoreName(item) }}</view>
<view class="store-card__rating"> {{ getStoreRate(item) }}</view>
<view class="store-card__brand">{{ t("pages.browse.brandTag") }}</view>
<view class="store-card__arrow center">
<i class="i-carbon:chevron-right text-30rpx text-white"></i>
@@ -180,6 +196,15 @@ defineExpose({
</view>
</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>
@@ -335,4 +360,35 @@ defineExpose({
border-radius: 50%;
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>