前端简单界面
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;