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: "/treasure-hunt/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)}%) {/* 商品名称 */} {currentProduct.name} )} {/* 左右切换按钮 */} {currentIndex > 0 && ( )} {currentIndex < products.length - 1 && ( )} {/* 左侧装饰 */} {/* 右侧装饰 */} {/* 底部装饰文字 */} {/* 侧边按钮 - 规则 */} ruleRef.current?.show()} > 规则 {/* 侧边按钮 - 记录 */} recordRef.current?.show()} > 记录 {/* 侧边按钮 - 客服 */} kefuRef.current?.open()} > 客服 {/* 侧边按钮 - 仓库 */} router.push("/cloud-warehouse" 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 }, positionService: { top: 300, 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", }, });