帖子的相关用户前端与管理员后端

Change-Id: I957181738817aeeaa89fabe23ceaf59d00c37a71
diff --git a/src/components/PostCard.jsx b/src/components/PostCard.jsx
new file mode 100644
index 0000000..5051cec
--- /dev/null
+++ b/src/components/PostCard.jsx
@@ -0,0 +1,103 @@
+import React, { useState, useEffect } from 'react';
+import {
+    likePost,
+    unlikePost,
+    togglePinPost,
+    deletePost,
+} from '../api/post';
+
+const PostCard = ({ post, onDeleted, onUpdated }) => {
+    const [likes, setLikes] = useState(post.likes);
+    const [isLiked, setIsLiked] = useState(false); // 默认未点赞
+    const [isPinned, setIsPinned] = useState(post.is_pinned || false);
+    const [loading, setLoading] = useState(false);
+
+    useEffect(() => {
+        setIsPinned(post.is_pinned || false);
+    }, [post.is_pinned]);
+
+    const handleLike = async () => {
+        setLoading(true);
+        try {
+            if (!isLiked) {
+                const res = await likePost(post.postid);
+                if (res) {
+                    setLikes(likes + 1);
+                    setIsLiked(true);
+                }
+            } else {
+                const res = await unlikePost(post.postid);
+                if (res) {
+                    setLikes(likes - 1);
+                    setIsLiked(false);
+                }
+            }
+        } catch (error) {
+            console.error('点赞操作失败', error);
+        }
+        setLoading(false);
+    };
+
+    const handlePin = async () => {
+        setLoading(true);
+        try {
+            const res = await togglePinPost(post.postid);
+            if (res) {
+                onUpdated && onUpdated(); // 通知父组件刷新数据
+            }
+        } catch (error) {
+            console.error('置顶切换失败', error);
+        }
+        setLoading(false);
+    };
+
+    const handleDelete = async () => {
+        if (!window.confirm('确认删除该帖子吗?')) return;
+        setLoading(true);
+        try {
+            const res = await deletePost(post.postid);
+            if (res) {
+                onDeleted && onDeleted(post.postid);
+            }
+        } catch (error) {
+            console.error('删除失败', error);
+        }
+        setLoading(false);
+    };
+
+    return (
+        <div className="post-card" style={{ border: '1px solid #ddd', padding: 16, marginBottom: 12 }}>
+            <h3>{post.postTitle}</h3>
+            <p>{post.postContent}</p>
+            {post.photo && (
+                <img
+                    src={`http://localhost:8080${post.photo}`}
+                    alt="帖子图片"
+                    style={{ maxWidth: '100%', maxHeight: 200 }}
+                />
+            )}
+            <p>
+                <strong>标签:</strong> {post.tags || '无'}
+            </p>
+            <p>
+                <strong>作者ID:</strong> {post.userid} | <strong>点赞数:</strong> {likes}
+            </p>
+            <p>
+                <strong>发布时间:</strong> {new Date(post.postCreatedTime).toLocaleString()}
+            </p>
+            <p>
+                <button onClick={handleLike} disabled={loading}>
+                    {isLiked ? '取消点赞' : '点赞'}
+                </button>{' '}
+                <button onClick={handlePin} disabled={loading}>
+                    {isPinned ? '取消置顶' : '置顶'}
+                </button>{' '}
+                <button onClick={handleDelete} disabled={loading}>
+                    删除
+                </button>
+            </p>
+        </div>
+    );
+};
+
+export default PostCard;