import React, { useState, useEffect, useCallback } from 'react';
|
import { Table, Card, Button, Space, Tag, message, Avatar, Popconfirm, Spin } from 'antd';
|
import { UserOutlined, EyeOutlined, DeleteOutlined } from '@ant-design/icons';
|
import dayjs from 'dayjs';
|
import { useNavigate, useParams } from 'react-router-dom';
|
import { activityUserAPI } from '../../services/api';
|
|
const RegistrationManagement = () => {
|
const navigate = useNavigate();
|
const { id: activityId } = useParams(); // 获取活动ID
|
const [registrations, setRegistrations] = useState([]);
|
const [loading, setLoading] = useState(false);
|
const [pagination, setPagination] = useState({
|
current: 1,
|
pageSize: 10,
|
total: 0,
|
});
|
|
// 获取报名列表数据
|
const fetchRegistrationData = useCallback(async (params = {}) => {
|
try {
|
setLoading(true);
|
const queryParams = {
|
activityId: activityId, // 从URL参数获取活动ID
|
page: pagination.current, // 页码从1开始
|
size: pagination.pageSize, // 每页大小
|
...params,
|
};
|
|
const response = await activityUserAPI.getRegistrationList(queryParams);
|
if (response.code === 0) {
|
// 转换数据格式以适配前端显示
|
const transformedData = response.data.content?.map(item => {
|
// 调试日志:查看原始状态值
|
console.log('原始状态值:', item.status, '类型:', typeof item.status);
|
return {
|
id: item.id,
|
volunteerName: item.userName, // userName -> volunteerName
|
phone: item.userPhone, // userPhone -> phone
|
registerTime: item.createTime ? dayjs(item.createTime).format('YYYY-MM-DD HH:mm') : '', // 格式化报名时间
|
checkInLocation: item.checkinLocation || '', // checkinLocation -> checkInLocation
|
checkInTime: item.checkinTime ? dayjs(item.checkinTime).format('YYYY-MM-DD HH:mm') : '', // 格式化签到时间
|
checkOutLocation: item.checkoutLocation || '', // checkoutLocation -> checkOutLocation
|
checkOutTime: item.checkoutTime ? dayjs(item.checkoutTime).format('YYYY-MM-DD HH:mm') : '', // 格式化签退时间
|
status: (item.status === 1 || item.status === '1') ? '1' : (item.status === 2 || item.status === '2') ? '2' : (item.status === 3 || item.status === '3') ? '3' : '未知', // 状态映射
|
originalData: item,
|
};
|
});
|
|
console.log('转换后的数据:', transformedData);
|
setRegistrations(transformedData);
|
setPagination(prev => ({
|
...prev,
|
total: response.data.totalElements || 0,
|
}));
|
}
|
} catch (error) {
|
console.error('获取报名列表失败:', error);
|
message.error('获取报名列表失败');
|
} finally {
|
setLoading(false);
|
}
|
}, [activityId, pagination.current, pagination.pageSize]);
|
|
// 页面初始化加载数据
|
useEffect(() => {
|
if (activityId) {
|
fetchRegistrationData();
|
}
|
}, [activityId, fetchRegistrationData]);
|
|
const columns = [
|
{
|
title: '志愿者',
|
key: 'volunteer',
|
width: 150,
|
render: (_, record) => (
|
<Space>
|
<Avatar icon={<UserOutlined />} />
|
<div>
|
<div style={{ fontWeight: 'bold' }}>{record.volunteerName}</div>
|
<div style={{ fontSize: '12px', color: '#8c8c8c' }}>{record.phone}</div>
|
</div>
|
</Space>
|
),
|
},
|
{
|
title: '报名时间',
|
dataIndex: 'registerTime',
|
key: 'registerTime',
|
width: 150,
|
render: (time) => time || '-',
|
},
|
{
|
title: '签到地点',
|
dataIndex: 'checkInLocation',
|
key: 'checkInLocation',
|
width: 120,
|
render: (location) => location || '-',
|
},
|
{
|
title: '签到时间',
|
dataIndex: 'checkInTime',
|
key: 'checkInTime',
|
width: 150,
|
render: (time) => time || '-',
|
},
|
{
|
title: '签退地点',
|
dataIndex: 'checkOutLocation',
|
key: 'checkOutLocation',
|
width: 120,
|
render: (location) => location || '-',
|
},
|
{
|
title: '签退时间',
|
dataIndex: 'checkOutTime',
|
key: 'checkOutTime',
|
width: 150,
|
render: (time) => time || '-',
|
},
|
{
|
title: '状态',
|
dataIndex: 'status',
|
key: 'status',
|
width: 100,
|
render: (status) => {
|
const statusMap = {
|
'1': { text: '已报名)', color: 'blue' },
|
'2': { text: '已签到', color: 'green' },
|
'3': { text: '已签退', color: 'purple' },
|
'未知': { text: '未知', color: 'default' },
|
};
|
const statusInfo = statusMap[status] || { text: status, color: 'default' };
|
return <Tag color={statusInfo.color}>{statusInfo.text}</Tag>;
|
},
|
},
|
{
|
title: '操作',
|
key: 'action',
|
width: 200,
|
render: (_, record) => (
|
<Space>
|
<Button
|
type="link"
|
icon={<EyeOutlined />}
|
onClick={() => handleViewDetail(record)}
|
>
|
详情
|
</Button>
|
{record.status === '1' && (
|
<Popconfirm
|
title="确定要移除这个报名者吗?"
|
onConfirm={() => handleRemove(record.id)}
|
okText="确定"
|
cancelText="取消"
|
>
|
<Button
|
type="link"
|
danger
|
icon={<DeleteOutlined />}
|
>
|
移除
|
</Button>
|
</Popconfirm>
|
)}
|
</Space>
|
),
|
},
|
];
|
|
const handleViewDetail = (record) => {
|
navigate(`/activities/registrations/detail/${record.id}`);
|
};
|
|
const handleRemove = async (id) => {
|
try {
|
const response = await activityUserAPI.deleteRegistrations(id);
|
if (response.code === 0) {
|
message.success('已移除报名者');
|
// 重新获取数据
|
fetchRegistrationData();
|
} else {
|
message.error('移除失败');
|
}
|
} catch (error) {
|
console.error('移除报名者失败:', error);
|
message.error('移除失败');
|
}
|
};
|
|
// 处理分页变化
|
const handleTableChange = (paginationInfo) => {
|
setPagination(prev => ({
|
...prev,
|
current: paginationInfo.current,
|
pageSize: paginationInfo.pageSize,
|
}));
|
fetchRegistrationData({
|
page: paginationInfo.current,
|
size: paginationInfo.pageSize,
|
});
|
};
|
|
if (!activityId) {
|
return (
|
<div style={{ textAlign: 'center', padding: '50px' }}>
|
<div>活动ID不存在</div>
|
<Button type="primary" onClick={() => navigate('/activities')} style={{ marginTop: '16px' }}>
|
返回活动列表
|
</Button>
|
</div>
|
);
|
}
|
|
return (
|
<div>
|
<div className="page-header">
|
<h1 className="page-title">报名管理</h1>
|
<p className="page-description">管理活动报名者,审核报名申请</p>
|
</div>
|
|
<Card>
|
<Table
|
columns={columns}
|
dataSource={registrations}
|
rowKey="id"
|
scroll={{ x: 1200 }}
|
loading={loading}
|
pagination={{
|
...pagination,
|
showSizeChanger: true,
|
showQuickJumper: true,
|
showTotal: (total, range) => `第 ${range[0]}-${range[1]} 条/共 ${total} 条`,
|
}}
|
onChange={handleTableChange}
|
/>
|
</Card>
|
</div>
|
);
|
};
|
|
export default RegistrationManagement;
|