import { useState } from 'react' import { View, Text, StyleSheet, ScrollView, Dimensions, Pressable, ActivityIndicator, } from 'react-native' import { Image } from 'expo-image' import { useRouter } from 'expo-router' import { useTranslation } from 'react-i18next' import { WhiteStarIcon } from '@/components/icon' import type { TemplateDetail } from '@/hooks' const { width: screenWidth } = Dimensions.get('window') interface TemplateSearchResultItem { id: string title: string image: string | { uri: string } previewUrl?: string coverImageUrl?: string aspectRatio?: number height?: number } interface SearchResultsGridProps { results: TemplateSearchResultItem[] loading?: boolean onEndReached?: () => void ListFooterComponent?: React.ReactElement | null } // 计算卡片高度的辅助函数 const calculateCardHeight = (width: number, aspectRatio?: number): number => { if (aspectRatio) { return width / aspectRatio } // 默认宽高比 return width * 1.2 } export default function SearchResultsGrid({ results, loading, onEndReached, ListFooterComponent }: SearchResultsGridProps) { const { t } = useTranslation() const router = useRouter() const [gridWidth, setGridWidth] = useState(screenWidth) const horizontalPadding = 8 * 2 const cardGap = 5 const cardWidth = (gridWidth - horizontalPadding - cardGap) / 2 const handleCardPress = (item: TemplateSearchResultItem) => { router.push({ pathname: '/templateDetail' as any, params: { id: item.id.toString() }, }) } const handleScroll = (event: any) => { const { layoutMeasurement, contentOffset, contentSize } = event.nativeEvent const paddingToBottom = 20 if (layoutMeasurement.height + contentOffset.y >= contentSize.height - paddingToBottom) { onEndReached?.() } } if (loading) { return ( ) } if (results.length === 0) { return ( {t('searchResults.noResults')} ) } return ( { const { width } = event.nativeEvent.layout setGridWidth(width) }} > {results.map((item, index) => { const height = item.height || calculateCardHeight(cardWidth, item.aspectRatio) return ( handleCardPress(item)} > {item.title} ) })} {ListFooterComponent} ) } const styles = StyleSheet.create({ loadingContainer: { flex: 1, justifyContent: 'center', alignItems: 'center', paddingVertical: 40, }, scrollView: { flex: 1, }, gridContainer: { flexDirection: 'row', flexWrap: 'wrap', paddingHorizontal: 8, justifyContent: 'space-between', }, card: { backgroundColor: '#16181B', borderBottomLeftRadius: 12, borderBottomRightRadius: 12, marginBottom: 12, overflow: 'hidden', }, cardLeft: { marginRight: 0, }, cardRight: { marginLeft: 0, }, cardImageContainer: { width: '100%', borderRadius: 12, overflow: 'hidden', marginBottom: 8, position: 'relative', }, cardImage: { width: '100%', height: '100%', }, cardTitle: { position: 'absolute', bottom: 8, left: 8, color: '#FFFFFF', fontSize: 12, fontWeight: '500', }, emptyContainer: { flex: 1, backgroundColor: '#090A0B', justifyContent: 'center', alignItems: 'center', paddingVertical: 60, }, emptyText: { color: '#8A8A8A', fontSize: 14, }, })