From 5ce0d76154bf4c1d70543476cdfad9a30195b0f8 Mon Sep 17 00:00:00 2001
From: shinnosuke <tantao@1hoper.com>
Date: 星期六, 10 十月 2026 16:44:38 +0800
Subject: [PATCH] fix(miniapp): 调整首页圆角布局并隐藏滚动条

---
 rencaika/pages/transport-benefits/transport-benefits.uvue |   30 +++++++++++++++++++++---------
 1 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/rencaika/pages/transport-benefits/transport-benefits.uvue b/rencaika/pages/transport-benefits/transport-benefits.uvue
index 7afd722..c92dee8 100644
--- a/rencaika/pages/transport-benefits/transport-benefits.uvue
+++ b/rencaika/pages/transport-benefits/transport-benefits.uvue
@@ -10,9 +10,14 @@
 			</view>
 		</view>
 
-		<scroll-view class="page-scroll" scroll-y lower-threshold="80" @scroll="handleScroll" @scrolltolower="loadMoreServices">
+		<scroll-view :show-scrollbar="false" class="page-scroll" scroll-y lower-threshold="80" @scroll="handleScroll" @scrolltolower="loadMoreServices">
 			<view class="hero">
-				<image class="hero-image" :src="currentScene.image" mode="aspectFill" @error="replaceHeroImage"></image>
+				<swiper v-if="scenes.length > 0" class="hero-swiper" :current="activeIndex < 0 ? 0 : activeIndex" :circular="scenes.length > 1" :duration="240" @change="handleHeroChange">
+					<swiper-item v-for="(item, index) in scenes" :key="item.id">
+						<image class="hero-image" :src="item.image" mode="aspectFill" @error="replaceSceneImage(index)"></image>
+					</swiper-item>
+				</swiper>
+				<image v-else class="hero-image" :src="currentScene.image" mode="aspectFill" @error="replaceHeroImage"></image>
 				<view class="hero-top-shade"></view>
 				<view class="hero-bottom-shade"></view>
 				<text v-if="currentScene.name != ''" class="scene-name">{{currentScene.name}}</text>
@@ -42,7 +47,7 @@
 						<image class="service-image" :src="item.image" mode="aspectFill" @error="replaceServiceImage(item)"></image>
 						<view class="service-info">
 							<text class="service-name">{{item.name}}</text>
-							<text class="service-discount">{{item.available ? item.discount : '已下架'}}</text>
+							<text v-if="!item.available || item.benefitTagVisible" class="service-discount">{{item.available ? item.discount : '已下架'}}</text>
 							<view class="address-row"><image src="/static/benefits-assets/map-pin.svg"></image><text>{{item.address}}</text></view>
 						</view>
 					</view>
@@ -60,14 +65,16 @@
 	import { isApiConfigured } from '../../config/api.uts'
 	import { getTransportTopic, getTransportTopicMerchants } from '../../services/portal.uts'
 	import { resolveApiUrl } from '../../services/http.uts'
+	import { resolveTalentId } from '../../utils/talent-id.uts'
 	import { safeBack } from '../../utils/navigation.uts'
 
 	const navTop = ref(28); const navHeight = ref(32); const navWidth = ref(88); const navRight = ref(10)
-	const isSolidNav = ref(false); const windowWidth = ref(375); const fallbackImage = '/static/home-assets/top.jpg'
-	const fallbackScenes = [{ id: 'fallback-fuel', name: '人才加油服务', image: '/static/home-assets/top.jpg' }, { id: 'fallback-parking', name: '人才停车服务', image: '/static/home-assets/city-intro.jpg' }]
+	const isSolidNav = ref(false); const windowWidth = ref(375); const fallbackImage = ''
+	const fallbackScenes: any[] = []
 	const topicTitle = ref('行--畅行无忧'); const topicDescription = ref('整合加油、停车、洗车等出行服务资源,为人才提供专属折扣、停车优惠和便捷洗车服务,全方位保障人才出行便捷。'); const topicError = ref(false)
-	const activeIndex = ref(0); const sceneScrollLeft = ref(0); const sceneTrackWidth = ref(644 + fallbackScenes.length * 137); const scenes = ref<any[]>(fallbackScenes); const currentScene = ref(fallbackScenes[0])
+	const activeIndex = ref(0); const sceneScrollLeft = ref(0); const sceneTrackWidth = ref(644); const scenes = ref<any[]>(fallbackScenes); const currentScene = ref({ id: '', name: '', image: '' })
 	const serviceTabs = [{ key: 'fuel', label: '加油服务' }, { key: 'parking', label: '停车服务' }, { key: 'carWash', label: '自助洗车服务' }]
