import { Image } from 'expo-image'; import { useLocalSearchParams, useRouter } from 'expo-router'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { ActivityIndicator, Animated, Dimensions, ImageBackground, ScrollView, StatusBar, StyleSheet, Text, TouchableOpacity, View, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Images } from '@/constants/images'; import { getPoolDetail, poolIn, poolOut, previewOrder, } from '@/services/award'; import { CheckoutModal } from './components/CheckoutModal'; import { ExplainSection } from './components/ExplainSection'; import { ProductList } from './components/ProductList'; import { RecordModal } from './components/RecordModal'; import { RuleModal } from './components/RuleModal'; const { width: SCREEN_WIDTH } = Dimensions.get('window'); interface PoolData { id: string; name: string; cover: string; price: number; specialPrice?: number; specialPriceFive?: number; demoFlag?: number; luckGoodsList: ProductItem[]; luckGoodsLevelProbabilityList?: any[]; } interface ProductItem { id: string; name: string; cover: string; level: string; probability: number; price?: number; } export default function AwardDetailScreen() { const { poolId } = useLocalSearchParams<{ poolId: string }>(); const router = useRouter(); const insets = useSafeAreaInsets(); const [loading, setLoading] = useState(true); const [data, setData] = useState(null); const [products, setProducts] = useState([]); const [currentIndex, setCurrentIndex] = useState(0); const [scrollTop, setScrollTop] = useState(0); const checkoutRef = useRef(null); const recordRef = useRef(null); const ruleRef = useRef(null); const floatAnim = useRef(new Animated.Value(0)).current; useEffect(() => { Animated.loop( Animated.sequence([ Animated.timing(floatAnim, { toValue: 10, duration: 1500, useNativeDriver: true }), Animated.timing(floatAnim, { toValue: -10, duration: 1500, useNativeDriver: true }), ]) ).start(); }, []); const loadData = useCallback(async () => { if (!poolId) return; setLoading(true); try { const detail = await getPoolDetail(poolId); if (detail) { setData(detail); setProducts(detail.luckGoodsList || []); } } catch (error) { console.error('加载数据失败:', error); } setLoading(false); }, [poolId]); useEffect(() => { loadData(); if (poolId) poolIn(poolId); return () => { if (poolId) poolOut(poolId); }; }, [poolId]); const handlePay = async (num: number) => { if (!poolId || !data) return; try { const preview = await previewOrder(poolId, num); if (preview) checkoutRef.current?.show(num, preview); } catch (error) { console.error('预览订单失败:', error); } }; const handleSuccess = () => { setTimeout(() => loadData(), 500); }; const handleProductPress = (index: number) => { router.push({ pathname: '/award-detail/swipe' as any, params: { poolId, index }, }); }; const handlePrev = () => { if (currentIndex > 0) setCurrentIndex(currentIndex - 1); }; const handleNext = () => { if (currentIndex < products.length - 1) setCurrentIndex(currentIndex + 1); }; const getLevelName = (level: string) => { const map: Record = { A: '超神款', B: '欧皇款', C: '隐藏款', D: '普通款' }; return map[level] || level; }; const ignoreRatio0 = (val: number) => { const str = String(val); const match = str.match(/^(\d+\.?\d*?)0*$/); return match ? match[1].replace(/\.$/, '') : str; }; if (loading) { return ( ); } if (!data) { return ( 奖池不存在 router.back()}> 返回 ); } const currentProduct = products[currentIndex]; const headerBg = scrollTop > 0 ? '#333' : 'transparent'; return ( {/* 顶部导航 */} router.back()}> {'<'} {data.name} setScrollTop(e.nativeEvent.contentOffset.y)} scrollEventThrottle={16} > {/* 主商品展示区域 */} {/* 商品轮播区域 */} {currentProduct && ( <> handleProductPress(currentIndex)} activeOpacity={0.9}> {/* 等级信息 */} {getLevelName(currentProduct.level)} ({ignoreRatio0(currentProduct.probability * 100)}%) {/* 商品名称 */} {currentProduct.name} )} {/* 左右切换按钮 */} {currentIndex > 0 && ( )} {currentIndex < products.length - 1 && ( )} {/* 左侧装饰 */} {/* 右侧装饰 */} {/* 底部装饰文字 */} {/* 侧边按钮 - 规则 */} ruleRef.current?.show()}> 规则 {/* 侧边按钮 - 记录 */} recordRef.current?.show()}> 记录 {/* 侧边按钮 - 仓库 */} router.push('/store' as any)}> 仓库 {/* 商品列表 */} {/* 说明文字 */} {/* 底部购买栏 */} handlePay(1)} activeOpacity={0.8}> 购买一盒 (¥{data.specialPrice || data.price}) handlePay(5)} activeOpacity={0.8}> 购买五盒 (¥{data.specialPriceFive || data.price * 5}) checkoutRef.current?.showFreedom()} activeOpacity={0.8}> 购买多盒 ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#1a1a2e' }, background: { flex: 1 }, loadingContainer: { flex: 1, backgroundColor: '#1a1a2e', justifyContent: 'center', alignItems: 'center' }, errorText: { color: '#999', fontSize: 16 }, backBtn2: { marginTop: 20, backgroundColor: '#ff6600', paddingHorizontal: 20, paddingVertical: 10, borderRadius: 8 }, backBtn2Text: { color: '#fff', fontSize: 14 }, // 顶部导航 header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 10, paddingBottom: 10, position: 'absolute', top: 0, left: 0, right: 0, zIndex: 100, }, backBtn: { width: 40, height: 40, justifyContent: 'center', alignItems: 'center' }, backText: { color: '#fff', fontSize: 16, fontWeight: 'bold' }, headerTitle: { color: '#fff', fontSize: 15, fontWeight: 'bold', flex: 1, textAlign: 'center', width: 250 }, placeholder: { width: 40 }, scrollView: { flex: 1 }, // 主商品展示区域 mainGoodsSection: { width: SCREEN_WIDTH, height: 504, position: 'relative', }, mainSwiper: { position: 'relative', width: '100%', height: 375, alignItems: 'center', justifyContent: 'center', marginTop: -50, }, productImageBox: { width: 200, height: 300, justifyContent: 'center', alignItems: 'center', }, productImage: { width: 200, height: 300, }, detailsBut: { width: 120, height: 45, justifyContent: 'center', alignItems: 'center', marginTop: -30, }, detailsText: { flexDirection: 'row', alignItems: 'center', }, levelText: { fontSize: 14, color: '#FBC400', fontWeight: 'bold', }, probabilityText: { fontSize: 10, color: '#FBC400', marginLeft: 3, }, goodsNameBg: { position: 'absolute', left: 47, top: 53, width: 43, height: 100, paddingTop: 8, justifyContent: 'flex-start', alignItems: 'center', }, goodsNameText: { fontSize: 12, fontWeight: 'bold', color: '#000', writingDirection: 'ltr', width: 20, textAlign: 'center', }, prevBtn: { position: 'absolute', left: 35, top: '40%' }, nextBtn: { position: 'absolute', right: 35, top: '40%' }, arrowImg: { width: 33, height: 38 }, // 装饰图片 positionBgleftBg: { position: 'absolute', left: 0, top: 225, width: 32, height: 188, }, positionBgRightBg: { position: 'absolute', right: 0, top: 225, width: 32, height: 188, }, mainGoodsSectionBtext: { width: SCREEN_WIDTH, height: 74, marginTop: -10, }, // 侧边按钮 positionBut: { position: 'absolute', zIndex: 10, width: 35, height: 34, }, positionButBg: { width: 35, height: 34, justifyContent: 'center', alignItems: 'center', }, positionButText: { fontSize: 12, fontWeight: 'bold', color: '#fff', transform: [{ rotate: '14deg' }], textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1, }, positionButTextR: { fontSize: 12, fontWeight: 'bold', color: '#fff', transform: [{ rotate: '-16deg' }], textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1, }, positionRule: { top: 256, left: 0 }, positionRecord: { top: 300, left: 0 }, positionStore: { top: 256, right: 0 }, // 底部购买栏 bottomBar: { position: 'absolute', bottom: 0, left: 0, right: 0, height: 69, paddingHorizontal: 5, }, bottomBtns: { flexDirection: 'row', height: 64, alignItems: 'center', justifyContent: 'space-around', }, btnItem: { flex: 1, marginHorizontal: 6, }, btnBg: { width: '100%', height: 54, justifyContent: 'center', alignItems: 'center', }, btnText: { fontSize: 14, fontWeight: 'bold', color: '#fff', }, btnPrice: { fontSize: 9, color: '#fff', }, });