前端简单界面

Change-Id: I7df9774daf4df8d92b13e659effe426ab0b6180b
diff --git a/pt--frontend/src/components/Post.jsx b/pt--frontend/src/components/Post.jsx
new file mode 100644
index 0000000..10a4840
--- /dev/null
+++ b/pt--frontend/src/components/Post.jsx
@@ -0,0 +1,200 @@
+import React, { useState, useEffect } from 'react';
+import {
+    createPost,
+    findPinnedPosts,
+    likePost,
+    unlikePost,
+    searchPosts,
+    getAllPostsSorted,
+    findPostsByUserId,
+} from '../api/post';
+import Comment from './Comment';
+
+const Post = () => {
+    const [title, setTitle] = useState('');
+    const [content, setContent] = useState('');
+    const [tags, setTags] = useState('');
+    const [photo, setPhoto] = useState(null);
+    const [posts, setPosts] = useState([]);
+    const [searchKeyword, setSearchKeyword] = useState('');
+
+    const currentUser = { id: 1, username: '测试用户' };
+
+    useEffect(() => {
+        loadPinnedPosts();  // 初始加载置顶帖子
+    }, []);
+
+    const loadPinnedPosts = async () => {
+        const data = await findPinnedPosts();
+        setPosts(data);
+    };
+
+    const loadAllPosts = async () => {
+        const data = await getAllPostsSorted();
+        setPosts(data);
+    };
+
+    const loadMyPosts = async () => {
+        const data = await findPostsByUserId(currentUser.id);
+        setPosts(data);
+    };
+
+    const handleCreate = async () => {
+        const formData = new FormData();
+        formData.append('userid', currentUser.id);
+        formData.append('post_title', title);
+        formData.append('post_content', content);
+        formData.append('is_pinned', true);
+        formData.append('tags', tags);
+        formData.append('rannge', 'public');
+        if (photo) {
+            formData.append('photo', photo);
+        }
+
+        const success = await createPost(formData);
+        if (success) {
+            alert('帖子创建成功');
+            loadPinnedPosts();
+            setTitle('');
+            setContent('');
+            setTags('');
+            setPhoto(null);
+        } else {
+            alert('创建失败');
+        }
+    };
+
+    const handleLike = async (postid) => {
+        await likePost(postid);
+        loadPinnedPosts();
+    };
+
+    const handleUnlike = async (postid) => {
+        await unlikePost(postid);
+        loadPinnedPosts();
+    };
+
+    const handleSearch = async () => {
+        const result = await searchPosts(searchKeyword);
+        setPosts(result);
+    };
+
+    return (
+        <div className="p-4 max-w-3xl mx-auto">
+            <h1 className="text-2xl font-bold mb-4">创建帖子</h1>
+            <div className="space-y-3 mb-6">
+                <input
+                    type="text"
+                    placeholder="标题"
+                    value={title}
+                    onChange={(e) => setTitle(e.target.value)}
+                    className="w-full border p-2 rounded"
+                />
+                <textarea
+                    placeholder="内容"
+                    value={content}
+                    onChange={(e) => setContent(e.target.value)}
+                    className="w-full border p-2 rounded"
+                />
+                <input
+                    type="text"
+                    placeholder="标签(用逗号分隔,如 学习,编程)"
+                    value={tags}
+                    onChange={(e) => setTags(e.target.value)}
+                    className="w-full border p-2 rounded"
+                />
+                <input
+                    type="file"
+                    onChange={(e) => setPhoto(e.target.files[0])}
+                />
+                <button
+                    onClick={handleCreate}
+                    className="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600"
+                >
+                    发布
+                </button>
+            </div>
+
+            <div className="mb-6 flex gap-3">
+                <input
+                    type="text"
+                    placeholder="搜索关键词"
+                    value={searchKeyword}
+                    onChange={(e) => setSearchKeyword(e.target.value)}
+                    className="border p-2 rounded flex-grow"
+                />
+                <button
+                    onClick={handleSearch}
+                    className="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600"
+                >
+                    搜索
+                </button>
+            </div>
+
+            {/* 新增三个展示按钮 */}
+            <div className="mb-6 flex gap-3">
+                <button
+                    onClick={loadPinnedPosts}
+                    className="bg-yellow-500 text-white px-4 py-2 rounded hover:bg-yellow-600"
+                >
+                    置顶帖子
+                </button>
+                <button
+                    onClick={loadAllPosts}
+                    className="bg-purple-500 text-white px-4 py-2 rounded hover:bg-purple-600"
+                >
+                    所有帖子
+                </button>
+                <button
+                    onClick={loadMyPosts}
+                    className="bg-indigo-500 text-white px-4 py-2 rounded hover:bg-indigo-600"
+                >
+                    我的帖子
+                </button>
+            </div>
+
+            <h2 className="text-xl font-semibold mb-3">帖子列表</h2>
+            <div className="space-y-6">
+                {posts.map((post) => (
+                    <div key={post.postid} className="border rounded p-4 shadow bg-white">
+                        <h3 className="text-lg font-bold">{post.postTitle}</h3>
+                        <p className="text-gray-700">{post.postContent}</p>
+                        {post.photo && (
+                            <img
+                                src={`http://localhost:8080${post.photo}`}
+                                alt="post"
+                                className="w-64 h-auto mt-2"
+                            />
+                        )}
+                        <div className="mt-2 text-sm text-gray-500">
+                            发布时间:{post.postCreatedTime}
+                        </div>
+                        <div className="mt-2 text-sm text-gray-500">
+                            标签:{post.tags || '无'}
+                        </div>
+                        <div className="mt-2 flex items-center gap-4">
+                            <span>👍 {post.likes}</span>
+                            <button
+                                onClick={() => handleLike(post.postid)}
+                                className="text-blue-500 hover:underline"
+                            >
+                                点赞
+                            </button>
+                            <button
+                                onClick={() => handleUnlike(post.postid)}
+                                className="text-red-500 hover:underline"
+                            >
+                                取消点赞
+                            </button>
+                        </div>
+                        <div className="mt-4 border-t pt-4">
+                            <Comment postId={post.postid} currentUser={currentUser} />
+                        </div>
+                    </div>
+                ))}
+            </div>
+        </div>
+    );
+};
+
+export default Post;