import {useEffect, useState} from 'react' import {View} from '@tarojs/components' import {Swiper} from '@nutui/nutui-react-taro' import {CmsAd} from "@/api/cms/cmsAd/model"; import {Image} from '@nutui/nutui-react-taro' import {getCmsAdByCode} from "@/api/cms/cmsAd"; import navTo from "@/utils/common"; import {pageCmsArticle} from "@/api/cms/cmsArticle"; import Taro from '@tarojs/taro' type AdImage = { url?: string path?: string title?: string // Compatible keys (some backends use different fields) src?: string imageUrl?: string } function normalizeAdImages(ad?: CmsAd): AdImage[] { const list = ad?.imageList if (Array.isArray(list) && list.length) return list as AdImage[] // Some APIs only return `images` as a JSON string. const raw = ad?.images if (!raw) return [] try { const parsed = JSON.parse(raw) return Array.isArray(parsed) ? (parsed as AdImage[]) : [] } catch { return [] } } function toNumberPx(input: unknown, fallback: number) { const n = typeof input === 'number' ? input : Number.parseInt(String(input ?? ''), 10) return Number.isFinite(n) ? n : fallback } const MyPage = () => { const [carouselData, setCarouselData] = useState() const [loading, setLoading] = useState(true) // const [disableSwiper, setDisableSwiper] = useState(false) const CACHE_KEY = 'home_banner_mp-ad' // 用于记录触摸开始位置 // const touchStartRef = useRef({x: 0, y: 0}) // 加载数据 const loadData = async (opts?: {silent?: boolean}) => { if (!opts?.silent) setLoading(true) try { // 只阻塞 banner 自己的数据;其他数据预热不应影响首屏展示速度 const flash = await getCmsAdByCode('mp-ad') setCarouselData(flash) void Taro.setStorage({ key: CACHE_KEY, data: flash }).catch(() => {}) } catch (error) { console.error('Banner数据加载失败:', error) } finally { if (!opts?.silent) setLoading(false) } // 后台预热(不阻塞 banner 渲染) void getCmsAdByCode('hot_today').catch(() => {}) void pageCmsArticle({ limit: 1, recommend: 1 }).catch(() => {}) } useEffect(() => { const cached = Taro.getStorageSync(CACHE_KEY) as CmsAd | undefined // 有缓存则先渲染缓存,避免首屏等待;再静默刷新 if (cached && normalizeAdImages(cached).length) { setCarouselData(cached) setLoading(false) void loadData({ silent: true }) return } void loadData() }, []) // 轮播图高度,默认300px const carouselHeight = toNumberPx(carouselData?.height, 300) const carouselImages = normalizeAdImages(carouselData) // 骨架屏组件 const BannerSkeleton = () => ( {/* 左侧轮播图骨架屏 */} {/* 右侧骨架屏 */} {/* 上层骨架屏 */} {[1, 2].map(i => ( ))} {/* 下层骨架屏 */} ) // 如果正在加载,显示骨架屏 if (loading) { return } return ( {carouselImages.map((img, index) => { const src = img.url || img.src || img.imageUrl if (!src) return null return ( (img.path ? navTo(`${img.path}`) : undefined)} // 首张图优先加载,其余按需懒加载,避免并发图片请求拖慢首屏可见 lazyLoad={index !== 0} style={{ height: `${carouselHeight}px`, borderRadius: '4px', touchAction: 'manipulation' // 关键修改:优化触摸操作 }} /> ) })} ) } export default MyPage