新增后台接口

Change-Id: Ibd8183079a77aad05b2c81658c2d6fe9b648e042
diff --git a/front/src/PostDetailPage.js b/front/src/PostDetailPage.js
index 85b7707..fceaef8 100644
--- a/front/src/PostDetailPage.js
+++ b/front/src/PostDetailPage.js
@@ -1,40 +1,70 @@
-import React from "react";
+import React, { useState, useEffect } from "react";
 import { useParams } from "react-router-dom";
-
-// 示例数据
-const post = {
-    post_id: "1",
-    title: "欢迎来到G10论坛",
-    content: "这里是G10 PT站的官方论坛,欢迎大家发帖交流!",
-    author_id: "u1",
-    author_name: "Alice",
-    created_at: "2024-06-01 12:00",
-    reply_count: 3,
-    view_count: 120,
-};
-
-const replies = [
-    {
-        reply_id: "r1",
-        post_id: "1",
-        content: "支持一下!",
-        author_id: "u2",
-        author_name: "Bob",
-        created_at: "2024-06-01 13:00",
-    },
-    {
-        reply_id: "r2",
-        post_id: "1",
-        content: "论坛终于上线了!",
-        author_id: "u3",
-        author_name: "Carol",
-        created_at: "2024-06-01 14:20",
-    },
-];
+import { API_BASE_URL } from "./config";
 
 export default function PostDetailPage() {
     const { postId } = useParams();
-    // 这里只展示post和replies的静态内容
+    const [post, setPost] = useState(null);
+    const [replies, setReplies] = useState([]);
+    const [newReply, setNewReply] = useState('');
+
+    // function to load post details and its replies
+    const fetchDetail = () => {
+        fetch(`${API_BASE_URL}/api/forum-detail?postid=${postId}`)
+            .then(res => res.json())
+            .then(data => {
+                console.log("Fetched post detail:", data);
+                const p = data.post || data;
+                const formattedPost = {
+                    post_id: p.postid,
+                    title: p.posttitle,
+                    content: p.postcontent,
+                    author_id: p.postuserid,
+                    author_name: p.author?.username || '',
+                    created_at: new Date(p.posttime).toLocaleString(),
+                    reply_count: p.replytime,
+                    view_count: p.readtime,
+                };
+                const formattedReplies = (data.replies || []).map(r => ({
+                    reply_id: r.replyid,
+                    post_id: r.postid || postId,
+                    content: r.content,
+                    author_id: r.authorid,
+                    author_name: r.author?.username || '',
+                    created_at: new Date(r.createdAt).toLocaleString(),
+                }));
+                setPost(formattedPost);
+                setReplies(formattedReplies);
+            })
+            .catch(err => console.error(err));
+    };
+
+    useEffect(() => {
+        fetchDetail();
+    }, [postId]);
+
+    // post a new reply to backend
+    const handleReply = () => {
+        const match = document.cookie.match('(^|;)\\s*userId=([^;]+)');
+        const userId = match ? match[2] : null;
+        if (!userId) {
+            alert('请先登录后再回复');
+            return;
+        }
+        fetch(`${API_BASE_URL}/api/forum-reply`, {
+            method: 'POST',
+            headers: { 'Content-Type': 'application/json' },
+            body: JSON.stringify({ postid: postId, replycontent: newReply, replyuserid: userId }),
+        })
+            .then(res => res.json())
+            .then(() => {
+                setNewReply('');
+                fetchDetail();
+            })
+            .catch(err => console.error(err));
+    };
+
+    if (!post) return <div>加载中...</div>;
     return (
         <div style={{ maxWidth: 700, margin: "40px auto" }}>
             {/* 原帖 */}
@@ -91,6 +121,8 @@
                 <input
                     type="text"
                     placeholder="写下你的回复..."
+                    value={newReply}
+                    onChange={e => setNewReply(e.target.value)}
                     style={{
                         flex: 1,
                         border: "1px solid #bfcfff",
@@ -99,7 +131,7 @@
                         fontSize: 15,
                     }}
                 />
-                <button style={{
+                <button onClick={handleReply} style={{
                     background: "#1976d2",
                     color: "#fff",
                     border: "none",