169 lines
4.7 KiB
TypeScript
169 lines
4.7 KiB
TypeScript
import { useState } from 'react'
|
||
import {
|
||
View,
|
||
Text,
|
||
StyleSheet,
|
||
ScrollView,
|
||
Dimensions,
|
||
Pressable,
|
||
} from 'react-native'
|
||
import { Image } from 'expo-image'
|
||
import { useRouter } from 'expo-router'
|
||
|
||
import { WhiteStarIcon } from '@/components/icon'
|
||
|
||
const { width: screenWidth } = Dimensions.get('window')
|
||
|
||
interface SearchResultItem {
|
||
id: number
|
||
title: string
|
||
image: any
|
||
height: number
|
||
videoUrl?: any
|
||
thumbnailUrl?: any
|
||
duration?: string
|
||
}
|
||
|
||
interface SearchResultsGridProps {
|
||
results: SearchResultItem[]
|
||
}
|
||
|
||
export default function SearchResultsGrid({ results }: SearchResultsGridProps) {
|
||
const router = useRouter()
|
||
const [gridWidth, setGridWidth] = useState(screenWidth)
|
||
|
||
const horizontalPadding = 8 * 2 // gridContainer 的左右 padding
|
||
const cardGap = 5 // 两个卡片之间的间距
|
||
const cardWidth = (gridWidth - horizontalPadding - cardGap) / 2
|
||
|
||
const handleSameStylePress = (item: SearchResultItem) => {
|
||
// 构建模板数据,传递给 generateVideo 页面
|
||
const templateData = {
|
||
id: item.id,
|
||
videoUrl: item.videoUrl || item.image, // 如果没有 videoUrl,使用 image
|
||
thumbnailUrl: item.thumbnailUrl || item.image, // 如果没有 thumbnailUrl,使用 image
|
||
title: item.title,
|
||
duration: item.duration || '00:00', // 默认时长
|
||
}
|
||
router.push({
|
||
pathname: '/generateVideo' as any,
|
||
params: {
|
||
template: JSON.stringify(templateData),
|
||
},
|
||
} as any)
|
||
}
|
||
|
||
return (
|
||
<ScrollView
|
||
style={styles.scrollView}
|
||
contentContainerStyle={styles.scrollContent}
|
||
showsVerticalScrollIndicator={false}
|
||
>
|
||
<View
|
||
style={styles.gridContainer}
|
||
onLayout={(event) => {
|
||
const { width } = event.nativeEvent.layout
|
||
setGridWidth(width)
|
||
}}
|
||
>
|
||
{results.map((item, index) => (
|
||
<View
|
||
key={item.id}
|
||
style={[
|
||
styles.card,
|
||
{ width: cardWidth },
|
||
index % 2 === 0 ? styles.cardLeft : styles.cardRight,
|
||
]}
|
||
>
|
||
<View
|
||
style={[
|
||
styles.cardImageContainer,
|
||
{ height: item.height },
|
||
]}
|
||
>
|
||
<Image
|
||
source={item.image}
|
||
style={styles.cardImage}
|
||
contentFit="cover"
|
||
/>
|
||
</View>
|
||
<Text style={styles.cardTitle} numberOfLines={1}>
|
||
{item.title}
|
||
</Text>
|
||
<Pressable
|
||
style={styles.sameStyleButton}
|
||
onPress={() => handleSameStylePress(item)}
|
||
>
|
||
<WhiteStarIcon />
|
||
<Text style={styles.sameStyleText}>做同款</Text>
|
||
</Pressable>
|
||
</View>
|
||
))}
|
||
</View>
|
||
</ScrollView>
|
||
)
|
||
}
|
||
|
||
const styles = StyleSheet.create({
|
||
scrollView: {
|
||
flex: 1,
|
||
},
|
||
scrollContent: {
|
||
paddingBottom: 100,
|
||
},
|
||
gridContainer: {
|
||
flexDirection: 'row',
|
||
flexWrap: 'wrap',
|
||
paddingHorizontal: 8,
|
||
justifyContent: 'space-between',
|
||
},
|
||
card: {
|
||
backgroundColor: '#16181B',
|
||
borderBottomLeftRadius: 12,
|
||
borderBottomRightRadius: 12,
|
||
marginBottom: 12,
|
||
},
|
||
cardLeft: {
|
||
marginRight: 0,
|
||
},
|
||
cardRight: {
|
||
marginLeft: 0,
|
||
},
|
||
cardImageContainer: {
|
||
width: '100%',
|
||
borderRadius: 12,
|
||
overflow: 'hidden',
|
||
marginBottom: 8,
|
||
position: 'relative',
|
||
},
|
||
cardImage: {
|
||
width: '100%',
|
||
height: '100%',
|
||
},
|
||
sameStyleButton: {
|
||
flexDirection: 'row',
|
||
alignItems: 'center',
|
||
gap: 4,
|
||
backgroundColor: '#262A31',
|
||
height:32,
|
||
marginHorizontal: 8,
|
||
marginTop: 10,
|
||
marginBottom: 8,
|
||
borderRadius: 100,
|
||
justifyContent: 'center',
|
||
},
|
||
sameStyleText: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12,
|
||
fontWeight: '500',
|
||
lineHeight: 17,
|
||
},
|
||
cardTitle: {
|
||
color: '#FFFFFF',
|
||
fontSize: 12,
|
||
fontWeight: '500',
|
||
paddingHorizontal: 8,
|
||
},
|
||
})
|
||
|