import { useState } from 'react'; import { View, Image, Swiper, SwiperItem } from '@tarojs/components'; import Taro from '@tarojs/taro'; type ProductCarouselProps = { images: string[]; alt: string; variant?: 'home' | 'detail' | 'store'; previewable?: boolean; /** * cover=aspectFill 裁剪铺满(固定高度,可能裁切) * contain=aspectFit 完整显示(固定高度,可能留白) * adaptive=widthFix 按图片真实比例自适应高度,完整显示不裁剪(门店套餐详情用) * 依赖 swiper 原生 auto-height:海报有多高,轮播就有多高,无裁切。 */ imageFit?: 'cover' | 'contain' | 'adaptive'; /** 预览相册(默认等于 images);门店详情可传入封面+环境图合并列表 */ previewUrls?: string[]; }; /** 商品/门店轮播(对齐 h5 ProductCarousel 三变体) */ export default function ProductCarousel({ images, alt, variant = 'detail', previewable = false, imageFit = 'cover', previewUrls, }: ProductCarouselProps) { const slides = images.length > 0 ? images : ['']; const [activeIndex, setActiveIndex] = useState(0); const prefix = variant === 'store' ? 'store-detail-carousel' : variant === 'home' ? 'home-carousel' : 'detail-carousel'; const isContain = imageFit === 'contain'; const isAdaptive = imageFit === 'adaptive'; const wrapClass = `${prefix}-wrap${isContain ? ` ${prefix}-wrap--contain` : ''}${isAdaptive ? ` ${prefix}-wrap--adaptive` : ''}`; function previewAt(index: number) { const album = (previewUrls?.length ? previewUrls : slides).filter(Boolean); if (!album.length) return; const current = slides[index] || album[0]; Taro.previewImage({ current, urls: album }).catch(() => undefined); } return ( 1} autoHeight={isAdaptive} {...(variant === 'detail' && slides.length > 1 ? { autoplay: true, interval: 3500 } : {})} onChange={(e) => setActiveIndex(e.detail.current)} > {slides.map((src, index) => ( {src ? ( {alt} previewAt(index) : undefined} /> ) : ( )} ))} {slides.length > 1 ? ( {slides.map((_, index) => ( ))} ) : null} {variant === 'detail' && slides.length > 1 ? ( {activeIndex + 1}/{slides.length} ) : null} ); }