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'; // 获取屏幕宽度 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 ; }); // 产品类型定义 interface Product { id: string; title: string; price: number; image: string; currency: string; sales: number; description: string; specifications: Record; } // 路由参数类型 type ProductDetailRouteParams = { offer_id: string; searchKeyword?: string; price:number; }; export const ProductDetailScreen = () => { const navigation = useNavigation>(); const route = useRoute, string>>(); const [product, setProduct] = useState(null); const [loading, setLoading] = useState(true); const [activeImageIndex, setActiveImageIndex] = useState(0); // 获取产品详情 useEffect(() => { fetchProductDetails(); }, []); // 模拟获取产品详情的API调用 const fetchProductDetails = async () => { if (!route.params?.offer_id) return; setLoading(true); try { const res = await productApi.getProductDetail(route.params.offer_id); console.log(res); res.price = route.params.price; // 模拟返回的数据 const searchKeyword = route.params.searchKeyword || 'Product'; console.log(searchKeyword); setProduct(res); } catch (error) { console.error('Error fetching product details:', error); // 在实际应用中应该显示错误消息 } finally { setLoading(false); } }; // 返回上一页 const goBack = useCallback(() => { navigation.goBack(); }, [navigation]); // 返回到搜索结果页 const goBackToSearch = useCallback(() => { if (route.params?.searchKeyword) { navigation.navigate('SearchResult', { keyword: route.params.searchKeyword }); } else { navigation.goBack(); } }, [navigation, route.params?.searchKeyword]); if (loading) { return ( Product Details Loading product details... ); } if (!product) { return ( Product Details Product not found Back to Search Results ); } return ( {/* 头部导航 */} {product.subject} {/* 产品图片轮播 */} {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) => ( ))} )} ) : ( Product Image )} {/* 产品基本信息 */} {product.subject} {product.price} {product.subject_trans} {/* 如果是从搜索结果跳转来的,显示匹配的关键词 */} {route.params?.searchKeyword && ( Matched Search: {route.params.searchKeyword} )} {/* 产品描述 */} {/* Description {product.description} */} {/* 产品规格 */} {/* Specifications {Object.entries(product.specifications).map(([key, value], index) => ( {key} {value} ))} */} {/* 返回搜索结果按钮 */} Back to Search Results {/* 底部空间,确保内容不被底部操作栏遮挡 */} {/* 底部操作栏 */} Add to Cart Buy Now ); }; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', }, header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', paddingHorizontal: 15, paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#f0f0f0', backgroundColor: '#fff', }, backButton: { padding: 5, }, headerTitle: { flex: 1, fontSize: 16, fontWeight: 'bold', color: '#333', textAlign: 'center', marginHorizontal: 10, }, headerRight: { width: 24, }, scrollContainer: { flex: 1, }, imageContainer: { height: 300, backgroundColor: '#f9f9f9', alignItems: 'center', justifyContent: 'center', position: 'relative', }, productImage: { width: '100%', height: '100%', }, imagePlaceholder: { width: '100%', height: '100%', alignItems: 'center', justifyContent: 'center', }, imagePlaceholderText: { fontSize: 16, color: '#999', }, infoSection: { padding: 15, borderBottomWidth: 8, borderBottomColor: '#f5f5f5', }, productTitle: { fontSize: 18, fontWeight: 'bold', color: '#333', marginBottom: 10, }, productPrice: { fontSize: 24, fontWeight: 'bold', color: '#ff6600', marginBottom: 5, }, productSales: { fontSize: 14, color: '#999', marginBottom: 10, }, keywordContainer: { flexDirection: 'row', alignItems: 'center', backgroundColor: '#f0f8ff', paddingVertical: 5, paddingHorizontal: 10, borderRadius: 5, marginTop: 5, }, keywordLabel: { fontSize: 14, color: '#666', }, keywordValue: { fontSize: 14, fontWeight: 'bold', color: '#0066ff', }, section: { padding: 15, borderBottomWidth: 8, borderBottomColor: '#f5f5f5', }, sectionTitle: { fontSize: 16, fontWeight: 'bold', color: '#333', marginBottom: 10, }, descriptionText: { fontSize: 14, color: '#666', lineHeight: 20, }, specRow: { flexDirection: 'row', paddingVertical: 8, borderBottomWidth: 1, borderBottomColor: '#f0f0f0', }, specKey: { flex: 1, fontSize: 14, color: '#666', }, specValue: { flex: 2, fontSize: 14, color: '#333', }, backToSearchButton: { alignItems: 'center', paddingVertical: 15, margin: 15, }, backToSearchText: { fontSize: 14, color: '#0066ff', }, 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, }, 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, }, paginationContainer: { position: 'absolute', bottom: 15, flexDirection: 'row', width: '100%', justifyContent: 'center', alignItems: 'center', }, paginationDot: { width: 8, height: 8, borderRadius: 4, backgroundColor: 'rgba(0, 0, 0, 0.2)', marginHorizontal: 4, }, paginationDotActive: { backgroundColor: '#ff6600', width: 10, height: 10, borderRadius: 5, }, });