fix(index): 修复首页轮播图显示与高度自适应问题

- 解决首页轮播图仅显示第一张图片的问题,支持广告位多图展开显示
- 通过 flatMap 展开广告位所有图片为独立轮播项,兼容单图老数据
- 轮播图点击跳转逻辑按广告位路径保持不变
- 获取轮播容器实际宽度,计算轮播高度自适应,替代固定 160px 高度
- 根据后台广告位宽高比计算轮播图展示高度,无效数据时回退到默认高度
- 轮播容器新增类名便于 DOM 选择和尺寸测量
- 轮播图及占位区高度均采用动态计算结果,适配不同设备屏幕宽度
This commit is contained in:
2026-07-15 22:30:02 +08:00
parent 4d646b3fd6
commit 501e79eed7
2 changed files with 52 additions and 4 deletions

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useCallback, useRef } from 'react'
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react'
import { View, Text, ScrollView, Swiper, SwiperItem, Image } from '@tarojs/components'
import Taro, { useDidShow } from '@tarojs/taro'
import { useUser } from '@/hooks/useUser'
@@ -26,6 +26,7 @@ definePageConfig({
const IndexPage: React.FC = () => {
const { user, isLoggedIn } = useUser()
const [banners, setBanners] = useState<CmsAd[]>([])
const [bannerWrapWidth, setBannerWrapWidth] = useState(0)
const [announcements, setAnnouncements] = useState<CmsArticle[]>([])
const [hotProducts, setHotProducts] = useState<ShopGoods[]>([])
const [loading, setLoading] = useState(true)
@@ -190,6 +191,31 @@ const IndexPage: React.FC = () => {
}
}
// 获取轮播容器实际宽度,用于根据后台 width/height 计算比例高度
useEffect(() => {
if (bannerWrapWidth > 0) return
const timer = setTimeout(() => {
const query = Taro.createSelectorQuery()
query.select('.index-banner-wrap').boundingClientRect((rect) => {
if (rect && rect.width > 0) {
setBannerWrapWidth(rect.width)
}
}).exec()
}, 0)
return () => clearTimeout(timer)
}, [bannerWrapWidth])
// 根据广告位后台返回的 width/height 计算轮播区域高度(无值则 fallback 160px
const bannerHeight = useMemo(() => {
if (bannerWrapWidth <= 0) return 160
const firstAd = banners.find(b => b.width && b.height)
if (!firstAd) return 160
const w = parseInt(firstAd.width || '0', 10)
const h = parseInt(firstAd.height || '0', 10)
if (!w || !h || w <= 0 || h <= 0) return 160
return Math.round(bannerWrapWidth * (h / w))
}, [bannerWrapWidth, banners])
// 轮播图数据:每个广告位下的所有图片都作为独立轮播项
const bannerSlides = banners.flatMap(item =>
(item.imageList && item.imageList.length > 0)
@@ -233,13 +259,13 @@ const IndexPage: React.FC = () => {
<ScrollView scrollY style={{ height: scrollHeight }}>
{/* 轮播图 */}
<View className='mx-3 mt-2 rounded-lg overflow-hidden'>
<View className='mx-3 mt-2 rounded-lg overflow-hidden index-banner-wrap'>
{bannerSlides.length > 0 ? (
<Swiper
autoplay
interval={3000}
className='rounded-lg'
style={{ height: '160px' }}
style={{ height: `${bannerHeight}px` }}
>
{bannerSlides.map(slide => (
<SwiperItem key={slide.key}>
@@ -255,7 +281,7 @@ const IndexPage: React.FC = () => {
))}
</Swiper>
) : (
<View className='w-full bg-green-50 flex items-center justify-center' style={{ height: '160px' }}>
<View className='w-full bg-green-50 flex items-center justify-center' style={{ height: `${bannerHeight}px` }}>
<Text className='text-gray-400 text-sm'></Text>
</View>
)}