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
235 lines
9.5 KiB
TypeScript
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;
|