+	const talentId = ref('')
 	const activeTab = ref('fuel'); const visibleServices = ref<any[]>([]); const initialLoading = ref(true); const initialError = ref(false); const loadingMore = ref(false); const loadMoreError = ref(false); const hasLoaded = ref(false); const hasMore = ref(false); const currentPage = ref(0); const listRequestVersion = ref(0); const failInitialOnce = ref(false); const failLoadMoreOnce = ref(false)
 
 	onLoad((options: any) => {
@@ -75,6 +82,7 @@
 		const capsule = uni.getMenuButtonBoundingClientRect(); const info = uni.getSystemInfoSync(); windowWidth.value = info.windowWidth; navTop.value = capsule.top; navHeight.value = capsule.height; navWidth.value = capsule.width; navRight.value = info.windowWidth - capsule.right
 		// #endif
 		if (options != null && options['previewState'] != null) { const state = options['previewState'] as string; failInitialOnce.value = state == 'initialError'; failLoadMoreOnce.value = state == 'loadMoreError' }
+		talentId.value = resolveTalentId()
 		selectScene(0); loadTransportTopic(); loadInitialServices()
 	})
 	const loadTransportTopic = () => {
@@ -92,6 +100,8 @@
 	const retryInitialLoad = () => loadInitialServices(); const retryLoadMore = () => loadMoreServices()
 	const selectScene = (index: number) => { if (index < 0 || index >= scenes.value.length) return; activeIndex.value = index; currentScene.value = scenes.value[index]; sceneScrollLeft.value = index * 137 * windowWidth.value / 750 }
 	const handleSceneScrollEnd = (event: any) => { let index = Math.round(event.detail.scrollLeft * 750 / windowWidth.value / 137); if (index < 0) index = 0; if (index >= scenes.value.length) index = scenes.value.length - 1; selectScene(index) }
+	/** 主图左右滑动:滑动落点同步到缩略图、名称与描述。 */
+	const handleHeroChange = (event: any) => { const current = event != null && event.detail != null && event.detail.current != null ? Number(event.detail.current) : -1; if (current < 0) return; selectScene(current) }
 	const handleScroll = (event: any) => { isSolidNav.value = event.detail.scrollTop > 64 }
 	const selectTab = (tab: string) => { if (activeTab.value == tab && hasLoaded.value) return; activeTab.value = tab; loadInitialServices() }
 	const loadServices = (append: boolean) => {
@@ -99,17 +109,17 @@
 		const requestVersion = listRequestVersion.value
 		if (!append && failInitialOnce.value) { failInitialOnce.value = false; initialLoading.value = false; initialError.value = true; return }
 		if (append && failLoadMoreOnce.value) { failLoadMoreOnce.value = false; loadingMore.value = false; loadMoreError.value = true; return }
-		getTransportTopicMerchants(activeTab.value, currentPage.value + 1, 4, (data: any) => {
+		getTransportTopicMerchants(activeTab.value, talentId.value, currentPage.value + 1, 4, (data: any) => {
 			if (requestVersion != listRequestVersion.value) return
 			const records: any[] = data != null && data.records instanceof Array ? data.records as any[] : []; const next = append ? visibleServices.value.slice() : []
-			for (let index = 0; index < records.length; index++) { const item = records[index]; next.push({ id: '' + item.id, merchantType: item.merchantType != null ? item.merchantType as string : activeTab.value, name: item.merchantName != null ? item.merchantName as string : '行服务', discount: item.discountText != null ? item.discountText as string : '人才专享', address: item.address != null ? item.address as string : '', image: item.coverUrl != null && item.coverUrl != '' ? resolveApiUrl(item.coverUrl as string) : fallbackImage, available: item.available !== false }) }
+			for (let index = 0; index < records.length; index++) { const item = records[index]; const merchantType = item.merchantType != null ? item.merchantType as string : activeTab.value; const discount = merchantType == 'fuel' ? '' : (item.discountText != null ? item.discountText as string : ''); next.push({ id: '' + item.id, merchantType: merchantType, name: item.merchantName != null ? item.merchantName as string : '行服务', discount: discount, benefitTagVisible: merchantType == 'fuel' ? false : (merchantType == 'carWash' ? item.benefitTagVisible === true : discount != ''), address: item.address != null ? item.address as string : '', image: item.coverUrl != null && item.coverUrl != '' ? resolveApiUrl(item.coverUrl as string) : fallbackImage, available: item.available !== false, externalLinkType: item.externalLinkType != null ? item.externalLinkType as string : '' }) }
 			visibleServices.value = next; currentPage.value++; hasMore.value = data != null && data.total != null ? next.length < data.total : false; initialLoading.value = false; loadingMore.value = false; hasLoaded.value = true
 		}, () => { if (requestVersion != listRequestVersion.value) return; initialLoading.value = false; loadingMore.value = false; if (append) loadMoreError.value = true; else initialError.value = true })
 	}
 	const loadMoreServices = () => { if (initialLoading.value || loadingMore.value || !hasMore.value) return; loadMoreError.value = false; loadingMore.value = true; loadServices(true) }
 	const replaceHeroImage = () => { currentScene.value.image = fallbackImage }; const replaceSceneImage = (index: number) => { if (index >= 0 && index < scenes.value.length) scenes.value[index].image = fallbackImage }; const replaceServiceImage = (item: any) => { item.image = fallbackImage }
 	const goBack = () => safeBack('/pages/benefits/benefits')
-	const openMerchant = (item: any) => { if (!item.available) { uni.showToast({ title: '该服务已下架', icon: 'none' }); return }; if (item.merchantType == 'carWash') { uni.navigateTo({ url: '/pages/car-wash-merchant/car-wash-merchant?merchantId=' + encodeURIComponent(item.id) + '&name=' + encodeURIComponent(item.name) }); return }; const action = item.merchantType == 'parking' && item.discount.indexOf('人才码') >= 0 ? 'talentCode' : ''; uni.navigateTo({ url: '/pages/merchant/merchant?type=transport&merchantType=' + encodeURIComponent(item.merchantType) + '&merchantId=' + encodeURIComponent(item.id) + '&name=' + encodeURIComponent(item.name) + '&image=' + encodeURIComponent(item.image) + '&address=' + encodeURIComponent(item.address) + '&discount=' + encodeURIComponent(item.discount) + '&action=' + encodeURIComponent(action) }) }
+	const openMerchant = (item: any) => { if (!item.available) { uni.showToast({ title: '该服务已下架', icon: 'none' }); return }; if (item.merchantType == 'carWash' || item.merchantType == '自助洗车') { if (item.externalLinkType == 'miniProgram' || item.externalLinkType == 'web') { uni.navigateTo({ url: '/pages/car-wash-merchant/car-wash-merchant?merchantId=' + encodeURIComponent(item.id) + '&name=' + encodeURIComponent(item.name) }); return }; uni.navigateTo({ url: '/pages/merchant/merchant?merchantType=carWash&merchantId=' + encodeURIComponent(item.id) + '&name=' + encodeURIComponent(item.name) + '&image=' + encodeURIComponent(item.image) + '&address=' + encodeURIComponent(item.address) + '&discount=' + encodeURIComponent(item.discount) }); return }; const action = item.merchantType == 'parking' && item.discount.indexOf('人才码') >= 0 ? 'talentCode' : ''; uni.navigateTo({ url: '/pages/merchant/merchant?type=transport&merchantType=' + encodeURIComponent(item.merchantType) + '&merchantId=' + encodeURIComponent(item.id) + '&name=' + encodeURIComponent(item.name) + '&image=' + encodeURIComponent(item.image) + '&address=' + encodeURIComponent(item.address) + '&discount=' + encodeURIComponent(item.discount) + '&action=' + encodeURIComponent(action) }) }
 </script>
 
 <style>
@@ -128,6 +138,8 @@
 	.capsule-space { height: 100%; flex-shrink: 0; }
 	.hero { height: 730rpx; position: relative; z-index: 2; overflow: visible; background-color: #6A563E; }
 	.hero-image { position: absolute; left: 0; top: 0; width: 100%; height: 730rpx; }
+	/* 主图轮播:与下方缩略图带同高同位,盖在原来的静态主图上。 */
+	.hero-swiper { position: absolute; left: 0; top: 0; width: 100%; height: 730rpx; }
 	.hero-top-shade { position: absolute; left: 0; right: 0; top: 0; height: 230rpx; background-image: linear-gradient(180deg, rgba(0,0,0,.60) 0%, rgba(0,0,0,.18) 68%, rgba(0,0,0,0) 100%); }
 	.hero-bottom-shade { position: absolute; left: 0; right: 0; bottom: 0; height: 230rpx; background-image: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,.46) 100%); }
 	.scene-name { position: absolute; z-index: 3; left: 38rpx; top: 322rpx; color: #FFFFFF; font-family: 'FoodCalligraphy'; font-size: 48rpx; line-height: 66rpx; text-shadow: 0 3rpx 10rpx rgba(0,0,0,.55); }

--
Gitblit v1.7.1