| import React, { useEffect, useState } from 'react'; |
| import { |
| Table, |
| Button, |
| Modal, |
| Image, |
| message, |
| Tag, |
| Space, |
| Input, |
| Tooltip, |
| } from 'antd'; |
| import { ExclamationCircleOutlined, SearchOutlined } from '@ant-design/icons'; |
| import { |
| getAllPostsSorted, |
| searchPosts, |
| deletePost, |
| togglePinPost, |
| } from '../api/post'; |
| |
| const { confirm } = Modal; |
| |
| const PostAdminPanel = () => { |
| const [posts, setPosts] = useState([]); |
| const [loading, setLoading] = useState(false); |
| const [keyword, setKeyword] = useState(''); |
| |
| const fetchPosts = async () => { |
| setLoading(true); |
| try { |
| const data = keyword.trim() |
| ? await searchPosts(keyword.trim()) |
| : await getAllPostsSorted(); |
| setPosts(data); |
| } catch (error) { |
| message.error('获取帖子失败'); |
| } finally { |
| setLoading(false); |
| } |
| }; |
| |
| useEffect(() => { |
| fetchPosts(); |
| }, []); |
| |
| const handleSearch = () => { |
| fetchPosts(); |
| }; |
| |
| const handleDelete = (postid) => { |
| confirm({ |
| title: '确认删除该帖子吗?', |
| icon: <ExclamationCircleOutlined />, |
| okText: '删除', |
| okType: 'danger', |
| cancelText: '取消', |
| onOk: async () => { |
| try { |
| const res = await deletePost(postid); |
| if (res) { |
| message.success('删除成功'); |
| fetchPosts(); |
| } else { |
| message.error('删除失败'); |
| } |
| } catch { |
| message.error('删除请求失败'); |
| } |
| }, |
| }); |
| }; |
| |
| const handlePinToggle = async (postid) => { |
| try { |
| const res = await togglePinPost(postid); |
| if (res === true || res === false) { |
| // ✅ 用后端返回的状态更新 UI |
| const newPosts = posts.map(post => { |
| if (post.postid === postid) { |
| return { |
| ...post, |
| is_pinned: res ? 1 : 0, |
| }; |
| } |
| return post; |
| }); |
| setPosts(newPosts); |
| message.success(`帖子${res ? '已置顶' : '已取消置顶'}`); |
| } else { |
| message.error('更新失败'); |
| } |
| } catch { |
| message.error('更新置顶状态失败'); |
| } |
| }; |
| |
| |
| |
| |
| const columns = [ |
| { |
| title: 'ID', |
| dataIndex: 'postid', |
| key: 'postid', |
| width: 80, |
| fixed: 'left', |
| }, |
| { |
| title: '用户ID', |
| dataIndex: 'userid', |
| key: 'userid', |
| width: 100, |
| }, |
| { |
| title: '标题', |
| dataIndex: 'postTitle', |
| key: 'postTitle', |
| width: 200, |
| ellipsis: true, |
| }, |
| { |
| title: '内容', |
| dataIndex: 'postContent', |
| key: 'postContent', |
| ellipsis: { showTitle: false }, |
| render: (text) => ( |
| <Tooltip placement="topLeft" title={text}> |
| {text} |
| </Tooltip> |
| ), |
| }, |
| { |
| title: '标签', |
| dataIndex: 'tags', |
| key: 'tags', |
| render: (tags) => |
| tags ? tags.split(',').map((tag) => <Tag key={tag}>{tag}</Tag>) : <Tag color="default">无</Tag>, |
| }, |
| { |
| title: '图片', |
| dataIndex: 'photo', |
| key: 'photo', |
| width: 100, |
| render: (url) => |
| url ? ( |
| <Image |
| src={`http://localhost:8080${url}`} |
| width={80} |
| height={80} |
| style={{ objectFit: 'cover' }} |
| /> |
| ) : ( |
| <Tag color="default">无</Tag> |
| ), |
| }, |
| { |
| title: '点赞数', |
| dataIndex: 'likes', |
| key: 'likes', |
| width: 100, |
| render: (likes) => <Tag color="blue">{likes}</Tag>, |
| }, |
| { |
| title: '置顶状态', |
| dataIndex: 'is_pinned', |
| key: 'is_pinned', |
| width: 100, |
| render: (val) => |
| val ? <Tag color="green">已置顶</Tag> : <Tag color="default">未置顶</Tag>, |
| }, |
| { |
| title: '发布时间', |
| dataIndex: 'postCreatedTime', |
| key: 'postCreatedTime', |
| width: 180, |
| render: (time) => |
| time ? new Date(time).toLocaleString() : <Tag color="default">暂无</Tag>, |
| }, |
| { |
| title: '操作', |
| key: 'action', |
| width: 180, |
| fixed: 'right', |
| render: (_, record) => ( |
| <Space size="middle"> |
| <Button |
| type="primary" |
| onClick={() => handlePinToggle(record.postid, record.is_pinned)} |
| > |
| {Boolean(record.is_pinned) ? '取消置顶' : '置顶'} |
| </Button> |
| |
| <Button danger onClick={() => handleDelete(record.postid)}> |
| 删除 |
| </Button> |
| </Space> |
| ), |
| }, |
| ]; |
| |
| return ( |
| <div style={{ padding: 20 }}> |
| <h2 style={{ marginBottom: 20 }}>帖子管理面板</h2> |
| <Space style={{ marginBottom: 16 }}> |
| <Input |
| placeholder="请输入关键词" |
| value={keyword} |
| onChange={(e) => setKeyword(e.target.value)} |
| style={{ width: 300 }} |
| /> |
| <Button type="primary" icon={<SearchOutlined />} onClick={handleSearch}> |
| 搜索 |
| </Button> |
| <Button onClick={() => { setKeyword(''); fetchPosts(); }}> |
| 重置 |
| </Button> |
| </Space> |
| <Table |
| rowKey="postid" |
| columns={columns} |
| dataSource={posts} |
| loading={loading} |
| scroll={{ x: 1600 }} |
| pagination={{ pageSize: 10 }} |
| bordered |
| size="middle" |
| /> |
| </div> |
| ); |
| }; |
| |
| export default PostAdminPanel; |