Files
glt-taro/src/pages/index/Banner.tsx
赵忠林 f5c6d52b78 feat(rider): 添加配送员模块和订单图片保存功能
- 新增配送员首页界面,包含订单管理、工资明细、配送小区、仓库地址等功能入口
- 实现小程序码保存到相册功能,支持权限检查和错误处理
- 添加相册写入权限配置和图片下载临时路径处理
- 修复订单列表商品信息显示问题,优化支付流程
- 更新首页轮播图广告代码,调整用户中心网格布局
- 增加订单页面返回时的数据刷新机制,提升用户体验
2026-01-31 02:52:28 +08:00

167 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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";
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<CmsAd>()
const [loading, setLoading] = useState(true)
// const [disableSwiper, setDisableSwiper] = useState(false)
// 用于记录触摸开始位置
// const touchStartRef = useRef({x: 0, y: 0})
// 加载数据
const loadData = async () => {
setLoading(true)
try {
const [flashRes] = await Promise.allSettled([
getCmsAdByCode('mp-ad'),
getCmsAdByCode('hot_today'),
pageCmsArticle({ limit: 1, recommend: 1 }),
])
if (flashRes.status === 'fulfilled') {
console.log('flashflashflash', flashRes.value)
setCarouselData(flashRes.value)
} else {
console.error('Failed to fetch flash:', flashRes.reason)
}
} catch (error) {
console.error('Banner数据加载失败:', error)
} finally {
setLoading(false)
}
}
useEffect(() => {
loadData().then()
}, [])
// 轮播图高度默认300px
const carouselHeight = toNumberPx(carouselData?.height, 300)
const carouselImages = normalizeAdImages(carouselData)
console.log(carouselImages,'carouselImages')
// 骨架屏组件
const BannerSkeleton = () => (
<View className="flex p-2 justify-between" style={{height: `${carouselHeight}px`}}>
{/* 左侧轮播图骨架屏 */}
<View style={{width: '50%', height: '100%'}}>
<View
className="bg-gray-200 rounded animate-pulse"
style={{height: `${carouselHeight}px`}}
/>
</View>
{/* 右侧骨架屏 */}
<View className="flex flex-col" style={{width: '50%', height: '100%'}}>
{/* 上层骨架屏 */}
<View className="ml-2 bg-white rounded-lg">
<View className="px-3 my-2">
<View className="bg-gray-200 h-4 w-16 rounded animate-pulse"/>
</View>
<View className="px-3 flex" style={{height: '110px'}}>
{[1, 2].map(i => (
<View key={i} className="item flex flex-col mr-4">
<View className="bg-gray-200 rounded animate-pulse" style={{width: 70, height: 70}}/>
<View className="bg-gray-200 h-3 w-16 rounded mt-2 animate-pulse"/>
</View>
))}
</View>
</View>
{/* 下层骨架屏 */}
<View className="ml-2 bg-white rounded-lg mt-3">
<View className="px-3 my-2">
<View className="bg-gray-200 h-4 w-20 rounded animate-pulse"/>
</View>
<View className="rounded-lg px-3 pb-3">
<View className="bg-gray-200 rounded animate-pulse" style={{width: '100%', height: 106}}/>
</View>
</View>
</View>
</View>
)
// 如果正在加载,显示骨架屏
if (loading) {
return <BannerSkeleton />
}
return (
<Swiper
defaultValue={0}
height={carouselHeight}
indicator
autoPlay
duration={3000}
style={{
height: `${carouselHeight}px`,
touchAction: 'pan-y' // 关键修改:允许垂直滑动
}}
disableTouch={false}
direction="horizontal"
className="custom-swiper"
>
{carouselImages.map((img, index) => {
const src = img.url || img.src || img.imageUrl
if (!src) return null
return (
<Swiper.Item key={index} style={{ touchAction: 'pan-x pan-y' }}>
<Image
width="100%"
height="100%"
src={src}
mode={'scaleToFill'}
onClick={() => (img.path ? navTo(`${img.path}`) : undefined)}
lazyLoad={false}
style={{
height: `${carouselHeight}px`,
borderRadius: '4px',
touchAction: 'manipulation' // 关键修改:优化触摸操作
}}
/>
</Swiper.Item>
)
})}
</Swiper>
)
}
export default MyPage