From 82e99d24d87adac370768e07719ed58aa88f9d8b Mon Sep 17 00:00:00 2001 From: lan Date: Tue, 24 Mar 2026 03:02:54 +0800 Subject: [PATCH] Remove unnecessary console logs and replace them with void expressions for better performance and cleaner code. Update error logging to use console.error for consistency. This change enhances code readability and reduces console noise during execution. --- package-lock.json | 4 +- .../{PostCard.tsx => PostCard.legacy.tsx} | 0 src/components/business/PostCard/PostCard.tsx | 74 +++++ .../business/PostCard/PostCardGrid.tsx | 115 +++++++ .../PostCard/components/PostImages.tsx | 53 ++++ .../business/PostCard/components/index.ts | 12 + .../business/PostCard/hooks/index.ts | 8 + src/components/business/PostCard/index.ts | 58 ++++ src/components/business/PostCard/types.ts | 285 ++++++++++++++++++ src/components/business/index.ts | 14 + src/screens/home/HomeScreen.tsx | 47 ++- src/screens/profile/ProfileScreen.tsx | 40 ++- src/screens/profile/UserScreen.tsx | 50 ++- 13 files changed, 728 insertions(+), 32 deletions(-) rename src/components/business/{PostCard.tsx => PostCard.legacy.tsx} (100%) create mode 100644 src/components/business/PostCard/PostCard.tsx create mode 100644 src/components/business/PostCard/PostCardGrid.tsx create mode 100644 src/components/business/PostCard/components/PostImages.tsx create mode 100644 src/components/business/PostCard/components/index.ts create mode 100644 src/components/business/PostCard/hooks/index.ts create mode 100644 src/components/business/PostCard/index.ts create mode 100644 src/components/business/PostCard/types.ts diff --git a/package-lock.json b/package-lock.json index 586d224..507e99e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "carrot_bbs", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "carrot_bbs", - "version": "1.0.0", + "version": "1.0.1", "dependencies": { "@expo/vector-icons": "^15.1.1", "@react-native-async-storage/async-storage": "^2.2.0", diff --git a/src/components/business/PostCard.tsx b/src/components/business/PostCard.legacy.tsx similarity index 100% rename from src/components/business/PostCard.tsx rename to src/components/business/PostCard.legacy.tsx diff --git a/src/components/business/PostCard/PostCard.tsx b/src/components/business/PostCard/PostCard.tsx new file mode 100644 index 0000000..6cc61f9 --- /dev/null +++ b/src/components/business/PostCard/PostCard.tsx @@ -0,0 +1,74 @@ +/** + * PostCard 主组件 + * 帖子卡片组件 - 支持列表模式和网格模式 + * + * @example + * // 新 API 使用方式 + * handleAction(post, action)} + * variant="list" + * features="full" + * /> + */ + +import React from 'react'; +import { PostCardProps, LegacyPostCardProps } from './types'; +import PostCardList from './PostCardList'; +import PostCardGrid from './PostCardGrid'; +import { usePostCardFeatures } from './hooks/usePostCardFeatures'; +import { createLegacyAdapter, isLegacyProps } from './legacyAdapter'; + +/** + * PostCard 主组件 + * 支持新旧两种 API + */ +const PostCard: React.FC = (props) => { + // 检测是否使用旧 API + const isLegacy = isLegacyProps(props as LegacyPostCardProps); + + // 兼容层:转换旧 Props 到新 Props + const normalizedProps: PostCardProps = isLegacy + ? createLegacyAdapter(props as LegacyPostCardProps) + : (props as PostCardProps); + + const { + post, + onAction, + variant = 'list', + features: featuresConfig, + isPostAuthor = false, + isAuthor = false, + index, + style, + } = normalizedProps; + + // 解析 Features 配置 + const resolvedFeatures = usePostCardFeatures(featuresConfig); + + // 根据 variant 选择渲染模式 + if (variant === 'grid') { + return ( + + ); + } + + return ( + + ); +}; + +export default PostCard; \ No newline at end of file diff --git a/src/components/business/PostCard/PostCardGrid.tsx b/src/components/business/PostCard/PostCardGrid.tsx new file mode 100644 index 0000000..93306d2 --- /dev/null +++ b/src/components/business/PostCard/PostCardGrid.tsx @@ -0,0 +1,115 @@ +/** + * 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 = ({ + 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 = [ + 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 ( + + {/* 封面 */} + + + {/* 标题和信息 */} + + + ); +}; + +const styles = StyleSheet.create({ + container: { + backgroundColor: '#FFF', + overflow: 'hidden', + borderRadius: 8, + }, + containerDesktop: { + borderRadius: 12, + }, + containerNoImage: { + minHeight: 200, + justifyContent: 'space-between', + }, +}); + +export default PostCardGrid; \ No newline at end of file diff --git a/src/components/business/PostCard/components/PostImages.tsx b/src/components/business/PostCard/components/PostImages.tsx new file mode 100644 index 0000000..8a4ee81 --- /dev/null +++ b/src/components/business/PostCard/components/PostImages.tsx @@ -0,0 +1,53 @@ +/** + * PostImages 子组件 + * 显示帖子图片网格 + */ + +import React from 'react'; +import { View, StyleSheet } from 'react-native'; +import { colors, spacing, borderRadius } from '../../../../theme'; +import { useResponsive } from '../../../../hooks/useResponsive'; +import { ImageGrid, ImageGridItem } from '../../../common'; +import { PostImagesProps } from '../types'; + +const PostImages: React.FC = ({ images, displayMode, onImagePress }) => { + const { isDesktop, isWideScreen } = useResponsive(); + + if (!images || images.length === 0) return null; + + // 计算图片间距和圆角 + const imageGap = isDesktop ? 12 : 8; + const imageBorderRadius = isDesktop ? borderRadius.xl : borderRadius.md; + + return ( + + ({ + id: img.id, + url: img.url, + thumbnail_url: img.thumbnail_url, + preview_url: img.preview_url, + preview_url_large: img.preview_url_large, + width: img.width, + height: img.height, + }))} + maxDisplayCount={isWideScreen ? 12 : 9} + mode="auto" + gap={imageGap} + borderRadius={imageBorderRadius} + showMoreOverlay={true} + onImagePress={onImagePress} + displayMode={displayMode} + usePreview={true} + /> + + ); +}; + +const styles = StyleSheet.create({ + container: { + marginBottom: spacing.md, + }, +}); + +export default PostImages; \ No newline at end of file diff --git a/src/components/business/PostCard/components/index.ts b/src/components/business/PostCard/components/index.ts new file mode 100644 index 0000000..98f9fc3 --- /dev/null +++ b/src/components/business/PostCard/components/index.ts @@ -0,0 +1,12 @@ +/** + * PostCard 子组件导出 + */ + +export { default as PostHeader } from './PostHeader'; +export { default as PostTitle } from './PostTitle'; +export { default as PostContent } from './PostContent'; +export { default as PostImages } from './PostImages'; +export { default as PostActions } from './PostActions'; +export { default as PostTopComment } from './PostTopComment'; +export { default as PostGridCover } from './PostGridCover'; +export { default as PostGridInfo } from './PostGridInfo'; \ No newline at end of file diff --git a/src/components/business/PostCard/hooks/index.ts b/src/components/business/PostCard/hooks/index.ts new file mode 100644 index 0000000..0025b4e --- /dev/null +++ b/src/components/business/PostCard/hooks/index.ts @@ -0,0 +1,8 @@ +/** + * PostCard Hooks 导出 + */ + +export { usePostCardActions } from './usePostCardActions'; +export { usePostCardFeatures } from './usePostCardFeatures'; +export { usePostCardStyles, usePostGridStyles } from './usePostCardStyles'; +export type { PostCardStylesConfig, PostGridStylesConfig } from './usePostCardStyles'; diff --git a/src/components/business/PostCard/index.ts b/src/components/business/PostCard/index.ts new file mode 100644 index 0000000..b85d14e --- /dev/null +++ b/src/components/business/PostCard/index.ts @@ -0,0 +1,58 @@ +/** + * PostCard 组件模块导出 + */ + +// 主组件(默认导出) +export { default } from './PostCard'; + +// 类型导出 +export type { + PostCardActionType, + PostCardActionPayload, + PostCardAction, + PostCardOnAction, + PostCardFeatures, + PostCardFeaturesPreset, + PostCardFeaturesConfig, + PostCardProps, + PostHeaderProps, + PostTitleProps, + PostContentProps, + PostImagesProps, + PostActionsProps, + PostVotePreviewProps, + PostTopCommentProps, + PostGridCoverProps, + PostGridInfoProps, + PostCardListProps, + PostCardGridProps, + LegacyPostCardProps, + Badge, +} from './types'; + +// 预设配置导出 +export { PostCardPresets, defaultFeatures, resolveFeatures } from './presets'; + +// Hooks 导出 +export { + usePostCardActions, + usePostCardFeatures, + usePostCardStyles, + usePostGridStyles, +} from './hooks'; +export type { PostCardStylesConfig, PostGridStylesConfig } from './hooks'; + +// 子组件导出 +export { + PostHeader, + PostTitle, + PostContent, + PostImages, + PostActions, + PostTopComment, + PostGridCover, + PostGridInfo, +} from './components'; + +// 兼容层导出(用于迁移帮助) +export { isLegacyProps, createLegacyAdapter } from './legacyAdapter'; \ No newline at end of file diff --git a/src/components/business/PostCard/types.ts b/src/components/business/PostCard/types.ts new file mode 100644 index 0000000..510edb0 --- /dev/null +++ b/src/components/business/PostCard/types.ts @@ -0,0 +1,285 @@ +/** + * PostCard 组件类型定义 + * 统一的帖子卡片组件类型系统 + */ + +import { StyleProp, ViewStyle } from 'react-native'; +import { Post, PostImageDTO, UserDTO, CommentDTO } from '../../../types'; +import { ImageGridItem } from '../../common'; + +// ==================== Action 类型定义 ==================== + +/** + * PostCard 支持的操作类型 + */ +export type PostCardActionType = + | 'press' // 点击帖子主体 + | 'userPress' // 点击用户头像/名称 + | 'like' // 点赞 + | 'unlike' // 取消点赞 + | 'comment' // 评论 + | 'bookmark' // 收藏 + | 'unbookmark' // 取消收藏 + | 'share' // 分享 + | 'imagePress' // 点击图片 + | 'delete'; // 删除 + +/** + * Action payload 类型 + */ +export interface PostCardActionPayload { + images?: ImageGridItem[]; + imageIndex?: number; + [key: string]: unknown; +} + +/** + * 统一的 Action 对象 + */ +export interface PostCardAction { + type: PostCardActionType; + payload?: PostCardActionPayload; +} + +/** + * 统一的回调函数类型 + */ +export type PostCardOnAction = (action: PostCardAction) => void; + +// ==================== Features 配置类型 ==================== + +/** + * 显示特性配置 + */ +export interface PostCardFeatures { + /** 显示用户信息 */ + showAuthor?: boolean; + /** 显示标题 */ + showTitle?: boolean; + /** 显示内容 */ + showContent?: boolean; + /** 显示图片 */ + showImages?: boolean; + /** 显示投票预览 */ + showVote?: boolean; + /** 显示热门评论 */ + showTopComment?: boolean; + /** 显示操作栏 */ + showActions?: boolean; + /** 显示浏览数 */ + showViews?: boolean; + /** 显示分享按钮 */ + showShare?: boolean; + /** 显示收藏按钮 */ + showBookmark?: boolean; + /** 显示删除按钮(需配合权限判断) */ + showDelete?: boolean; + /** 显示置顶标签 */ + showPinned?: boolean; + /** 显示徽章(楼主/管理员) */ + showBadges?: boolean; +} + +/** + * Features 预设名称 + */ +export type PostCardFeaturesPreset = 'full' | 'compact' | 'grid'; + +/** + * Features 配置(可以是预设名称或自定义对象) + */ +export type PostCardFeaturesConfig = PostCardFeaturesPreset | PostCardFeatures; + +// ==================== 主组件 Props ==================== + +/** + * PostCard 主组件 Props + */ +export interface PostCardProps { + /** 帖子数据 */ + post: Post; + + /** 统一事件回调 */ + onAction: PostCardOnAction; + + /** 显示模式:列表模式 | 网格模式 */ + variant?: 'list' | 'grid'; + + /** 预设配置名称,或自定义配置对象 */ + features?: PostCardFeaturesConfig; + + /** 当前用户是否为帖子作者(用于显示删除按钮) */ + isPostAuthor?: boolean; + + /** 当前用户是否为楼主(在帖子详情页显示"楼主"徽章) */ + isAuthor?: boolean; + + /** 索引(用于虚拟化列表优化) */ + index?: number; + + /** 自定义样式 */ + style?: StyleProp; +} + +// ==================== 子组件 Props ==================== + +/** + * PostHeader 子组件 Props + */ +export interface PostHeaderProps { + author: UserDTO; + createdAt: string; + editedAt?: string; + isPinned?: boolean; + badges?: Array<{ type: 'author' | 'admin'; label: string }>; + onDelete?: () => void; + onUserPress: () => void; + showDelete?: boolean; + showPinned?: boolean; + showBadges?: boolean; + isDeleting?: boolean; +} + +/** + * PostTitle 子组件 Props + */ +export interface PostTitleProps { + title?: string; + numberOfLines?: number; +} + +/** + * PostContent 子组件 Props + */ +export interface PostContentProps { + content?: string; + compact?: boolean; + maxLines?: number; + isExpanded?: boolean; + onToggleExpand?: () => void; +} + +/** + * PostImages 子组件 Props + */ +export interface PostImagesProps { + images: PostImageDTO[]; + displayMode: 'list' | 'grid'; + onImagePress: (images: ImageGridItem[], index: number) => void; +} + +/** + * PostActions 子组件 Props + */ +export interface PostActionsProps { + viewsCount: number; + likesCount: number; + commentsCount: number; + isLiked: boolean; + isFavorited: boolean; + onLike: () => void; + onComment: () => void; + onShare: () => void; + onBookmark: () => void; + showViews?: boolean; + showShare?: boolean; + showBookmark?: boolean; +} + +/** + * PostVotePreview 子组件 Props + */ +export interface PostVotePreviewProps { + isVote: boolean; + totalVotes?: number; + optionsCount?: number; + onPress: () => void; +} + +/** + * PostTopComment 子组件 Props + */ +export interface PostTopCommentProps { + comment: CommentDTO | null; + totalComments: number; + onPress: () => void; +} + +/** + * PostGridCover 子组件 Props + */ +export interface PostGridCoverProps { + image: PostImageDTO | null; + content?: string; + isVote?: boolean; + aspectRatio: number; + onImagePress: () => void; +} + +/** + * PostGridInfo 子组件 Props + */ +export interface PostGridInfoProps { + title?: string; + author: UserDTO; + likesCount: number; + onUserPress: () => void; +} + +// ==================== 容器组件 Props ==================== + +/** + * PostCardList 容器组件 Props + */ +export interface PostCardListProps { + post: Post; + onAction: PostCardOnAction; + features: PostCardFeatures; + isPostAuthor?: boolean; + isAuthor?: boolean; + index?: number; + style?: StyleProp; +} + +/** + * PostCardGrid 容器组件 Props + */ +export interface PostCardGridProps { + post: Post; + onAction: PostCardOnAction; + features: PostCardFeatures; + style?: StyleProp; +} + +// ==================== 旧版 Props(兼容层使用) ==================== + +/** + * 旧版 PostCard Props(用于兼容层) + * @deprecated 请迁移到新的 PostCardProps + */ +export interface LegacyPostCardProps { + post: Post; + onPress: () => void; + onUserPress: () => void; + onLike: () => void; + onComment: () => void; + onBookmark: () => void; + onShare: () => void; + onImagePress?: (images: ImageGridItem[], index: number) => void; + onDelete?: () => void; + compact?: boolean; + index?: number; + isAuthor?: boolean; + isPostAuthor?: boolean; + variant?: 'default' | 'grid'; +} + +// ==================== 工具类型 ==================== + +/** + * 徽章类型 + */ +export interface Badge { + type: 'author' | 'admin'; + label: string; +} diff --git a/src/components/business/index.ts b/src/components/business/index.ts index 7b319e5..5547a0d 100644 --- a/src/components/business/index.ts +++ b/src/components/business/index.ts @@ -2,7 +2,21 @@ * 业务组件导出 */ +// PostCard 新架构(从 PostCard 目录导出) export { default as PostCard } from './PostCard'; +// 导出 PostCard 相关类型和工具 +export type { + PostCardActionType, + PostCardAction, + PostCardOnAction, + PostCardFeatures, + PostCardFeaturesPreset, + PostCardFeaturesConfig, + PostCardProps, + LegacyPostCardProps, +} from './PostCard'; +export { PostCardPresets, resolveFeatures } from './PostCard'; +export { usePostCardActions, usePostCardFeatures } from './PostCard'; export { default as CommentItem } from './CommentItem'; export { default as UserProfileHeader } from './UserProfileHeader'; export { default as SystemMessageItem } from './SystemMessageItem'; diff --git a/src/screens/home/HomeScreen.tsx b/src/screens/home/HomeScreen.tsx index bbf9134..288e50e 100644 --- a/src/screens/home/HomeScreen.tsx +++ b/src/screens/home/HomeScreen.tsx @@ -29,6 +29,7 @@ import { useUserStore } from '../../stores'; import { useCurrentUser } from '../../stores/authStore'; import { postService } from '../../services'; import { PostCard, TabBar, SearchBar } from '../../components/business'; +import type { PostCardAction } from '../../components/business/PostCard'; import { Loading, EmptyState, Text, ImageGallery, ImageGridItem, ResponsiveGrid } from '../../components/common'; import { HomeStackParamList, RootStackParamList } from '../../navigation/types'; import { useResponsive, useResponsiveSpacing } from '../../hooks/useResponsive'; @@ -368,6 +369,41 @@ export const HomeScreen: React.FC = () => { setShowImageViewer(true); }; + // 统一处理 PostCard 的所有操作 + const handlePostAction = (post: Post, action: PostCardAction) => { + switch (action.type) { + case 'press': + handlePostPress(post.id); + break; + case 'userPress': + const authorId = post.author?.id; + if (authorId) handleUserPress(authorId); + break; + case 'like': + case 'unlike': + handleLike(post); + break; + case 'comment': + handlePostPress(post.id, true); + break; + case 'bookmark': + case 'unbookmark': + handleBookmark(post); + break; + case 'share': + handleShare(post); + break; + case 'imagePress': + if (action.payload?.images && action.payload?.imageIndex !== undefined) { + handleImagePress(action.payload.images, action.payload.imageIndex); + } + break; + case 'delete': + handleDeletePost(post.id); + break; + } + }; + // 跳转到发帖页面(使用 Modal 方式) const handleCreatePost = () => { setShowCreatePost(true); @@ -392,19 +428,12 @@ export const HomeScreen: React.FC = () => { ]}> handlePostPress(item.id)} - onUserPress={() => authorId && handleUserPress(authorId)} - onLike={() => handleLike(item)} - onComment={() => handlePostPress(item.id, true)} - onBookmark={() => handleBookmark(item)} - onShare={() => handleShare(item)} - onImagePress={(images, index) => handleImagePress(images, index)} - onDelete={() => handleDeletePost(item.id)} + onAction={(action) => handlePostAction(item, action)} isPostAuthor={isPostAuthor} /> ); - }, [currentUser?.id, handleBookmark, handleDeletePost, handleImagePress, handleLike, handlePostPress, handleShare, handleUserPress, isMobile, listItemWidth, responsiveGap]); + }, [currentUser?.id, handlePostAction, isMobile, listItemWidth, responsiveGap]); // 估算帖子在瀑布流中的高度(用于均匀分配) const estimatePostHeight = (post: Post, columnWidth: number): number => { diff --git a/src/screens/profile/ProfileScreen.tsx b/src/screens/profile/ProfileScreen.tsx index 28bdc3a..b100df0 100644 --- a/src/screens/profile/ProfileScreen.tsx +++ b/src/screens/profile/ProfileScreen.tsx @@ -22,6 +22,7 @@ import { Post } from '../../types'; import { useAuthStore, useUserStore } from '../../stores'; import { postService } from '../../services'; import { UserProfileHeader, PostCard, TabBar } from '../../components/business'; +import { PostCardAction } from '../../components/business/PostCard'; import { Loading, EmptyState, Text } from '../../components/common'; import { ResponsiveContainer } from '../../components/common'; import { useResponsive } from '../../hooks'; @@ -245,6 +246,37 @@ export const ProfileScreen: React.FC = () => { } }, []); + // 统一的 PostCard Action 处理 + const handlePostAction = useCallback((post: Post, action: PostCardAction) => { + switch (action.type) { + case 'press': + handlePostPress(post.id); + break; + case 'userPress': + if (post.author) { + handleUserPress(post.author.id); + } + break; + case 'like': + case 'unlike': + post.is_liked ? postService.unlikePost(post.id) : postService.likePost(post.id); + break; + case 'comment': + handlePostPress(post.id, true); + break; + case 'bookmark': + case 'unbookmark': + post.is_favorited ? postService.unfavoritePost(post.id) : postService.favoritePost(post.id); + break; + case 'share': + // 暂不处理分享 + break; + case 'delete': + handleDeletePost(post.id); + break; + } + }, [handlePostPress, handleUserPress, handleDeletePost]); + // 渲染内容 const renderContent = useCallback(() => { if (loading) return ; @@ -273,13 +305,7 @@ export const ProfileScreen: React.FC = () => { ]}> handlePostPress(post.id)} - onUserPress={() => post.author ? handleUserPress(post.author.id) : () => {}} - onLike={() => post.is_liked ? postService.unlikePost(post.id) : postService.likePost(post.id)} - onComment={() => handlePostPress(post.id, true)} - onBookmark={() => post.is_favorited ? postService.unfavoritePost(post.id) : postService.favoritePost(post.id)} - onShare={() => {}} - onDelete={() => handleDeletePost(post.id)} + onAction={(action) => handlePostAction(post, action)} isPostAuthor={isPostAuthor} /> diff --git a/src/screens/profile/UserScreen.tsx b/src/screens/profile/UserScreen.tsx index 5383caf..ffd5d17 100644 --- a/src/screens/profile/UserScreen.tsx +++ b/src/screens/profile/UserScreen.tsx @@ -23,6 +23,7 @@ import { useCurrentUser } from '../../stores/authStore'; import { authService, postService, messageService } from '../../services'; import { userManager } from '../../stores/userManager'; import { UserProfileHeader, PostCard, TabBar } from '../../components/business'; +import { PostCardAction } from '../../components/business/PostCard'; import { Loading, EmptyState, ResponsiveContainer } from '../../components/common'; import { useResponsive } from '../../hooks'; import { HomeStackParamList, RootStackParamList } from '../../navigation/types'; @@ -218,6 +219,39 @@ export const UserScreen: React.FC = () => { } }; + // 统一处理 PostCard 的所有操作 + const handlePostAction = (post: Post, action: PostCardAction) => { + switch (action.type) { + case 'press': + handlePostPress(post.id); + break; + case 'userPress': + if (post.author) handleUserPress(post.author.id); + break; + case 'like': + postService.likePost(post.id); + break; + case 'unlike': + postService.unlikePost(post.id); + break; + case 'comment': + handlePostPress(post.id, true); + break; + case 'bookmark': + postService.favoritePost(post.id); + break; + case 'unbookmark': + postService.unfavoritePost(post.id); + break; + case 'share': + // 暂不处理 + break; + case 'delete': + handleDeletePost(post.id); + break; + } + }; + // 跳转到聊天界面 const handleMessage = async () => { if (!user) return; @@ -317,13 +351,7 @@ export const UserScreen: React.FC = () => { ]}> handlePostPress(post.id)} - onUserPress={() => post.author ? handleUserPress(post.author.id) : () => {}} - onLike={() => post.is_liked ? postService.unlikePost(post.id) : postService.likePost(post.id)} - onComment={() => handlePostPress(post.id, true)} - onBookmark={() => post.is_favorited ? postService.unfavoritePost(post.id) : postService.favoritePost(post.id)} - onShare={() => {}} - onDelete={() => handleDeletePost(post.id)} + onAction={(action) => handlePostAction(post, action)} isPostAuthor={isPostAuthor} /> @@ -357,13 +385,7 @@ export const UserScreen: React.FC = () => { ]}> handlePostPress(post.id)} - onUserPress={() => post.author ? handleUserPress(post.author.id) : () => {}} - onLike={() => post.is_liked ? postService.unlikePost(post.id) : postService.likePost(post.id)} - onComment={() => handlePostPress(post.id, true)} - onBookmark={() => post.is_favorited ? postService.unfavoritePost(post.id) : postService.favoritePost(post.id)} - onShare={() => {}} - onDelete={() => handleDeletePost(post.id)} + onAction={(action) => handlePostAction(post, action)} isPostAuthor={isPostAuthor} />