Files
shz-admin/src/pages/Jobfair/Indoorjobfair/Detail/components/VenueLayoutModal.tsx

163 lines
7.3 KiB
TypeScript
Raw Normal View History

2026-06-24 09:06:09 +08:00
import React, { useState } from 'react';
import { Modal, Tag, Space, Card, Row, Col, Button, message } from 'antd';
import { CloseOutlined, CheckOutlined } from '@ant-design/icons';
import type { VenueItem } from '@/services/jobportal/indoorJobFair';
interface Props {
venue: VenueItem | null;
open: boolean;
onClose: () => void;
}
const VENUE_LAYOUT_DATA = [
// A区
{ id: 1, area: 'A', row: 1, col: 1, boothNumber: 'A01', status: 'reserved', companyName: '新疆天业(集团)有限公司' },
{ id: 2, area: 'A', row: 1, col: 2, boothNumber: 'A02', status: 'fixed', companyName: '石河子经济技术开发区管委会' },
{ id: 3, area: 'A', row: 1, col: 3, boothNumber: 'A03', status: 'available', companyName: '' },
{ id: 4, area: 'A', row: 1, col: 4, boothNumber: 'A04', status: 'reserved', companyName: '新疆西部牧业股份有限公司' },
{ id: 5, area: 'A', row: 2, col: 1, boothNumber: 'A05', status: 'available', companyName: '' },
{ id: 6, area: 'A', row: 2, col: 2, boothNumber: 'A06', status: 'locked', companyName: '' },
{ id: 7, area: 'A', row: 2, col: 3, boothNumber: 'A07', status: 'available', companyName: '' },
{ id: 8, area: 'A', row: 2, col: 4, boothNumber: 'A08', status: 'reserved', companyName: '兵团水利水电工程集团' },
// B区
{ id: 9, area: 'B', row: 1, col: 1, boothNumber: 'B01', status: 'available', companyName: '' },
{ id: 10, area: 'B', row: 1, col: 2, boothNumber: 'B02', status: 'fixed', companyName: '阿拉尔新爵纺织有限公司' },
{ id: 11, area: 'B', row: 1, col: 3, boothNumber: 'B03', status: 'locked', companyName: '' },
{ id: 12, area: 'B', row: 1, col: 4, boothNumber: 'B04', status: 'available', companyName: '' },
{ id: 13, area: 'B', row: 2, col: 1, boothNumber: 'B05', status: 'reserved', companyName: '新疆通用航空有限责任公司' },
{ id: 14, area: 'B', row: 2, col: 2, boothNumber: 'B06', status: 'available', companyName: '' },
{ id: 15, area: 'B', row: 2, col: 3, boothNumber: 'B07', status: 'reserved', companyName: '石河子市商业银行' },
{ id: 16, area: 'B', row: 2, col: 4, boothNumber: 'B08', status: 'available', companyName: '' },
];
const statusMap: Record<string, { text: string; color: string }> = {
available: { text: '可用', color: '#52c41a' },
fixed: { text: '固定', color: '#1890ff' },
reserved: { text: '预留', color: '#fa8c16' },
locked: { text: '锁定', color: '#ff4d4f' },
};
const VenueLayoutModal: React.FC<Props> = ({ venue, open, onClose }) => {
const [selectedBooth, setSelectedBooth] = useState<typeof VENUE_LAYOUT_DATA[0] | null>(null);
if (!venue) return null;
const areas = ['A', 'B'];
const handleBoothClick = (booth: typeof VENUE_LAYOUT_DATA[0]) => {
setSelectedBooth(booth);
};
const getBoothStyle = (status: string) => {
switch (status) {
case 'available':
return { backgroundColor: '#f6ffed', borderColor: '#52c41a' };
case 'fixed':
return { backgroundColor: '#e6f7ff', borderColor: '#1890ff' };
case 'reserved':
return { backgroundColor: '#fff7e6', borderColor: '#fa8c16' };
case 'locked':
return { backgroundColor: '#fff1f0', borderColor: '#ff4d4f' };
default:
return {};
}
};
return (
<Modal
title={`场地布局 - ${venue.venueName}`}
open={open}
onCancel={onClose}
footer={null}
width={900}
destroyOnClose
>
<div style={{ marginBottom: 16 }}>
<Space>
<Tag color="#52c41a"></Tag>
<Tag color="#1890ff"></Tag>
<Tag color="#fa8c16"></Tag>
<Tag color="#ff4d4f"></Tag>
</Space>
<span style={{ marginLeft: 24, color: '#888' }}>
{venue.boothCount} | 使 {VENUE_LAYOUT_DATA.filter(b => b.status !== 'available').length} | {VENUE_LAYOUT_DATA.filter(b => b.status === 'available').length}
</span>
</div>
<Row gutter={16}>
<Col span={16}>
<Card size="small" title="平面布局图" style={{ marginBottom: 16 }}>
{areas.map((area) => (
<div key={area} style={{ marginBottom: 16 }}>
<div style={{ fontWeight: 'bold', marginBottom: 8 }}>{area}</div>
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(4, 1fr)', gap: 8 }}>
{VENUE_LAYOUT_DATA.filter(b => b.area === area).map((booth) => (
<div
key={booth.id}
onClick={() => handleBoothClick(booth)}
style={{
...getBoothStyle(booth.status),
border: '1px solid',
borderRadius: 4,
padding: '8px 4px',
textAlign: 'center',
cursor: 'pointer',
minHeight: 60,
display: 'flex',
flexDirection: 'column',
justifyContent: 'center',
alignItems: 'center',
}}
>
<div style={{ fontSize: 12, fontWeight: 'bold' }}>{booth.boothNumber}</div>
{booth.companyName ? (
<div style={{ fontSize: 10, color: '#666', marginTop: 2, maxWidth: 80, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{booth.companyName}
</div>
) : (
<div style={{ fontSize: 10, color: '#999' }}>{statusMap[booth.status].text}</div>
)}
</div>
))}
</div>
</div>
))}
</Card>
</Col>
<Col span={8}>
<Card size="small" title="展位详情">
{selectedBooth ? (
<div>
<p><strong></strong>{selectedBooth.boothNumber}</p>
<p><strong></strong><Tag color={statusMap[selectedBooth.status].color}>{statusMap[selectedBooth.status].text}</Tag></p>
<p><strong></strong>{selectedBooth.area} {selectedBooth.row} {selectedBooth.col}</p>
<p><strong></strong>{selectedBooth.companyName || '--'}</p>
<Space style={{ marginTop: 16 }}>
<Button size="small" icon={<CheckOutlined />}></Button>
<Button size="small" icon={<CloseOutlined />}></Button>
</Space>
</div>
) : (
<div style={{ color: '#999', textAlign: 'center', padding: 20 }}>
</div>
)}
</Card>
<Card size="small" title="场地信息" style={{ marginTop: 16 }}>
<p><strong></strong>{venue.venueName}</p>
<p><strong></strong>{venue.employmentAgency}</p>
<p><strong></strong>{venue.venueType}</p>
<p><strong></strong>{venue.venueAddress}</p>
<p><strong></strong>{venue.contactPerson}</p>
<p><strong></strong>{venue.contactPhone}</p>
</Card>
</Col>
</Row>
</Modal>
);
};
export default VenueLayoutModal;