blob: fceaef845fabd38e15aecbbc1d7e28d152cf3923 [file] [log] [blame]
223011339e292152025-06-08 00:34:37 +08001import React, { useState, useEffect } from "react";
wht6a1b6782025-06-06 19:14:59 +08002import { useParams } from "react-router-dom";
223011339e292152025-06-08 00:34:37 +08003import { API_BASE_URL } from "./config";
wht6a1b6782025-06-06 19:14:59 +08004
5export default function PostDetailPage() {
6 const { postId } = useParams();
223011339e292152025-06-08 00:34:37 +08007 const [post, setPost] = useState(null);
8 const [replies, setReplies] = useState([]);
9 const [newReply, setNewReply] = useState('');
10
11 // function to load post details and its replies
12 const fetchDetail = () => {
13 fetch(`${API_BASE_URL}/api/forum-detail?postid=${postId}`)
14 .then(res => res.json())
15 .then(data => {
16 console.log("Fetched post detail:", data);
17 const p = data.post || data;
18 const formattedPost = {
19 post_id: p.postid,
20 title: p.posttitle,
21 content: p.postcontent,
22 author_id: p.postuserid,
23 author_name: p.author?.username || '',
24 created_at: new Date(p.posttime).toLocaleString(),
25 reply_count: p.replytime,
26 view_count: p.readtime,
27 };
28 const formattedReplies = (data.replies || []).map(r => ({
29 reply_id: r.replyid,
30 post_id: r.postid || postId,
31 content: r.content,
32 author_id: r.authorid,
33 author_name: r.author?.username || '',
34 created_at: new Date(r.createdAt).toLocaleString(),
35 }));
36 setPost(formattedPost);
37 setReplies(formattedReplies);
38 })
39 .catch(err => console.error(err));
40 };
41
42 useEffect(() => {
43 fetchDetail();
44 }, [postId]);
45
46 // post a new reply to backend
47 const handleReply = () => {
48 const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
49 const userId = match ? match[2] : null;
50 if (!userId) {
51 alert('请先登录后再回复');
52 return;
53 }
54 fetch(`${API_BASE_URL}/api/forum-reply`, {
55 method: 'POST',
56 headers: { 'Content-Type': 'application/json' },
57 body: JSON.stringify({ postid: postId, replycontent: newReply, replyuserid: userId }),
58 })
59 .then(res => res.json())
60 .then(() => {
61 setNewReply('');
62 fetchDetail();
63 })
64 .catch(err => console.error(err));
65 };
66
67 if (!post) return <div>加载中...</div>;
wht6a1b6782025-06-06 19:14:59 +080068 return (
69 <div style={{ maxWidth: 700, margin: "40px auto" }}>
70 {/* 原帖 */}
71 <div style={{
72 background: "#fff",
73 borderRadius: 12,
74 boxShadow: "0 2px 8px #e0e7ff",
75 padding: 24,
76 marginBottom: 32,
77 }}>
78 <div style={{ fontSize: 15, color: "#1976d2", marginBottom: 6 }}>
79 {post.author_name} · {post.created_at}
80 </div>
81 <div style={{ fontWeight: 600, fontSize: 20, marginBottom: 8, color: "#222" }}>
82 {post.title}
83 </div>
84 <div style={{ fontSize: 16, color: "#444", marginBottom: 18 }}>
85 {post.content}
86 </div>
87 <div style={{ display: "flex", justifyContent: "flex-start", gap: 32, fontSize: 14, color: "#888" }}>
88 <span>回复数: {post.reply_count}</span>
89 <span>观看数: {post.view_count}</span>
90 </div>
91 </div>
92 {/* 评论区 */}
93 <div>
94 {replies.map(reply => (
95 <div key={reply.reply_id} style={{
96 display: "flex",
97 alignItems: "center",
98 background: "#f8faff",
99 borderRadius: 8,
100 padding: "12px 18px",
101 marginBottom: 16,
102 fontSize: 15,
103 }}>
104 <span style={{ color: "#1976d2", fontWeight: 500, minWidth: 80 }}>{reply.author_name}</span>
105 <span style={{ flex: 1, marginLeft: 18 }}>{reply.content}</span>
106 <span style={{ color: "#888", fontSize: 13, marginLeft: 18 }}>{reply.created_at}</span>
107 </div>
108 ))}
109 </div>
110 {/* 回复框 */}
111 <div style={{
112 marginTop: 32,
113 background: "#fff",
114 borderRadius: 8,
115 boxShadow: "0 2px 8px #e0e7ff",
116 padding: 18,
117 display: "flex",
118 gap: 12,
119 alignItems: "center"
120 }}>
121 <input
122 type="text"
123 placeholder="写下你的回复..."
223011339e292152025-06-08 00:34:37 +0800124 value={newReply}
125 onChange={e => setNewReply(e.target.value)}
wht6a1b6782025-06-06 19:14:59 +0800126 style={{
127 flex: 1,
128 border: "1px solid #bfcfff",
129 borderRadius: 6,
130 padding: "8px 12px",
131 fontSize: 15,
132 }}
133 />
223011339e292152025-06-08 00:34:37 +0800134 <button onClick={handleReply} style={{
wht6a1b6782025-06-06 19:14:59 +0800135 background: "#1976d2",
136 color: "#fff",
137 border: "none",
138 borderRadius: 6,
139 padding: "8px 24px",
140 fontSize: 15,
141 cursor: "pointer"
142 }}>回复</button>
143 </div>
144 </div>
145 );
146}