招聘会
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

This commit is contained in:
2026-01-11 10:00:56 +08:00
parent caa72e1b76
commit b7d252fcf9
11 changed files with 1076 additions and 2 deletions

8
.idea/modules.xml generated Normal file
View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/shz-admin.iml" filepath="$PROJECT_DIR$/.idea/shz-admin.iml" />
</modules>
</component>
</project>

View File

@@ -15,8 +15,8 @@ export default {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': {
// 要代理的地址
target: 'http://36.105.163.21:30081/api/ks', // 发版
// target: 'http://wykj.cdwsx.com/api',// 后端
// target: 'http://localhost:9091', // 本地代理
target: 'http://wykj.cdwsx.com/api',// 后端
// target: 'http://ks.zhaopinzao8dian.com/api/ks',
// 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie

View File

@@ -162,5 +162,26 @@ export default [
},
],
},
{
name: 'jobfair',
path: '/jobfair',
routes: [
{
name: '公共招聘会列表',
path: '/jobfair/public-job-fair',
component: './Jobfair/PublicJobFair',
},
{
name: '招聘会详情',
path: '/jobfair/public-job-fair/detail',
component: './Jobfair/PublicJobFair/Detail',
},
{
name: '报名人员',
path: '/jobfair/public-job-fair/signups',
component: './Jobfair/PublicJobFair/Signups',
},
],
},
];

View File

