Files
frontend/src/components/business/PostCard/PostCardGrid.tsx

115 lines
2.8 KiB
TypeScript
Raw Normal View History

/**
* PostCardGrid
*
*/
import React from 'react';
import { TouchableOpacity, StyleSheet, StyleProp, ViewStyle, GestureResponderEvent } from 'react-native';
import { colors, borderRadius } from '../../../theme';
import { useResponsive } from '../../../hooks/useResponsive';
import { PostCardGridProps } from './types';
import { usePostCardActions } from './hooks/usePostCardActions';
import { usePostGridStyles } from './hooks/usePostCardStyles';
import { PostGridCover, PostGridInfo } from './components';
import { convertToImageGridItems, getConsistentAspectRatio } from './utils';
const PostCardGrid: React.FC<PostCardGridProps> = ({
post,
onAction,
features,
style,
}) => {
const { isDesktop } = useResponsive();
const gridStyles = usePostGridStyles();
const {
handlePress,
handleUserPress,
handleImagePress,
} = usePostCardActions(onAction);
// 防御性检查:确保 author 存在
const author = post.author ?? {
id: '',
nickname: '匿名用户',
avatar: '',
username: '',
cover_url: '',
bio: '',
website: '',
location: '',
posts_count: 0,
followers_count: 0,
following_count: 0,
created_at: '',
};
// 获取封面图(第一张图)
const coverImage = post.images && post.images.length > 0 ? post.images[0] : null;
// 根据帖子 ID 生成一致的宽高比
const aspectRatio = getConsistentAspectRatio(post.id);
// 样式计算
const containerStyle: StyleProp<ViewStyle> = [
styles.container,
!coverImage && styles.containerNoImage,
isDesktop && styles.containerDesktop,
];
const handleContainerPress = () => {
handlePress();
};
const handleImagePressLocal = () => {
if (post.images && post.images.length > 0) {
handleImagePress(convertToImageGridItems(post.images), 0);
}
};
const handleUserPressLocal = () => {
handleUserPress();
};
return (
<TouchableOpacity
style={[containerStyle, style]}
onPress={handleContainerPress}
activeOpacity={0.9}
>
{/* 封面 */}
<PostGridCover
image={coverImage}
content={post.content}
isVote={post.is_vote}
aspectRatio={aspectRatio}
onImagePress={handleImagePressLocal}
/>
{/* 标题和信息 */}
<PostGridInfo
title={post.title}
author={author}
likesCount={post.likes_count}
onUserPress={handleUserPressLocal}
/>
</TouchableOpacity>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: '#FFF',
overflow: 'hidden',
borderRadius: 8,
},
containerDesktop: {
borderRadius: 12,
},
containerNoImage: {
minHeight: 200,
justifyContent: 'space-between',
},
});
export default PostCardGrid;