blob: a01df086b47f09e6354a0834eda68b123dc58fad [file] [log] [blame]
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;