@@ -0,0 +1,217 @@
import React, { useEffect, useState } from 'react';
import { history, useSearchParams } from '@umijs/max';
import { Button, Card, Collapse, Descriptions, message, Modal, Space, Tag, List } from 'antd';
import { PageContainer } from '@ant-design/pro-components';
import { ArrowLeftOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import {
getPublicJobFairDetail,
removeCompanyFromJobFair,
removeJobFromJobFair,
} from '@/services/jobfair/publicJobFair';
import CompanySelectModal from '../components/CompanySelectModal';
import JobSelectModal from '../components/JobSelectModal';
const JobFairDetail: React.FC = () => {
const [searchParams] = useSearchParams();
const jobFairId = searchParams.get('id') || '';
const [detail, setDetail] = useState<API.PublicJobFair.JobFairItem & { companyList?: API.PublicJobFair.CompanyInfo[] }>();
const [loading, setLoading] = useState(false);
const [companyModalOpen, setCompanyModalOpen] = useState(false);
const [jobModalOpen, setJobModalOpen] = useState(false);
const [currentCompany, setCurrentCompany] = useState<API.PublicJobFair.CompanyInfo>();
const fetchDetail = async () => {
if (!jobFairId) return;
setLoading(true);
const res = await getPublicJobFairDetail(jobFairId);
setLoading(false);
if (res.code === 200) {
setDetail(res.data);
}
};
useEffect(() => {
fetchDetail();
}, [jobFairId]);
const handleRemoveCompany = (id: string) => {
Modal.confirm({
title: '确认移除',
content: '确定要移除该企业吗?',
onOk: async () => {
const res = await removeCompanyFromJobFair(id);
if (res.code === 200) {
message.success('移除成功');
fetchDetail();
} else {
message.error(res.msg || '移除失败');
}
},
});
};
const handleRemoveJob = (id: string) => {
Modal.confirm({
title: '确认移除',
content: '确定要移除该岗位吗?',
onOk: async () => {
const res = await removeJobFromJobFair(id);
if (res.code === 200) {
message.success('移除成功');
fetchDetail();
} else {
message.error(res.msg || '移除失败');
}
},
});
};
const jobFairTypeMap: Record<string, string> = { '1': '线上', '2': '线下' };
return (
<PageContainer
loading={loading}
header={{
title: `招聘会详情: ${detail?.jobFairTitle || ''}`,
extra: [
<Button key="back" icon={<ArrowLeftOutlined />} onClick={() => history.back()}>
</Button>,
],
}}
>
<Card title="基本信息" style={{ marginBottom: 16 }} extra={
<Button onClick={() => history.push(`/jobfair/public-job-fair/signups?id=${jobFairId}`)}>
</Button>
}>
<Descriptions column={2}>
<Descriptions.Item label="标题">{detail?.jobFairTitle}</Descriptions.Item>
<Descriptions.Item label="类型">
<Tag color={detail?.jobFairType === '1' ? 'blue' : 'green'}>
{jobFairTypeMap[detail?.jobFairType || '']}
</Tag>
</Descriptions.Item>
<Descriptions.Item label="地址">{detail?.jobFairAddress}</Descriptions.Item>
<Descriptions.Item label="联系电话">{detail?.jobFairPhone}</Descriptions.Item>
<Descriptions.Item label="招聘会时间">
{detail?.jobFairStartTime} ~ {detail?.jobFairEndTime}
</Descriptions.Item>
<Descriptions.Item label="报名时间">
{detail?.jobFairSignUpStartTime} ~ {detail?.jobFairSignUpEndTime}
</Descriptions.Item>
<Descriptions.Item label="主办单位">{detail?.jobFairHostUnit}</Descriptions.Item>
<Descriptions.Item label="协办单位">{detail?.jobFairCoOrganizer}</Descriptions.Item>
<Descriptions.Item label="承办单位" span={2}>{detail?.jobFairOrganizer}</Descriptions.Item>
<Descriptions.Item label="简介" span={2}>{detail?.jobFairIntroduction}</Descriptions.Item>
</Descriptions>
</Card>
<Card
title="参会企业及岗位"
extra={
<Button type="primary" icon={<PlusOutlined />} onClick={() => setCompanyModalOpen(true)}>
</Button>
}
>
{detail?.companyList?.length ? (
<Collapse>
{detail.companyList.map((company) => (
<Collapse.Panel
key={company.id}
header={
<Space>
<span style={{ fontWeight: 500 }}>{company.companyName}</span>
<Tag>{company.industry}</Tag>
<Tag>{company.scale}</Tag>
</Space>
}
extra={
<Space onClick={(e) => e.stopPropagation()}>
<Button
size="small"
icon={<PlusOutlined />}
onClick={() => {
setCurrentCompany(company);
setJobModalOpen(true);
}}
>
</Button>
<Button
size="small"
danger
icon={<DeleteOutlined />}
onClick={() => handleRemoveCompany(company.id)}
>
</Button>
</Space>
}
>
<List
size="small"
dataSource={company.jobInfoList || []}
renderItem={(job) => (
<List.Item
actions={[
<Button
key="remove"
type="link"
danger
size="small"
onClick={() => handleRemoveJob(job.id!)}
>
</Button>,
]}
>
<Space>
<span>{job.jobTitle}</span>
<Tag color="orange">{job.minSalary}K-{job.maxSalary}K</Tag>
<Tag>{job.education}</Tag>
<Tag>{job.vacancies}</Tag>
</Space>
</List.Item>
)}
locale={{ emptyText: '暂无岗位' }}
/>
</Collapse.Panel>
))}
</Collapse>
) : (
<div style={{ textAlign: 'center', padding: 24, color: '#999' }}></div>
)}
</Card>
<CompanySelectModal
open={companyModalOpen}
jobFairId={jobFairId}
onCancel={() => setCompanyModalOpen(false)}
onSuccess={() => {
setCompanyModalOpen(false);
fetchDetail();
}}
/>
<JobSelectModal
open={jobModalOpen}
jobFairId={jobFairId}
company={currentCompany}
onCancel={() => {
setJobModalOpen(false);
setCurrentCompany(undefined);
}}
onSuccess={() => {
setJobModalOpen(false);
setCurrentCompany(undefined);
fetchDetail();
}}
/>
</PageContainer>
);
};
export default JobFairDetail;

View File

@@ -0,0 +1,75 @@
import React, { useEffect, useState } from 'react';
import { history, useSearchParams } from '@umijs/max';
import { Button, Tag } from 'antd';
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { ArrowLeftOutlined, ExportOutlined } from '@ant-design/icons';
import { getJobFairSignups, getPublicJobFairDetail } from '@/services/jobfair/publicJobFair';
const SignupList: React.FC = () => {
const [searchParams] = useSearchParams();
const jobFairId = searchParams.get('id') || '';
const [jobFairTitle, setJobFairTitle] = useState('');
useEffect(() => {
if (jobFairId) {
getPublicJobFairDetail(jobFairId).then((res) => {
if (res.code === 200) {
setJobFairTitle(res.data.jobFairTitle);
}
});
}
}, [jobFairId]);
const statusMap: Record<string, { text: string; color: string }> = {
'0': { text: '已报名', color: 'green' },
'1': { text: '已取消', color: 'red' },
};
const columns: ProColumns<API.PublicJobFair.SignupItem>[] = [
{ title: '用户名', dataIndex: 'userName' },
{ title: '姓名', dataIndex: 'realName', hideInSearch: true },
{ title: '手机号', dataIndex: 'phone', hideInSearch: true },
{ title: '报名时间', dataIndex: 'signUpTime', valueType: 'dateTime', hideInSearch: true },
{
title: '状态',
dataIndex: 'status',
valueType: 'select',
valueEnum: { '0': '已报名', '1': '已取消' },
render: (_, record) => (
<Tag color={statusMap[record.status]?.color}>{statusMap[record.status]?.text}</Tag>
),
},
];
return (
<PageContainer
header={{
title: `报名人员 - ${jobFairTitle}`,
extra: [
<Button key="back" icon={<ArrowLeftOutlined />} onClick={() => history.back()}>
</Button>,
],
}}
>
<ProTable<API.PublicJobFair.SignupItem>
rowKey="id"
columns={columns}
request={async (params) => {
const res = await getJobFairSignups(jobFairId, {
userName: params.userName,
status: params.status,
});
return { data: res.rows, total: res.total, success: true };
}}
toolBarRender={() => [
<Button key="export" icon={<ExportOutlined />}>
</Button>,
]}
/>
</PageContainer>
);
};
export default SignupList;

View File

@@ -0,0 +1,83 @@
import React, { useRef, useState } from 'react';
import { Modal, message } from 'antd';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { getCmsCompanyList } from '@/services/company/list';
import { batchAddCompanyToJobFair } from '@/services/jobfair/publicJobFair';
interface CompanySelectModalProps {
open: boolean;
jobFairId: string;
onCancel: () => void;
onSuccess: () => void;
}
const CompanySelectModal: React.FC<CompanySelectModalProps> = ({ open, jobFairId, onCancel, onSuccess }) => {
const actionRef = useRef<ActionType>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [loading, setLoading] = useState(false);
const handleOk = async () => {
if (!selectedRowKeys.length) {
message.warning('请选择企业');
return;
}
setLoading(true);
const data = selectedRowKeys.map((companyId) => ({
jobFairId,
companyId: companyId as number,
}));
const res = await batchAddCompanyToJobFair(data);
setLoading(false);
if (res.code === 200) {
message.success('添加成功');
setSelectedRowKeys([]);
onSuccess();
} else {
message.error(res.msg || '添加失败');
}
};
const columns: ProColumns[] = [
{ title: '企业名称', dataIndex: 'name', ellipsis: true },
{ title: '行业', dataIndex: 'industry', hideInSearch: true },
{ title: '规模', dataIndex: 'scale', hideInSearch: true },
{ title: '类型', dataIndex: 'companyType', hideInSearch: true },
];
return (
<Modal
title="选择企业"
open={open}
width={800}
onCancel={() => {
setSelectedRowKeys([]);
onCancel();
}}
onOk={handleOk}
okText="确定添加"
confirmLoading={loading}
destroyOnClose
>
<ProTable
actionRef={actionRef}
rowKey="companyId"
columns={columns}
search={{ labelWidth: 'auto' }}
pagination={{ pageSize: 5 }}
rowSelection={{
selectedRowKeys,
onChange: setSelectedRowKeys,
}}
request={async (params) => {
const res = await getCmsCompanyList({
name: params.name,
} as any);
return { data: res.rows, total: res.total, success: true };
}}
toolBarRender={false}
/>
</Modal>
);
};
export default CompanySelectModal;

View File

@@ -0,0 +1,129 @@
import React, { useEffect, useState } from 'react';
import {
ModalForm,
ProForm,
ProFormText,
ProFormTextArea,
ProFormRadio,
ProFormDateTimePicker,
} from '@ant-design/pro-components';
import { Button, Form } from 'antd';
import ProFromMap from '@/components/ProFromMap';
interface EditModalProps {
open: boolean;
values?: API.PublicJobFair.JobFairItem;
jobFairTypeEnum: any;
onCancel: () => void;
onSubmit: (values: API.PublicJobFair.JobFairForm) => Promise<void>;
}
const EditModal: React.FC<EditModalProps> = ({ open, values, jobFairTypeEnum, onCancel, onSubmit }) => {
const [form] = Form.useForm();
const [mapOpen, setMapOpen] = useState(false);
const [locationInfo, setLocationInfo] = useState<{ address?: string; latitude?: number; longitude?: number }>({});
useEffect(() => {
if (open) {
form.resetFields();
if (values) {
form.setFieldsValue(values);
setLocationInfo({
address: values.jobFairAddress,
latitude: values.latitude,
longitude: values.longitude,
});
} else {
setLocationInfo({});
}
}
}, [open, values, form]);
const handleMapSelect = (result: any) => {
if (result?.location) {
const { lat, lng } = result.location;
form.setFieldsValue({
latitude: lat,
longitude: lng,
jobFairAddress: result.address,
});
setLocationInfo({ address: result.address, latitude: lat, longitude: lng });
setMapOpen(false);
}
};
return (
<ModalForm
title={values ? '编辑招聘会' : '新增招聘会'}
form={form}
open={open}
width={700}
modalProps={{ destroyOnClose: true, onCancel }}
onFinish={async (formValues) => {
await onSubmit({ ...formValues, jobFairId: values?.jobFairId } as API.PublicJobFair.JobFairForm);
}}
>
<ProFormText name="jobFairId" hidden />
<ProFormText
name="jobFairTitle"
label="招聘会标题"
rules={[{ required: true, message: '请输入招聘会标题' }]}
placeholder="请输入招聘会标题"
/>
<ProFormText
name="jobFairAddress"
label="招聘会地址"
rules={[{ required: true, message: '请输入招聘会地址' }]}
placeholder="请输入招聘会地址"
/>
<ProFormRadio.Group
name="jobFairType"
label="招聘会类型"
valueEnum={jobFairTypeEnum}
rules={[{ required: true, message: '请选择招聘会类型' }]}
/>
<ProForm.Group>
<ProFormDateTimePicker
name="jobFairStartTime"
label="开始时间"
width="md"
rules={[{ required: true, message: '请选择开始时间' }]}
/>
<ProFormDateTimePicker
name="jobFairEndTime"
label="结束时间"
width="md"
rules={[{ required: true, message: '请选择结束时间' }]}
/>
</ProForm.Group>
<ProForm.Group>
<ProFormDateTimePicker name="jobFairSignUpStartTime" label="报名开始时间" width="md" />
<ProFormDateTimePicker name="jobFairSignUpEndTime" label="报名结束时间" width="md" />
</ProForm.Group>
<ProForm.Group>
<ProFormText name="jobFairHostUnit" label="主办单位" width="md" placeholder="请输入主办单位" />
<ProFormText name="jobFairCoOrganizer" label="协办单位" width="md" placeholder="请输入协办单位" />
</ProForm.Group>
<ProForm.Group>
<ProFormText name="jobFairOrganizer" label="承办单位" width="md" placeholder="请输入承办单位" />
<ProFormText name="jobFairPhone" label="联系电话" width="md" placeholder="请输入联系电话" />
</ProForm.Group>
<ProFormTextArea name="jobFairIntroduction" label="招聘会简介" placeholder="请输入招聘会简介" />
<ProForm.Item label="地图选点">
<Button onClick={() => setMapOpen(true)}></Button>
{locationInfo.latitude && (
<div style={{ marginTop: 8, color: '#666' }}>
{locationInfo.address} | {locationInfo.longitude} | {locationInfo.latitude}
</div>
)}
</ProForm.Item>
<ProFormText name="latitude" hidden />
<ProFormText name="longitude" hidden />
<ProFromMap open={mapOpen} onSelect={handleMapSelect} onCancel={() => setMapOpen(false)} />
</ModalForm>
);
};
export default EditModal;

View File

@@ -0,0 +1,91 @@
import React, { useRef, useState } from 'react';
import { Modal, message } from 'antd';
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
import { batchAddJobToJobFair } from '@/services/jobfair/publicJobFair';
import { getCmsJobList } from '@/services/Management/list';
interface JobSelectModalProps {
open: boolean;
jobFairId: string;
company?: API.PublicJobFair.CompanyInfo;
onCancel: () => void;
onSuccess: () => void;
}
const JobSelectModal: React.FC<JobSelectModalProps> = ({ open, jobFairId, company, onCancel, onSuccess }) => {
const actionRef = useRef<ActionType>();
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
const [loading, setLoading] = useState(false);
const handleOk = async () => {
if (!selectedRowKeys.length) {
message.warning('请选择岗位');
return;
}
if (!company) return;
setLoading(true);
const data = selectedRowKeys.map((jobId) => ({
jobFairId,
jobId: jobId as number,
companyId: company.companyId,
}));
const res = await batchAddJobToJobFair(data);
setLoading(false);
if (res.code === 200) {
message.success('添加成功');
setSelectedRowKeys([]);
onSuccess();
} else {
message.error(res.msg || '添加失败');
}
};
const columns: ProColumns[] = [
{ title: '岗位名称', dataIndex: 'jobTitle', ellipsis: true },
{ title: '薪资', dataIndex: 'salary', hideInSearch: true, render: (_, r) => `${r.minSalary || 0}K-${r.maxSalary || 0}K` },
{ title: '学历', dataIndex: 'education', hideInSearch: true },
{ title: '经验', dataIndex: 'experience', hideInSearch: true },
{ title: '招聘人数', dataIndex: 'vacancies', hideInSearch: true },
];
return (
<Modal
title={`选择岗位 - ${company?.companyName || ''}`}
open={open}
width={800}
onCancel={() => {
setSelectedRowKeys([]);
onCancel();
}}
onOk={handleOk}
okText="确定添加"
confirmLoading={loading}
destroyOnClose
>
<ProTable
actionRef={actionRef}
rowKey="jobId"
columns={columns}
search={{ labelWidth: 'auto' }}
pagination={{ pageSize: 5 }}
rowSelection={{
selectedRowKeys,
onChange: setSelectedRowKeys,
}}
request={async (params) => {
if (!company?.companyId) return { data: [], total: 0, success: true };
const res = await getCmsJobList({
current: params.current,
pageSize: params.pageSize,
companyId: company.companyId,
jobTitle: params.jobTitle,
} as any);
return { data: res.rows, total: res.total, success: true };
}}
toolBarRender={false}
/>
</Modal>
);
};
export default JobSelectModal;

View File

@@ -0,0 +1,208 @@
import React, { useRef, useState, useEffect } from 'react';
import { useAccess, history } from '@umijs/max';
import { Button, message, Modal } from 'antd';
import { ActionType, PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { PlusOutlined, DeleteOutlined, FormOutlined, ExportOutlined, EyeOutlined } from '@ant-design/icons';
import { getDictValueEnum } from '@/services/system/dict';
import DictTag from '@/components/DictTag';
import {
getPublicJobFairList,
getPublicJobFairDetail,
addPublicJobFair,
updatePublicJobFair,
deletePublicJobFair,
exportPublicJobFair,
} from '@/services/jobfair/publicJobFair';
import EditModal from './components/EditModal';
const PublicJobFairList: React.FC = () => {
const access = useAccess();
const actionRef = useRef<ActionType>();
const [modalVisible, setModalVisible] = useState(false);
const [currentRow, setCurrentRow] = useState<API.PublicJobFair.JobFairItem>();
const [jobFairTypeEnum, setJobFairTypeEnum] = useState<any>({});
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
useEffect(() => {
getDictValueEnum('job_fair_type', true).then(setJobFairTypeEnum);
}, []);
const handleDelete = async (ids: string) => {
Modal.confirm({
title: '确认删除',
content: '确定要删除选中的招聘会吗?',
onOk: async () => {
const res = await deletePublicJobFair(ids);
if (res.code === 200) {
message.success('删除成功');
actionRef.current?.reload();
setSelectedRowKeys([]);
} else {
message.error(res.msg || '删除失败');
}
},
});
};
const handleExport = async () => {
message.loading('正在导出...');
try {
await exportPublicJobFair();
message.success('导出成功');
} catch {
message.error('导出失败');
}
};
const columns: ProColumns<API.PublicJobFair.JobFairItem>[] = [
{
title: '招聘会标题',
dataIndex: 'jobFairTitle',
ellipsis: true,
},
{
title: '地址',
dataIndex: 'jobFairAddress',
hideInSearch: true,
ellipsis: true,
},
{
title: '类型',
dataIndex: 'jobFairType',
valueType: 'select',
valueEnum: jobFairTypeEnum,
render: (_, record) => <DictTag enums={jobFairTypeEnum} value={record.jobFairType} />,
},
{
title: '开始时间',
dataIndex: 'jobFairStartTime',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '结束时间',
dataIndex: 'jobFairEndTime',
valueType: 'dateTime',
hideInSearch: true,
},
{
title: '操作',
valueType: 'option',
width: 150,
render: (_, record) => [
<Button
key="detail"
type="link"
size="small"
icon={<EyeOutlined />}
onClick={() => history.push(`/jobfair/public-job-fair/detail?id=${record.jobFairId}`)}
>
</Button>,
<Button
key="edit"
type="link"
size="small"
icon={<FormOutlined />}
hidden={!access.hasPerms('cms:publicJobFair:edit')}
onClick={async () => {
const res = await getPublicJobFairDetail(record.jobFairId);
if (res.code === 200) {
setCurrentRow(res.data);
setModalVisible(true);
}
}}
>
</Button>,
<Button
key="delete"
type="link"
size="small"
danger
icon={<DeleteOutlined />}
hidden={!access.hasPerms('cms:publicJobFair:remove')}
onClick={() => handleDelete(record.jobFairId)}
>
</Button>,
],
},
];
return (
<PageContainer>
<ProTable<API.PublicJobFair.JobFairItem>
headerTitle="公共招聘会列表"
actionRef={actionRef}
rowKey="jobFairId"
columns={columns}
rowSelection={{
selectedRowKeys,
onChange: setSelectedRowKeys,
}}
request={async (params) => {
const res = await getPublicJobFairList({
pageNum: params.current,
pageSize: params.pageSize,
jobFairTitle: params.jobFairTitle,
jobFairType: params.jobFairType,
});
return { data: res.rows, total: res.total, success: true };
}}
toolBarRender={() => [
<Button
key="add"
type="primary"
icon={<PlusOutlined />}
hidden={!access.hasPerms('cms:publicJobFair:add')}
onClick={() => {
setCurrentRow(undefined);
setModalVisible(true);
}}
>
</Button>,
selectedRowKeys.length > 0 && (
<Button
key="batchDelete"
danger
icon={<DeleteOutlined />}
hidden={!access.hasPerms('cms:publicJobFair:remove')}
onClick={() => handleDelete(selectedRowKeys.join(','))}
>
</Button>
),
<Button key="export" icon={<ExportOutlined />} onClick={handleExport}>
</Button>,
]}
/>
<EditModal
open={modalVisible}
values={currentRow}
jobFairTypeEnum={jobFairTypeEnum}
onCancel={() => {
setModalVisible(false);
setCurrentRow(undefined);
}}
onSubmit={async (values) => {
const res = values.jobFairId
? await updatePublicJobFair(values)
: await addPublicJobFair(values);
if (res.code === 200) {
message.success(values.jobFairId ? '修改成功' : '新增成功');
setModalVisible(false);
setCurrentRow(undefined);
actionRef.current?.reload();
} else {
message.error(res.msg || '操作失败');
}
}}
/>
</PageContainer>
);
};
export default PublicJobFairList;

View File

@@ -0,0 +1,109 @@
import { request } from '@umijs/max';
import { downLoadXlsx } from '@/utils/downloadfile';
const BASE_URL = '/api/cms/publicJobFair';
/** 查询招聘会列表 */
export async function getPublicJobFairList(params?: API.PublicJobFair.ListParams) {
return request<API.PublicJobFair.ListResult>(`${BASE_URL}/list`, {
method: 'GET',
params,
});
}
/** 获取招聘会详情 */
export async function getPublicJobFairDetail(jobFairId: string) {
return request<API.PublicJobFair.DetailResult>(`${BASE_URL}/${jobFairId}`, {
method: 'GET',
});
}
/** 新增招聘会 */
export async function addPublicJobFair(data: API.PublicJobFair.JobFairForm) {
return request<API.PublicJobFair.CommonResult>(BASE_URL, {
method: 'POST',
data,
});
}
/** 修改招聘会 */
export async function updatePublicJobFair(data: API.PublicJobFair.JobFairForm) {
return request<API.PublicJobFair.CommonResult>(BASE_URL, {
method: 'PUT',
data,
});
}
/** 删除招聘会 */
export async function deletePublicJobFair(jobFairIds: string) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/${jobFairIds}`, {
method: 'DELETE',
});
}
/** 添加企业到招聘会 */
export async function addCompanyToJobFair(data: API.PublicJobFair.AddCompanyParams) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/company`, {
method: 'POST',
data,
});
}
/** 批量添加企业到招聘会 */
export async function batchAddCompanyToJobFair(data: API.PublicJobFair.AddCompanyParams[]) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/company/batch`, {
method: 'POST',
data,
});
}
/** 移除招聘会企业 */
export async function removeCompanyFromJobFair(id: string) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/company/${id}`, {
method: 'DELETE',
});
}
/** 添加岗位到招聘会 */
export async function addJobToJobFair(data: API.PublicJobFair.AddJobParams) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/job`, {
method: 'POST',
data,
});
}
/** 批量添加岗位到招聘会 */
export async function batchAddJobToJobFair(data: API.PublicJobFair.AddJobParams[]) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/job/batch`, {
method: 'POST',
data,
});
}
/** 移除招聘会岗位 */
export async function removeJobFromJobFair(id: string) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/job/${id}`, {
method: 'DELETE',
});
}
/** 查询招聘会报名列表 */
export async function getJobFairSignups(jobFairId: string, params?: { userName?: string; status?: string }) {
return request<API.PublicJobFair.SignupListResult>(`${BASE_URL}/signups/${jobFairId}`, {
method: 'GET',
params,
});
}
/** 查询招聘会企业及岗位 */
export async function getJobFairCompanies(jobFairId: string) {
return request<API.PublicJobFair.CommonResult>(`${BASE_URL}/companies/${jobFairId}`, {
method: 'GET',
});
}
/** 导出招聘会 */
export async function exportPublicJobFair(params?: API.PublicJobFair.ListParams) {
return downLoadXlsx(`${BASE_URL}/export`, { params }, `job_fair_${new Date().getTime()}.xlsx`);
}

133
src/types/jobfair/publicJobFair.d.ts vendored Normal file
View File

@@ -0,0 +1,133 @@
/**
* 公共招聘会管理类型定义
*/
declare namespace API.PublicJobFair {
/** 招聘会列表查询参数 */
export interface ListParams {
pageNum?: number;
pageSize?: number;
jobFairTitle?: string;
jobFairType?: string;
}
/** 招聘会列表项 */
export interface JobFairItem {
jobFairId: string;
jobFairTitle: string;
jobFairAddress: string;
jobFairType: string;
jobFairStartTime: string;
jobFairEndTime: string;
jobFairSignUpStartTime?: string;
jobFairSignUpEndTime?: string;
jobFairHostUnit?: string;
jobFairCoOrganizer?: string;
jobFairOrganizer?: string;
jobFairPhone?: string;
jobFairIntroduction?: string;
latitude?: number;
longitude?: number;
enterpriseNum?: string;
boothNum?: string;
}
/** 招聘会列表响应 */
export interface ListResult {
code: number;
msg?: string;
rows: JobFairItem[];
total: number;
}
/** 岗位信息 */
export interface JobInfo {
id?: string;
jobId: number;
jobTitle: string;
minSalary?: number;
maxSalary?: number;
education?: string;
experience?: string;
vacancies?: number;
}
/** 企业信息 */
export interface CompanyInfo {
id: string;
companyId: number;
companyName: string;
scale?: string;
industry?: string;
companyType?: string;
jobInfoList?: JobInfo[];
}
/** 招聘会详情响应 */
export interface DetailResult {
code: number;
msg?: string;
data: JobFairItem & {
companyList?: CompanyInfo[];
};
}
/** 新增/编辑招聘会参数 */
export interface JobFairForm {
jobFairId?: string;
jobFairTitle: string;
jobFairAddress: string;
jobFairType: string;
jobFairStartTime: string;
jobFairEndTime: string;
jobFairSignUpStartTime?: string;
jobFairSignUpEndTime?: string;
jobFairHostUnit?: string;
jobFairCoOrganizer?: string;
jobFairOrganizer?: string;
jobFairPhone?: string;
jobFairIntroduction?: string;
latitude?: number;
longitude?: number;
}
/** 添加企业参数 */
export interface AddCompanyParams {
jobFairId: string;
companyId: number;
}
/** 添加岗位参数 */
export interface AddJobParams {
jobFairId: string;
jobId: number;
companyId: number;
}
/** 报名人员 */
export interface SignupItem {
id: number;
jobFairId: number;
userId: number;
userName: string;
realName?: string;
phone?: string;
signUpTime: string;
status: string;
}
/** 报名人员列表响应 */
export interface SignupListResult {
code: number;
msg?: string;
rows: SignupItem[];
total: number;
}
/** 通用响应 */
export interface CommonResult {
code: number;
msg?: string;
data?: any;
}
}