Files
shz-admin/src/pages/Jobfair/Outdoorfair/Detail/components/FairInfoTab.tsx
francis-fh e7616b0c8e
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
11
2026-06-18 02:30:11 +08:00

235 lines
9.5 KiB
TypeScript

import React, { useRef, useState } from 'react';
import { useAccess } from '@umijs/max';
import { Button, Card, Descriptions, List, Tag, message, Modal, Space } from 'antd';
import { ActionType, ProTable } from '@ant-design/pro-components';
import { PlusOutlined, DeleteOutlined, FormOutlined } from '@ant-design/icons';
import type { OutdoorFairItem } from '@/services/jobportal/outdoorFair';
import { updateOutdoorFair } from '@/services/jobportal/outdoorFair';
import {
getParticipatingCompanies,
addParticipatingCompany,
removeParticipatingCompany,
addJobForCompany,
updateJobForCompany,
removeJobFromCompany,
} from '@/services/jobportal/outdoorFairDetail';
import EditModal from '@/pages/Jobfair/Outdoorfair/components/EditModal';
import CompanyAddModal from './CompanyAddModal';
import JobEditModal from './JobEditModal';
interface Props {
fairId: number;
fairInfo: OutdoorFairItem;
onFairUpdate: () => void;
}
const FairInfoTab: React.FC<Props> = ({ fairId, fairInfo, onFairUpdate }) => {
const access = useAccess();
const actionRef = useRef<ActionType>();
const [editModalOpen, setEditModalOpen] = useState(false);
const [companyModalOpen, setCompanyModalOpen] = useState(false);
const [jobModalOpen, setJobModalOpen] = useState(false);
const [selectedCompany, setSelectedCompany] = useState<any>(null);
const [editingJob, setEditingJob] = useState<any>(null);
const fairTypeColors: Record<string, string> = {
'综合类': 'blue', '校园招聘': 'green', '行业专场': 'orange',
'高新技术专场': 'purple', '智能制造专场': 'cyan', '文旅专场': 'magenta',
'其他': 'default',
};
return (
<div>
{/* 基本信息卡片 */}
<Card
title="基本信息"
extra={
<Button
type="primary"
size="small"
icon={<FormOutlined />}
hidden={!access.hasPerms('cms:outdoorFair:edit')}
onClick={() => setEditModalOpen(true)}
>
</Button>
}
style={{ marginBottom: 16 }}
>
<Descriptions column={3} bordered size="small">
<Descriptions.Item label="招聘会标题" span={3}>{fairInfo.title}</Descriptions.Item>
<Descriptions.Item label="举办单位">{fairInfo.hostUnit}</Descriptions.Item>
<Descriptions.Item label="招聘会类型">
<Tag color={fairTypeColors[fairInfo.fairType] || 'default'}>{fairInfo.fairType}</Tag>
</Descriptions.Item>
<Descriptions.Item label="举办区域">{fairInfo.region}</Descriptions.Item>
<Descriptions.Item label="举办地址" span={2}>{fairInfo.address}</Descriptions.Item>
<Descriptions.Item label="展位数量">{fairInfo.boothCount}</Descriptions.Item>
<Descriptions.Item label="举办时间">{fairInfo.holdTime}</Descriptions.Item>
<Descriptions.Item label="截止时间">{fairInfo.endTime}</Descriptions.Item>
<Descriptions.Item label="开放申请">{fairInfo.applyStartTime}</Descriptions.Item>
<Descriptions.Item label="截止申请">{fairInfo.applyEndTime}</Descriptions.Item>
<Descriptions.Item label="线上申请">{fairInfo.onlineApply ? '是' : '否'}</Descriptions.Item>
</Descriptions>
</Card>
{/* 参会企业及岗位 */}
<Card
title="参会企业及岗位"
extra={
<Button
type="primary"
icon={<PlusOutlined />}
onClick={() => setCompanyModalOpen(true)}
>
</Button>
}
>
<ProTable
actionRef={actionRef}
rowKey="id"
search={false}
options={false}
pagination={{ pageSize: 10 }}
request={async (params) => {
const res = await getParticipatingCompanies(fairId, {
current: params.current,
pageSize: params.pageSize,
companyName: params.companyName,
});
return { data: res.rows, total: res.total, success: true };
}}
expandable={{
expandedRowRender: (record) => (
<div style={{ padding: '0 24px' }}>
{record.jobList.length === 0 ? (
<p style={{ color: '#999' }}></p>
) : (
<List
dataSource={record.jobList}
renderItem={(job: any) => (
<List.Item
actions={[
<Button
key="edit" type="link" size="small"
onClick={() => { setEditingJob(job); setSelectedCompany(record); setJobModalOpen(true); }}
>
</Button>,
<Button
key="delete" type="link" size="small" danger
onClick={() => {
Modal.confirm({
title: '确认删除',
content: `确定删除岗位「${job.jobTitle}」吗?`,
onOk: async () => {
const res = await removeJobFromCompany(job.id);
if (res.code === 200) { message.success('删除成功'); actionRef.current?.reload(); }
},
});
}}
>
</Button>,
]}
>
<List.Item.Meta
title={job.jobTitle}
description={
<Space>
<Tag color="blue"> {job.minSalary}-{job.maxSalary}K</Tag>
<Tag>{job.education}</Tag>
<Tag>{job.experience}</Tag>
<Tag> {job.vacancies} </Tag>
<Tag color={job.status === 'active' ? 'green' : 'red'}>
{job.status === 'active' ? '在招' : '已关闭'}
</Tag>
</Space>
}
/>
</List.Item>
)}
/>
)}
</div>
),
}}
columns={[
{ title: '企业名称', dataIndex: 'companyName', ellipsis: true },
{ title: '行业', dataIndex: 'industry', width: 100, hideInSearch: true,
render: (_, r: any) => <Tag>{r.industry}</Tag> },
{ title: '规模', dataIndex: 'scale', width: 110, hideInSearch: true },
{ title: '联系人', dataIndex: 'contactPerson', width: 100, hideInSearch: true },
{ title: '联系电话', dataIndex: 'contactPhone', width: 130, hideInSearch: true },
{ title: '展位号', dataIndex: 'boothNumber', width: 80, hideInSearch: true,
render: (_, r: any) => r.boothNumber || '--' },
{ title: '岗位数', width: 80, hideInSearch: true,
render: (_, r: any) => r.jobList?.length || 0 },
{
title: '操作', valueType: 'option', width: 200,
render: (_, record: any) => [
<Button key="addJob" type="link" size="small"
onClick={() => { setEditingJob(null); setSelectedCompany(record); setJobModalOpen(true); }}
>
</Button>,
<Button key="remove" type="link" size="small" danger
onClick={() => {
Modal.confirm({
title: '确认移除', content: `确定移除「${record.companyName}」吗?`,
onOk: async () => {
const res = await removeParticipatingCompany(record.id);
if (res.code === 200) { message.success('移除成功'); actionRef.current?.reload(); }
},
});
}}
>
</Button>,
],
},
]}
/>
</Card>
{/* 编辑招聘会基本信息弹窗 */}
<EditModal
open={editModalOpen}
values={fairInfo}
onCancel={() => setEditModalOpen(false)}
onSubmit={async (values) => {
const res = await updateOutdoorFair(values as any);
if (res.code === 200) {
message.success('修改成功');
setEditModalOpen(false);
onFairUpdate();
} else {
message.error(res.msg || '操作失败');
}
}}
/>
{/* 添加企业弹窗 */}
<CompanyAddModal
open={companyModalOpen}
fairId={fairId}
onCancel={() => setCompanyModalOpen(false)}
onSuccess={() => { setCompanyModalOpen(false); actionRef.current?.reload(); }}
/>
{/* 添加/编辑岗位弹窗 */}
<JobEditModal
open={jobModalOpen}
fairId={fairId}
company={selectedCompany}
job={editingJob}
onCancel={() => { setJobModalOpen(false); setEditingJob(null); setSelectedCompany(null); }}
onSuccess={() => { setJobModalOpen(false); setEditingJob(null); actionRef.current?.reload(); }}
/>
</div>
);
};
export default FairInfoTab;