import React, { useEffect, useState, useCallback, useRef } from 'react'; import { View, Text, StyleSheet, ScrollView, Image, TouchableOpacity, SafeAreaView, StatusBar, ActivityIndicator, Dimensions, FlatList } from 'react-native'; import Ionicons from '@expo/vector-icons/Ionicons'; import { useNavigation, useRoute } from '@react-navigation/native'; import { NativeStackNavigationProp } from '@react-navigation/native-stack'; import { RouteProp } from '@react-navigation/native'; import { productApi, ProductDetailParams } from '../services/api/productApi'; import { useTranslation } from 'react-i18next'; // 获取屏幕宽度 const { width: screenWidth } = Dimensions.get('window'); // 图标组件 - 使用React.memo优化渲染 const IconComponent = React.memo(({ name, size, color }: { name: string; size: number; color: string }) => { const Icon = Ionicons as any; return ; }); // 路由参数类型 type ProductDetailRouteParams = { offer_id: string; searchKeyword?: string; price: number; }; // 颜色选项组件 const ColorOption = React.memo(({ color, selected, onSelect }: { color: string; selected: boolean; onSelect: () => void }) => ( {color} )); // 尺寸选项组件 const SizeOption = React.memo(({ size, selected, onSelect }: { size: string; selected: boolean; onSelect: () => void }) => ( {size} )); // 相关商品组件 const RelatedProductItem = React.memo(({ product, onPress }: { product: any; onPress: () => void }) => ( ${product.price} )); export const ProductDetailScreen = () => { const { t } = useTranslation(); const navigation = useNavigation>(); const route = useRoute, string>>(); const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [activeImageIndex, setActiveImageIndex] = useState(0); const [selectedColor, setSelectedColor] = useState('Black'); const [selectedSize, setSelectedSize] = useState('M'); const [relatedProducts, setRelatedProducts] = useState([ { id: 1, name: 'Related Product 1', price: 19.99, image: 'https://via.placeholder.com/150' }, { id: 2, name: 'Related Product 2', price: 24.99, image: 'https://via.placeholder.com/150' }, { id: 3, name: 'Related Product 3', price: 14.99, image: 'https://via.placeholder.com/150' }, { id: 4, name: 'Related Product 4', price: 34.99, image: 'https://via.placeholder.com/150' }, ]); const [page, setPage] = useState(1); const [loadingMore, setLoadingMore] = useState(false); const [hasMoreProducts, setHasMoreProducts] = useState(true); // 颜色和尺寸选项 const colorOptions = ['Black', 'White', 'Blue', 'Red']; const sizeOptions = ['S', 'M', 'L', 'XL', 'XXL']; // 获取产品详情 useEffect(() => { fetchProductDetails(); }, []); // 获取产品详情的API调用 const fetchProductDetails = async () => { if (!route.params?.offer_id) return; setLoading(true); try { const res = await productApi.getProductDetail(route.params.offer_id); res.price = route.params.price; setProduct(res); } catch (error) { console.error('Error fetching product details:', error); } finally { setLoading(false); } }; // 返回上一页 const goBack = useCallback(() => { navigation.goBack(); }, [navigation]); // 处理相关商品点击 const handleRelatedProductPress = useCallback((product: any) => { // 这里可以导航到对应的商品详情页 console.log('Navigate to related product:', product.id); }, []); // 处理添加到购物车 const handleAddToCart = useCallback(() => { // 添加到购物车的逻辑 console.log('Add to cart with color:', selectedColor, 'and size:', selectedSize); }, [selectedColor, selectedSize]); // 处理立即购买 const handleBuyNow = useCallback(() => { // 立即购买的逻辑 console.log('Buy now with color:', selectedColor, 'and size:', selectedSize); }, [selectedColor, selectedSize]); // 获取相关商品 const fetchRelatedProducts = useCallback(async (pageNumber = 1) => { if (!hasMoreProducts && pageNumber > 1) return; try { setLoadingMore(true); // 模拟网络请求延迟 await new Promise(resolve => setTimeout(resolve, 1000)); // 模拟新数据 const newProducts = Array(4).fill(0).map((_, index) => ({ id: pageNumber * 10 + index, name: `Related Product ${pageNumber * 10 + index}`, price: Number((Math.random() * 30 + 10).toFixed(2)), image: 'https://via.placeholder.com/150' })); if (pageNumber === 1) { setRelatedProducts(newProducts); } else { setRelatedProducts(prev => [...prev, ...newProducts]); } // 模拟数据加载完毕的情况 if (pageNumber >= 3) { setHasMoreProducts(false); } else { setPage(pageNumber); } } catch (error) { console.error('Error fetching related products:', error); } finally { setLoadingMore(false); } }, [hasMoreProducts]); // 初始加载相关商品 useEffect(() => { fetchRelatedProducts(1); }, [fetchRelatedProducts]); // 处理滚动到底部加载更多 const handleLoadMore = useCallback(() => { if (!loadingMore && hasMoreProducts) { fetchRelatedProducts(page + 1); } }, [fetchRelatedProducts, loadingMore, hasMoreProducts, page]); if (loading) { return ( {t('productDetail')} {t('loadingProductInfo')} ); } if (!product) { return ( {t('productDetail')} {t('productNotAvailable')} ); } return ( {/* 头部导航 */} {t('productDetail')} { const { layoutMeasurement, contentOffset, contentSize } = nativeEvent; const paddingToBottom = 20; if (layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom) { handleLoadMore(); } }} scrollEventThrottle={400} > {/* 产品图片轮播 */} {product.product_image_urls && product.product_image_urls.length > 0 ? ( <> `image-${index}`} onScroll={(event) => { const slideSize = event.nativeEvent.layoutMeasurement.width; const index = Math.floor(event.nativeEvent.contentOffset.x / slideSize); setActiveImageIndex(index); }} scrollEventThrottle={16} renderItem={({ item }) => ( )} /> {/* 指示器 */} {product.product_image_urls.length > 1 && ( {product.product_image_urls.map((_, index) => ( ))} )} ) : ( {t('productDetail')} )} {/* 产品基本信息 */} ${product.price?.toFixed(2) || '29.99'} ${(product.price * 1.4).toFixed(2) || '49.99'} -40% VIP {product.subject || 'Product Name'} {t('monthlySales')} {product.sold_out || 2458} {/* 颜色选择 */} {t('color')} {colorOptions.map((color, index) => ( setSelectedColor(color)} /> ))} +2 {/* 尺寸选择 */} {t('size')} {sizeOptions.map((size, index) => ( setSelectedSize(size)} /> ))} {/* 相关商品 */} {t('moreFromStore')} {t('viewAll')} {relatedProducts.map((product, index) => ( handleRelatedProductPress(product)} /> ))} {loadingMore && ( {t('loadingMoreProducts')} )} {!hasMoreProducts && relatedProducts.length > 0 && ( {t('noMoreProducts')} )} {/* 商品详情 */} {t('productDetails')} {t('productDetails')} 1 {t('productDetails')} 2 {t('productDetails')} 3 {/* 底部空间,确保内容不被底部操作栏遮挡 */} {/* 底部操作栏 */} {t('customerService')} {t('addToCart')} {t('buyNow')} ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#f5f5f5', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 15, paddingVertical: 10, backgroundColor: '#fff', borderBottomWidth: 1, borderBottomColor: '#f0f0f0', }, backButton: { padding: 5, }, headerTitle: { flex: 1, fontSize: 16, fontWeight: 'bold', color: '#333', textAlign: 'center', marginHorizontal: 10, }, headerRight: { flexDirection: 'row', alignItems: 'center', }, headerIconButton: { padding: 5, }, scrollContainer: { flex: 1, }, imageContainer: { height: 300, backgroundColor: '#f9f9f9', alignItems: 'center', justifyContent: 'center', position: 'relative', }, imagePlaceholder: { width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }, imagePlaceholderText: { fontSize: 16, color: '#999', }, paginationContainer: { position: 'absolute', bottom: 15, flexDirection: 'row', width: '100%', justifyContent: 'center', alignItems: 'center', }, paginationDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: 'rgba(255, 255, 255, 0.4)', marginHorizontal: 4, }, paginationDotActive: { backgroundColor: '#fff', width: 10, height: 10, borderRadius: 5, }, infoSection: { padding: 15, backgroundColor: '#fff', marginBottom: 10, }, priceContainer: { flexDirection: 'row', alignItems: 'center', marginBottom: 10, }, productPrice: { fontSize: 24, fontWeight: 'bold', color: '#ff6600', }, originalPrice: { fontSize: 16, color: '#999', textDecorationLine: 'line-through', marginLeft: 8, }, discountBadge: { backgroundColor: '#ff6600', paddingHorizontal: 6, paddingVertical: 2, borderRadius: 3, marginLeft: 8, }, discountText: { color: '#fff', fontSize: 12, fontWeight: 'bold', }, vipBadge: { backgroundColor: '#f1c40f', paddingHorizontal: 6, paddingVertical: 2, borderRadius: 3, marginLeft: 6, }, vipText: { color: '#fff', fontSize: 12, fontWeight: 'bold', }, productTitle: { fontSize: 16, color: '#333', marginBottom: 8, }, productSales: { fontSize: 12, color: '#999', marginBottom: 15, }, optionSection: { marginTop: 15, }, optionTitle: { fontSize: 14, fontWeight: 'bold', color: '#333', marginBottom: 10, }, colorOptions: { flexDirection: 'row', flexWrap: 'wrap', }, colorOption: { flexDirection: 'row', alignItems: 'center', paddingHorizontal: 10, paddingVertical: 6, borderRadius: 4, marginRight: 10, marginBottom: 10, borderWidth: 1, borderColor: '#e0e0e0', }, colorOptionSelected: { borderColor: '#ff6600', backgroundColor: '#fff8f5', }, colorCircle: { width: 16, height: 16, borderRadius: 8, marginRight: 6, }, colorName: { fontSize: 12, color: '#333', }, moreColorsButton: { width: 35, height: 35, borderRadius: 4, backgroundColor: '#f5f5f5', justifyContent: 'center', alignItems: 'center', marginRight: 10, marginBottom: 10, }, moreColorsText: { fontSize: 12, color: '#333', }, sizeOptions: { flexDirection: 'row', flexWrap: 'wrap', }, sizeOption: { paddingHorizontal: 15, paddingVertical: 6, borderRadius: 4, marginRight: 10, marginBottom: 10, borderWidth: 1, borderColor: '#e0e0e0', }, sizeOptionSelected: { borderColor: '#ff6600', backgroundColor: '#fff8f5', }, sizeText: { fontSize: 12, color: '#333', }, sizeTextSelected: { color: '#ff6600', fontWeight: 'bold', }, relatedProductsSection: { backgroundColor: '#fff', padding: 15, marginBottom: 10, }, sectionHeader: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15, }, sectionTitle: { fontSize: 16, fontWeight: 'bold', color: '#333', }, viewAllButton: { flexDirection: 'row', alignItems: 'center', }, viewAllText: { fontSize: 12, color: '#0066ff', }, relatedProductsContainer: { flexDirection: 'row', flexWrap: 'wrap', justifyContent: 'space-between', marginTop: 10, }, relatedProductItem: { width: screenWidth / 2 - 25, marginBottom: 15, }, relatedProductImage: { width: '100%', height: 120, borderRadius: 4, marginBottom: 5, }, relatedProductPrice: { fontSize: 14, fontWeight: 'bold', color: '#ff6600', }, loadMoreIndicator: { flexDirection: 'row', justifyContent: 'center', alignItems: 'center', paddingVertical: 10, }, loadMoreText: { fontSize: 12, color: '#666', marginLeft: 8, }, noMoreProductsText: { textAlign: 'center', fontSize: 12, color: '#999', paddingVertical: 10, }, detailsSection: { backgroundColor: '#fff', padding: 15, }, productDetails: { marginTop: 10, }, productDetailItem: { marginBottom: 10, }, productDetailImage: { width: '100%', height: 200, borderRadius: 4, }, detailPlaceholder: { width: '100%', height: 200, borderRadius: 4, backgroundColor: '#f0f0f0', justifyContent: 'center', alignItems: 'center', }, detailPlaceholderText: { fontSize: 16, color: '#999', }, bottomSpace: { height: 60, }, bottomBar: { position: 'absolute', bottom: 0, left: 0, right: 0, flexDirection: 'row', height: 60, backgroundColor: '#fff', borderTopWidth: 1, borderTopColor: '#f0f0f0', paddingHorizontal: 15, paddingVertical: 10, }, chatButton: { alignItems: 'center', justifyContent: 'center', marginRight: 15, }, chatButtonText: { fontSize: 10, color: '#666', marginTop: 2, }, addToCartButton: { flex: 1, flexDirection: 'row', justifyContent: 'center', alignItems: 'center', backgroundColor: '#ff9500', borderRadius: 25, marginRight: 10, }, addToCartText: { color: '#fff', fontWeight: 'bold', marginLeft: 5, }, buyNowButton: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: '#ff6600', borderRadius: 25, }, buyNowText: { color: '#fff', fontWeight: 'bold', }, loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', }, loadingText: { fontSize: 16, color: '#666', marginTop: 10, }, errorContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', padding: 20, }, errorText: { fontSize: 18, fontWeight: 'bold', color: '#333', marginTop: 15, marginBottom: 20, }, });