import { Image } from 'expo-image'; import { useLocalSearchParams, useRouter } from 'expo-router'; import React, { useCallback, useEffect, useRef, useState } from 'react'; import { ActivityIndicator, Alert, ImageBackground, Modal, ScrollView, StatusBar, StyleSheet, Text, TextInput, TouchableOpacity, View, } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; import { Images } from '@/constants/images'; import { getWealDetail, getWinningRecord, joinWealRoom } from '@/services/weal'; const TYPE_MAP: any = { COMMON: { title: '福利房' }, PASSWORD: { title: '口令房' }, ACHIEVEMENT: { title: '成就房' }, EUROPEAN_GAS: { title: '欧气房' }, HONOR_ROLL: { title: '荣耀榜' }, }; export default function WealDetailScreen() { const { id } = useLocalSearchParams<{ id: string }>(); const router = useRouter(); const insets = useSafeAreaInsets(); const [loading, setLoading] = useState(true); const [data, setData] = useState(null); const [leftTime, setLeftTime] = useState(0); const [scrollTop, setScrollTop] = useState(0); const [winVisible, setWinVisible] = useState(false); const [winRecords, setWinRecords] = useState([]); const [joinVisible, setJoinVisible] = useState(false); const [password, setPassword] = useState(''); const timerRef = useRef(null); const loadData = useCallback(async (showLoading = false) => { if (showLoading) setLoading(true); try { const res = await getWealDetail(id as string); if (res) { setData(res); setLeftTime(res.leftTime); } } catch (error) { console.error('加载详情失败:', error); } setLoading(false); }, [id]); useEffect(() => { loadData(true); return () => stopTimer(); }, [loadData]); useEffect(() => { if (data?.status === 1 && leftTime > 0) { startTimer(); } else { stopTimer(); } }, [data, leftTime]); const startTimer = () => { stopTimer(); timerRef.current = setInterval(() => { setLeftTime(prev => { if (prev <= 0) { stopTimer(); loadData(); return 0; } return prev - 1000; }); }, 1000); }; const stopTimer = () => { if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null; } }; const formatLeftTime = () => { if (leftTime <= 0) return '00:00:00'; let second = Math.floor(leftTime / 1000); const d = Math.floor(second / (24 * 3600)); second %= 24 * 3600; const h = Math.floor(second / 3600); second %= 3600; const m = Math.floor(second / 60); const s = second % 60; let res = ''; if (d > 0) res += `${d}天`; res += `${h.toString().padStart(2, '0')}时${m.toString().padStart(2, '0')}分${s.toString().padStart(2, '0')}秒`; return res; }; const handleJoin = async () => { if (data.status !== 1 || data.myParticipatedFlag === 1) return; if (data.type === 'PASSWORD') { setJoinVisible(true); } else { try { const res = await joinWealRoom(id as string, ''); if (res.success) { Alert.alert('提示', '加入成功'); loadData(); } else { Alert.alert('错误', res.msg || '加入失败'); } } catch (error) { Alert.alert('错误', '请求异常'); } } }; const handleJoinWithPassword = async () => { if (!password) return; try { const res = await joinWealRoom(id as string, password); if (res.success) { Alert.alert('提示', '加入成功'); setJoinVisible(false); setPassword(''); loadData(); } else { Alert.alert('错误', res.msg || '口令错误'); } } catch (error) { Alert.alert('错误', '请求异常'); } }; const showWinRecords = async () => { try { const res = await getWinningRecord(id as string); setWinRecords(res || []); setWinVisible(true); } catch (error) { console.error('获取中奖记录失败:', error); } }; if (loading) { return ; } const headerBg = scrollTop > 50 ? '#333' : 'transparent'; return ( {/* 导航 */} router.back()} style={styles.backBtn}> {TYPE_MAP[data.type]?.title || '详情'} setScrollTop(e.nativeEvent.contentOffset.y)} scrollEventThrottle={16} showsVerticalScrollIndicator={false} > {data.name} {TYPE_MAP[data.type]?.title} {data.description} {/* 中奖记录按钮 */} {data.prizeMode !== 1 && data.type !== 'EUROPEAN_GAS' && ( 中奖记录 )} {/* 赠品池 */} 赠品池 {data.luckRoomGoodsList?.length}件赠品 {data.luckRoomGoodsList?.map((item: any, index: number) => ( {item.spu.name} 数量:{item.quantity} ))} {/* 参与度 */} 参与度 {data.participatingList?.length}个玩家 {data.participatingList?.map((user: any, index: number) => ( {user.nickname} ))} {/* 底部按钮栏 */} {data.status === 1 && ( 倒计时: {formatLeftTime()} )} {data.status !== 1 ? '已开奖' : data.myParticipatedFlag === 1 ? ( data.participateMode === 1 && data.myAuditStatus === 0 ? '待审核' : data.participateMode === 1 && data.myAuditStatus === 1 ? '审核不通过' : '等待开赏' ) : '加入房间,即可参与'} {/* 口令弹窗 */} 请输入房间口令 setJoinVisible(false)}> 取消 确认加入 {/* 中奖记录弹窗 */} 中奖记录 setWinVisible(false)} style={styles.winClose}> × {winRecords.length === 0 ? ( 暂无记录 ) : winRecords.map((item: any, index: number) => ( {item.nickname} 获得了 {item.spu.name} ))} ); } const styles = StyleSheet.create({ container: { flex: 1 }, background: { flex: 1 }, loading: { flex: 1, backgroundColor: '#1a1a2e', justifyContent: 'center', alignItems: 'center' }, nav: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 15, height: 90, zIndex: 100 }, backBtn: { width: 40 }, backText: { color: '#fff', fontSize: 24 }, navTitle: { color: '#fff', fontSize: 16, fontWeight: 'bold' }, placeholder: { width: 40 }, scrollView: { flex: 1 }, headerBg: { width: '100%', height: 180, position: 'absolute', top: 0 }, content: { paddingHorizontal: 15, marginTop: 90 }, roomInfo: { alignItems: 'center', marginBottom: 20 }, roomName: { color: '#fff', fontSize: 22, fontWeight: 'bold', textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 2 }, roomType: { marginTop: 8, paddingVertical: 4, paddingHorizontal: 12, backgroundColor: 'rgba(255,255,255,0.2)', borderRadius: 10 }, roomTypeText: { color: '#fff', fontSize: 12 }, roomDesc: { marginTop: 10, color: '#BEBBB3', fontSize: 12 }, recordBtn: { position: 'absolute', right: 0, top: 0, zIndex: 10 }, recordBtnBg: { width: 78, height: 26, justifyContent: 'center', alignItems: 'center', flexDirection: 'row' }, recordIcon: { width: 16, height: 16, marginRight: 2 }, recordBtnText: { color: '#fff', fontSize: 12, fontWeight: 'bold', textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1 }, goodsCard: { marginTop: 25, backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 15, padding: 15 }, cardHeader: { flexDirection: 'row', alignItems: 'center', marginBottom: 15 }, cardTitle: { color: '#fff', fontSize: 18, fontWeight: 'bold' }, cardNum: { color: '#eee', fontSize: 12, marginLeft: 10 }, goodsList: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between' }, goodsItem: { width: '31%', aspectRatio: 0.8, backgroundColor: 'rgba(0,0,0,0.3)', borderRadius: 10, padding: 8, marginBottom: 10, alignItems: 'center' }, goodsImg: { width: '80%', height: '60%' }, goodsName: { color: '#fff', fontSize: 10, marginTop: 5 }, goodsCountTag: { position: 'absolute', left: 0, bottom: 25, backgroundColor: '#FFDD00', paddingHorizontal: 5, borderTopRightRadius: 5, borderBottomRightRadius: 5 }, goodsCountText: { color: '#000', fontSize: 8, fontWeight: 'bold' }, participantSection: { marginTop: 20, backgroundColor: 'rgba(255,255,255,0.1)', borderRadius: 15, padding: 15 }, userList: { flexDirection: 'row' }, userItem: { alignItems: 'center', marginRight: 15, width: 50 }, userAvatar: { width: 40, height: 40, borderRadius: 20, borderWidth: 1, borderColor: '#fff' }, userName: { color: '#fff', fontSize: 8, marginTop: 5, width: '100%', textAlign: 'center' }, bottomBar: { position: 'absolute', left: 0, right: 0, bottom: 0, backgroundColor: 'rgba(0,0,0,0.8)', paddingHorizontal: 15, paddingTop: 10 }, timerRow: { flexDirection: 'row', alignItems: 'center', justifyContent: 'center', marginBottom: 10 }, timerLabel: { color: '#fff', fontSize: 12 }, timerValue: { color: '#fdf685', fontSize: 12, fontWeight: 'bold' }, joinBtn: { height: 45, borderRadius: 22.5, width: '100%', overflow: 'hidden' }, joinBtnDisabled: { backgroundColor: '#666' }, joinBtnBg: { width: '100%', height: '100%', justifyContent: 'center', alignItems: 'center' }, joinBtnText: { color: '#fff', fontSize: 14, fontWeight: 'bold' }, modalOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.6)', justifyContent: 'center', alignItems: 'center' }, modalContent: { width: '80%', backgroundColor: '#fff', borderRadius: 15, padding: 20, alignItems: 'center' }, modalTitle: { fontSize: 18, fontWeight: 'bold', marginBottom: 20 }, modalInput: { width: '100%', height: 45, backgroundColor: '#f5f5f5', borderRadius: 8, paddingHorizontal: 15, marginBottom: 20 }, modalBtns: { flexDirection: 'row', justifyContent: 'space-between', width: '100%' }, modalBtn: { flex: 0.45, height: 40, justifyContent: 'center', alignItems: 'center', borderRadius: 20, backgroundColor: '#eee' }, modalBtnConfirm: { backgroundColor: '#e79018' }, modalBtnText: { fontWeight: 'bold' }, winOverlay: { flex: 1, backgroundColor: 'rgba(0,0,0,0.5)', justifyContent: 'flex-end' }, winContent: { backgroundColor: '#fff', height: '60%', borderTopLeftRadius: 20, borderTopRightRadius: 20, padding: 20 }, winHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 }, winTitle: { fontSize: 18, fontWeight: 'bold' }, winClose: { width: 30, height: 30, backgroundColor: '#eee', borderRadius: 15, justifyContent: 'center', alignItems: 'center' }, winCloseText: { fontSize: 20, color: '#999' }, winList: { flex: 1 }, winItem: { flexDirection: 'row', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#f5f5f5' }, winAvatar: { width: 30, height: 30, borderRadius: 15 }, winUser: { marginLeft: 10, fontSize: 12, width: 60 }, winGot: { fontSize: 12, color: '#999', marginHorizontal: 5 }, winGoods: { flex: 1, fontSize: 12 }, winGoodsImg: { width: 30, height: 30, marginLeft: 10 }, empty: { alignItems: 'center', padding: 30 }, });