blob: ca789c59043706b0ce85c566e907ea9501bb5e75 [file] [log] [blame] [edit]
import React, { useState, useEffect } from 'react';
import { Table, Button, message, Space, Modal } from 'antd';
import axios from 'axios'; // 新增 axios 导入
import { useNavigate } from 'umi';
import { getBountyList } from '@/services/bounty/bounty';
import BountyPublish from './BountyPublish';
import BountyReply from './BountyReply';
const BountyList: React.FC = () => {
const [dataSource, setDataSource] = useState<API.Bounty[]>([]);
const [loading, setLoading] = useState(false);
const [publishVisible, setPublishVisible] = useState(false);
const [replyVisible, setReplyVisible] = useState(false);
const [selectedId, setSelectedId] = useState<number | null>(null);
const navigate = useNavigate();
// 加载悬赏列表(修改请求方式)
const loadBountyList = async () => {
try {
setLoading(true);
const res = await getBountyList();
// 添加详细日志输出
console.log('接口原始响应:', res);
// 修改数据处理逻辑以适配实际数据结构
if (res && Array.isArray(res)) {
// 当接口直接返回数组时
setDataSource(res);
} else if (res && res.code === 200) {
// 当接口返回标准分页结构时
setDataSource(res.data.records || res.data || []);
} else {
throw new Error('接口返回异常结构');
}
} catch (err) {
console.error('加载数据异常:', err);
console.error('完整错误:', err);
// 添加网络错误处理
// @ts-ignore
if (err?.response?.status === 401) {
message.error('认证失效,请重新登录');
navigate('/login');
} else {
message.error('加载悬赏列表失败');
}
} finally {
setLoading(false);
}
};
useEffect(() => {
loadBountyList();
}, []);
// ✅ 发布成功回调(普通函数,无需useEffect)
const handlePublishSuccess = () => {
setPublishVisible(false);
loadBountyList(); // 重新加载数据
message.success('悬赏发布成功');
};
// ✅ 回复成功回调(普通函数,无需useEffect)
const handleReplySuccess = () => {
setReplyVisible(false);
loadBountyList(); // 重新加载数据
message.success('回复提交成功');
};
// 跳转详情页
const goDetail = (id: number) => {
navigate(`/bounty/detail/${id}`);
};
// 表格列配置
const columns = [
{
title: '标题',
dataIndex: 'title',
width: 200,
ellipsis: true,
},
{
title: '发布者ID',
dataIndex: 'creator_id', // ✅ 新增列
width: 100,
align: 'center' as const,
},
{
title: '奖励',
dataIndex: 'reward',
width: 100,
align: 'center' as const,
},
{
title: '状态',
dataIndex: 'status',
width: 100,
render: (status: number) => (
status === 0 ? '未回复' : status === 1 ? '已回复' : '已关闭'
)
},
{
title: '操作',
width: 160,
render: (value: unknown, record: API.Bounty) => (
<Space>
<Button
type="link"
onClick={() => navigate(`/bounty/detail/${record.id}`)}
>
查看详情
</Button>
<Button
type="link"
onClick={() => {
setSelectedId(record.id);
setReplyVisible(true);
}}
>
回复悬赏
</Button>
</Space>
)
}
];
return (
<div className="page-container">
{/* 顶部操作区 */}
<div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 16 }}>
<h2>悬赏列表</h2>
{/* 发布按钮 */}
<Button
type="primary"
onClick={() => setPublishVisible(true)}
>
发布悬赏
</Button>
</div>
{/* 悬赏列表 */}
<Table
dataSource={dataSource}
columns={columns}
rowKey="id"
pagination={{ pageSize: 10 }}
loading={loading}
/>
{/* 发布悬赏模态框 */}
<Modal
title="发布新悬赏"
open={publishVisible}
onCancel={() => setPublishVisible(false)}
footer={null}
>
<BountyPublish onSuccess={handlePublishSuccess} />
</Modal>
{/* 回复悬赏模态框 */}
<Modal
title="回复悬赏"
open={replyVisible}
onCancel={() => setReplyVisible(false)}
footer={null}
>
{selectedId && (
<BountyReply
bountyId={selectedId}
onSuccess={handleReplySuccess}
/>
)}
</Modal>
</div>
);
};
export default BountyList;