| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191 |
- import { Image } from 'expo-image';
- import { useRouter } from 'expo-router';
- import React, { useCallback, useEffect, useState } from 'react';
- import {
- ActivityIndicator,
- ImageBackground,
- RefreshControl,
- ScrollView,
- StatusBar,
- StyleSheet,
- Text,
- TouchableOpacity,
- View,
- } from 'react-native';
- import { useSafeAreaInsets } from 'react-native-safe-area-context';
- import { Images } from '@/constants/images';
- import { getWealRecord } from '@/services/dimension';
- interface RecordItem {
- id: string;
- name: string;
- type: string;
- goodsQuantity: number;
- officialFlag: number;
- leftTime: number;
- user: { avatar: string; username: string };
- luckRoomGoodsList: { spu: { cover: string } }[];
- participatingList: any[];
- }
- export default function WealRecordScreen() {
- const router = useRouter();
- const insets = useSafeAreaInsets();
- const [loading, setLoading] = useState(true);
- const [refreshing, setRefreshing] = useState(false);
- const [list, setList] = useState<RecordItem[]>([]);
- const [pageNum, setPageNum] = useState(1);
- const [hasMore, setHasMore] = useState(true);
- const loadData = useCallback(async (isRefresh = false) => {
- if (isRefresh) {
- setRefreshing(true);
- setPageNum(1);
- } else {
- setLoading(true);
- }
- try {
- const page = isRefresh ? 1 : pageNum;
- const data = await getWealRecord(page, 10);
- if (data) {
- if (page === 1) {
- setList(data);
- } else {
- setList(prev => [...prev, ...data]);
- }
- setHasMore(data.length === 10);
- }
- } catch (error) {
- console.error('加载记录失败:', error);
- }
- setLoading(false);
- setRefreshing(false);
- }, [pageNum]);
- useEffect(() => {
- loadData();
- }, [loadData]);
- const handleLoadMore = () => {
- if (!hasMore || loading || refreshing) return;
- setPageNum(prev => prev + 1);
- };
- const isItemType = (type: string) => {
- const map: Record<string, string> = {
- COMMON: '福利房',
- PASSWORD: '口令房',
- EUROPEAN_GAS: '欧气房',
- ACHIEVEMENT: '成就房',
- };
- return map[type] || type;
- };
- return (
- <View style={styles.container}>
- <StatusBar barStyle="light-content" />
- <ImageBackground source={{ uri: Images.common.commonBg }} style={styles.background} resizeMode="cover">
- {/* 导航 */}
- <View style={[styles.nav, { paddingTop: insets.top }]}>
- <TouchableOpacity onPress={() => router.back()} style={styles.backBtn}>
- <Text style={styles.backText}>←</Text>
- </TouchableOpacity>
- <Text style={styles.navTitle}>参与记录</Text>
- <View style={styles.placeholder} />
- </View>
- <ScrollView
- style={styles.scrollView}
- refreshControl={<RefreshControl refreshing={refreshing} onRefresh={() => loadData(true)} tintColor="#fff" />}
- onScroll={({ nativeEvent }) => {
- const { layoutMeasurement, contentOffset, contentSize } = nativeEvent;
- if (layoutMeasurement.height + contentOffset.y >= contentSize.height - 20) {
- handleLoadMore();
- }
- }}
- scrollEventThrottle={400}
- >
- <View style={{ height: 20 }} />
- <View style={styles.list}>
- {list.length === 0 && !loading ? (
- <View style={styles.empty}><Text style={styles.emptyText}>暂无记录</Text></View>
- ) : list.map((item, index) => (
- <TouchableOpacity
- key={index}
- style={[styles.itemWrapper, item.leftTime < 1 && styles.grayscale]}
- activeOpacity={0.8}
- onPress={() => router.push({ pathname: '/dimension/detail', params: { id: item.id } } as any)}
- >
- <ImageBackground source={{ uri: Images.welfare.roomItemBg }} style={styles.item} resizeMode="stretch">
- {item.officialFlag === 1 && (
- <View style={styles.officialBadge}>
- <Image source={{ uri: Images.welfare.official }} style={styles.officialImg} contentFit="contain" />
- </View>
- )}
- <ImageBackground source={{ uri: Images.welfare.roomItemImgBg }} style={styles.roomCover} resizeMode="contain">
- <Image source={{ uri: item.luckRoomGoodsList[0]?.spu?.cover }} style={styles.roomCoverImg} contentFit="cover" />
- </ImageBackground>
- <View style={styles.roomInfo}>
- <View style={styles.roomTop}>
- <Text style={styles.roomName} numberOfLines={1}>{item.name}</Text>
- <Text style={styles.roomTypeLabel}>{isItemType(item.type)}</Text>
- </View>
- <View style={styles.roomBottom}>
- <View style={styles.userInfo}>
- <Image source={{ uri: item.user.avatar }} style={styles.userAvatar} />
- <Text style={styles.userName} numberOfLines={1}>{item.user.username}</Text>
- </View>
- <Text style={styles.goodsNum}>共{item.goodsQuantity}件赠品</Text>
- <View style={styles.participantBox}>
- <Image source={{ uri: Images.welfare.participationIcon }} style={styles.participantIcon} />
- <Text style={styles.participantNum}>{item.participatingList.length}</Text>
- </View>
- </View>
- </View>
- </ImageBackground>
- </TouchableOpacity>
- ))}
- </View>
- {loading && <ActivityIndicator color="#fff" style={{ marginVertical: 20 }} />}
- <View style={{ height: 100 }} />
- </ScrollView>
- </ImageBackground>
- </View>
- );
- }
- const styles = StyleSheet.create({
- container: { flex: 1, backgroundColor: '#1a1a2e' },
- background: { flex: 1 },
- nav: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 15, height: 90 },
- backBtn: { width: 40 },
- backText: { color: '#fff', fontSize: 24 },
- navTitle: { color: '#fff', fontSize: 16, fontWeight: 'bold' },
- placeholder: { width: 40 },
- scrollView: { flex: 1 },
- list: { paddingHorizontal: 15 },
- itemWrapper: { marginBottom: 6 },
- grayscale: { opacity: 0.6 }, // 模拟原项目的置灰效果
- item: { width: '100%', height: 84, flexDirection: 'row', alignItems: 'center', paddingHorizontal: 16 },
- officialBadge: { position: 'absolute', right: 0, top: 0, width: 48, height: 22 },
- officialImg: { width: '100%', height: '100%' },
- roomCover: { width: 58, height: 58, justifyContent: 'center', alignItems: 'center', marginRight: 14 },
- roomCoverImg: { width: 44, height: 44 },
- roomInfo: { flex: 1 },
- roomTop: { flexDirection: 'row', alignItems: 'center', marginBottom: 10 },
- roomName: { flex: 1, color: '#fff', fontSize: 14, textShadowColor: '#000', textShadowOffset: { width: 1, height: 1 }, textShadowRadius: 1 },
- roomTypeLabel: { color: '#2E0000', fontSize: 12 },
- roomBottom: { flexDirection: 'row', alignItems: 'center' },
- userInfo: { flexDirection: 'row', alignItems: 'center', width: '45%' },
- userAvatar: { width: 24, height: 24, borderRadius: 2, backgroundColor: '#FFDD00', borderWidth: 1.5, borderColor: '#000', marginRight: 5 },
- userName: { color: '#2E0000', fontSize: 12, fontWeight: 'bold', maxWidth: 60 },
- goodsNum: { color: '#2E0000', fontSize: 10, width: '35%' },
- participantBox: { flexDirection: 'row', alignItems: 'center', width: '20%' },
- participantIcon: { width: 14, height: 14 },
- participantNum: { color: '#2E0000', fontSize: 12, marginLeft: 3 },
- empty: { alignItems: 'center', marginTop: 100 },
- emptyText: { color: '#999', fontSize: 14 },
- });
|