/** * 帖子详情页 * 展示帖子完整内容、事件时间轴、评论区 */ import React, { useState, useEffect } from 'react'; import { Box, Heading, Text, HStack, VStack, Avatar, Badge, Button, Image, SimpleGrid, Spinner, Center, Flex, IconButton, Divider, } from '@chakra-ui/react'; import { useParams, useNavigate } from 'react-router-dom'; import { motion } from 'framer-motion'; import { ArrowLeft, Heart, MessageCircle, Eye, Share2, Bookmark, } from 'lucide-react'; import { forumColors } from '@theme/forumTheme'; import { getPostById, likePost, getEventsByPostId, } from '@services/elasticsearchService'; import EventTimeline from './components/EventTimeline'; import CommentSection from './components/CommentSection'; import ImagePreviewModal from '@components/ImagePreviewModal'; const MotionBox = motion(Box); const PostDetail = () => { const { postId } = useParams(); const navigate = useNavigate(); const [post, setPost] = useState(null); const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [isLiked, setIsLiked] = useState(false); const [likes, setLikes] = useState(0); // 图片预览相关状态 const [isImagePreviewOpen, setIsImagePreviewOpen] = useState(false); const [previewImageIndex, setPreviewImageIndex] = useState(0); // 加载帖子数据 useEffect(() => { const loadPostData = async () => { try { setLoading(true); // 并行加载帖子和事件 const [postData, eventsData] = await Promise.all([ getPostById(postId), getEventsByPostId(postId), ]); setPost(postData); setLikes(postData.likes_count || 0); setEvents(eventsData); } catch (error) { console.error('加载帖子失败:', error); } finally { setLoading(false); } }; loadPostData(); }, [postId]); // 处理点赞 const handleLike = async () => { try { if (!isLiked) { await likePost(postId); setLikes((prev) => prev + 1); setIsLiked(true); } } catch (error) { console.error('点赞失败:', error); } }; // 打开图片预览 const handleImageClick = (index) => { setPreviewImageIndex(index); setIsImagePreviewOpen(true); }; // 格式化时间 const formatTime = (dateString) => { const date = new Date(dateString); return date.toLocaleString('zh-CN', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', }); }; if (loading) { return (
加载中...
); } if (!post) { return (
帖子不存在或已被删除
); } return ( {/* 返回按钮 */} {/* 左侧:帖子内容 + 评论 */} {/* 帖子主体 */} {/* 作者信息 */} {post.author_name} 发布于 {formatTime(post.created_at)} {/* 操作按钮 */} } variant="ghost" color={forumColors.text.tertiary} _hover={{ color: forumColors.primary[500] }} aria-label="分享" /> } variant="ghost" color={forumColors.text.tertiary} _hover={{ color: forumColors.primary[500] }} aria-label="收藏" /> {/* 帖子内容 */} {/* 标题 */} {post.title} {/* 标签 */} {post.tags && post.tags.length > 0 && ( {post.tags.map((tag, index) => ( #{tag} ))} )} {/* 正文 */} {post.content} {/* 图片 */} {post.images && post.images.length > 0 && ( {post.images.map((img, index) => ( {`图片 handleImageClick(index)} _hover={{ transform: 'scale(1.05)', boxShadow: forumColors.shadows.gold, }} transition="all 0.3s" /> ))} )} {/* 互动栏 */} {likes} {post.comments_count || 0} {post.views_count || 0} {/* 评论区 */} {/* 右侧:事件时间轴 */} {/* 图片预览弹窗 */} setIsImagePreviewOpen(false)} images={post?.images || []} initialIndex={previewImageIndex} /> ); }; export default PostDetail;