feat: implement participating companies and jobs tabs in outdoor fair detail
- Add ParticipatingCompaniesTab component to manage participating companies. - Add ParticipatingJobsTab component to manage jobs associated with participating companies. - Remove StatisticsTab component as it is no longer needed. - Update OutdoorFairDetail to include new tabs for participating companies and jobs. - Modify API services to support fetching and managing participating companies and jobs. - Update types to reflect changes in job and company data structures.
This commit is contained in:
@@ -1,26 +1,54 @@
|
||||
import React, { useEffect } from 'react';
|
||||
import { ModalForm, ProForm, ProFormText, ProFormDigit, ProFormSelect } from '@ant-design/pro-components';
|
||||
import { Form } from 'antd';
|
||||
import {
|
||||
ModalForm,
|
||||
ProForm,
|
||||
ProFormDigit,
|
||||
ProFormSelect,
|
||||
ProFormText,
|
||||
ProFormTextArea,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Button, Form, Input, message } from 'antd';
|
||||
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
|
||||
import type { DictValueEnumObj } from '@/components/DictTag';
|
||||
import { addJobForCompany, updateJobForCompany } from '@/services/jobportal/outdoorFairDetail';
|
||||
|
||||
interface Props {
|
||||
open: boolean;
|
||||
fairId: number;
|
||||
company: any;
|
||||
job: any;
|
||||
company: API.OutdoorFairDetail.ParticipatingCompany | null;
|
||||
job: API.OutdoorFairDetail.PostedJob | null;
|
||||
educationEnum: DictValueEnumObj;
|
||||
experienceEnum: DictValueEnumObj;
|
||||
areaEnum: DictValueEnumObj;
|
||||
jobTypeEnum: DictValueEnumObj;
|
||||
onCancel: () => void;
|
||||
onSuccess: () => void;
|
||||
}
|
||||
|
||||
const JobEditModal: React.FC<Props> = ({ open, fairId, company, job, onCancel, onSuccess }) => {
|
||||
const JobEditModal: React.FC<Props> = ({
|
||||
open,
|
||||
fairId,
|
||||
company,
|
||||
job,
|
||||
educationEnum,
|
||||
experienceEnum,
|
||||
areaEnum,
|
||||
jobTypeEnum,
|
||||
onCancel,
|
||||
onSuccess,
|
||||
}) => {
|
||||
const [form] = Form.useForm();
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
form.resetFields();
|
||||
if (job) {
|
||||
form.setFieldsValue(job);
|
||||
}
|
||||
if (!open) return;
|
||||
form.resetFields();
|
||||
if (job) {
|
||||
form.setFieldsValue({
|
||||
...job,
|
||||
jobLocationAreaCode: String(job.jobLocationAreaCode || ''),
|
||||
});
|
||||
} else {
|
||||
form.setFieldsValue({ isPublish: 1, jobContactList: [{}] });
|
||||
}
|
||||
}, [open, job, form]);
|
||||
|
||||
@@ -29,35 +57,156 @@ const JobEditModal: React.FC<Props> = ({ open, fairId, company, job, onCancel, o
|
||||
title={job ? '编辑岗位' : `为「${company?.companyName || ''}」添加岗位`}
|
||||
form={form}
|
||||
open={open}
|
||||
width={500}
|
||||
modalProps={{ destroyOnClose: true, onCancel }}
|
||||
width={900}
|
||||
grid
|
||||
rowProps={{ gutter: [16, 16] }}
|
||||
colProps={{ span: 12 }}
|
||||
modalProps={{
|
||||
destroyOnClose: true,
|
||||
onCancel,
|
||||
style: { height: '80vh' },
|
||||
styles: {
|
||||
body: {
|
||||
height: 'calc(80vh - 120px)',
|
||||
overflowY: 'auto',
|
||||
padding: '16px 24px',
|
||||
},
|
||||
},
|
||||
}}
|
||||
onFinish={async (values) => {
|
||||
if (job) {
|
||||
const res = await updateJobForCompany({ ...job, ...values });
|
||||
if (res.code === 200) { onSuccess(); return true; }
|
||||
} else if (company) {
|
||||
const res = await addJobForCompany({ fairId, companyId: company.id, ...values });
|
||||
if (res.code === 200) { onSuccess(); return true; }
|
||||
const payload = {
|
||||
...values,
|
||||
companyId: company?.companyId,
|
||||
companyName: company?.companyName,
|
||||
jobContactList: values.jobContactList || [],
|
||||
};
|
||||
const res = job
|
||||
? await updateJobForCompany(fairId, { ...job, ...payload })
|
||||
: await addJobForCompany({ fairId, companyId: company!.companyId, ...payload });
|
||||
if (res.code === 200) {
|
||||
message.success(job ? '岗位修改成功' : '岗位添加成功');
|
||||
onSuccess();
|
||||
return true;
|
||||
}
|
||||
message.error(res.msg || '操作失败');
|
||||
return false;
|
||||
}}
|
||||
>
|
||||
<ProFormText name="jobTitle" label="岗位名称" rules={[{ required: true, message: '请输入岗位名称' }]} placeholder="请输入岗位名称" />
|
||||
<ProForm.Group>
|
||||
<ProFormDigit name="minSalary" label="最低薪资(K)" width="sm" min={0} rules={[{ required: true }]} fieldProps={{ precision: 0 }} />
|
||||
<ProFormDigit name="maxSalary" label="最高薪资(K)" width="sm" min={0} rules={[{ required: true }]} fieldProps={{ precision: 0 }} />
|
||||
</ProForm.Group>
|
||||
<ProForm.Group>
|
||||
<ProFormSelect name="education" label="学历要求" width="sm"
|
||||
options={['高中', '大专', '本科', '硕士', '博士', '不限'].map(v => ({ label: v, value: v }))}
|
||||
rules={[{ required: true }]}
|
||||
/>
|
||||
<ProFormSelect name="experience" label="经验要求" width="sm"
|
||||
options={['不限', '应届生', '1-3年', '3-5年', '5-10年', '10年以上'].map(v => ({ label: v, value: v }))}
|
||||
rules={[{ required: true }]}
|
||||
/>
|
||||
</ProForm.Group>
|
||||
<ProFormDigit name="vacancies" label="招聘人数" width="md" min={1} rules={[{ required: true }]} fieldProps={{ precision: 0 }} />
|
||||
<ProFormText
|
||||
name="jobTitle"
|
||||
label="岗位名称"
|
||||
placeholder="请输入岗位名称"
|
||||
rules={[{ required: true, message: '请输入岗位名称' }]}
|
||||
/>
|
||||
<ProFormDigit
|
||||
name="minSalary"
|
||||
min={0}
|
||||
label="最小薪资(元/月)"
|
||||
placeholder="请输入最小薪资"
|
||||
rules={[{ required: true, message: '请输入最小薪资' }]}
|
||||
/>
|
||||
<ProFormDigit
|
||||
name="maxSalary"
|
||||
min={0}
|
||||
label="最大薪资(元/月)"
|
||||
placeholder="请输入最大薪资"
|
||||
rules={[{ required: true, message: '请输入最大薪资' }]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
name="education"
|
||||
label="学历要求"
|
||||
valueEnum={educationEnum}
|
||||
placeholder="请选择学历要求"
|
||||
rules={[{ required: true, message: '请选择学历要求' }]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
name="experience"
|
||||
label="工作经验"
|
||||
valueEnum={experienceEnum}
|
||||
placeholder="请选择工作经验"
|
||||
rules={[{ required: true, message: '请选择工作经验' }]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
name="jobLocationAreaCode"
|
||||
label="工作区县"
|
||||
valueEnum={areaEnum}
|
||||
placeholder="请选择区县"
|
||||
rules={[{ required: true, message: '请选择区县' }]}
|
||||
/>
|
||||
<ProFormDigit
|
||||
name="vacancies"
|
||||
min={0}
|
||||
label="招聘人数"
|
||||
placeholder="请输入招聘人数"
|
||||
rules={[{ required: true, message: '请输入招聘人数' }]}
|
||||
/>
|
||||
<ProFormSelect
|
||||
name="jobType"
|
||||
label="岗位类型"
|
||||
valueEnum={jobTypeEnum}
|
||||
placeholder="请选择岗位类型"
|
||||
rules={[{ required: true, message: '请选择岗位类型' }]}
|
||||
/>
|
||||
<ProFormText name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
|
||||
<ProFormTextArea
|
||||
name="description"
|
||||
label="岗位描述"
|
||||
placeholder="请输入岗位描述"
|
||||
colProps={{ span: 24 }}
|
||||
/>
|
||||
|
||||
<div style={{ width: '100%', marginBottom: 16, gridColumn: '1 / -1' }}>
|
||||
<div style={{ marginBottom: 8, fontWeight: 500 }}>岗位联系人</div>
|
||||
<Form.List name="jobContactList">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
{fields.map(({ key, name, ...restField }) => (
|
||||
<div
|
||||
key={key}
|
||||
style={{ display: 'flex', width: '100%', marginBottom: 8, alignItems: 'center', gap: 8 }}
|
||||
>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'contactPerson']}
|
||||
label="联系人姓名"
|
||||
rules={[{ required: true, message: '请输入联系人姓名' }]}
|
||||
style={{ marginBottom: 0, flex: 1 }}
|
||||
>
|
||||
<Input placeholder="请输入联系人姓名" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'contactPersonPhone']}
|
||||
label="联系电话"
|
||||
rules={[
|
||||
{ required: true, message: '请输入联系电话' },
|
||||
{ pattern: /^1[3-9]\d{9}$/, message: '请输入正确的手机号码' },
|
||||
]}
|
||||
style={{ marginBottom: 0, flex: 1 }}
|
||||
>
|
||||
<Input placeholder="请输入联系电话" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
{...restField}
|
||||
name={[name, 'position']}
|
||||
label="职务"
|
||||
rules={[{ required: true, message: '请输入职务' }]}
|
||||
style={{ marginBottom: 0, flex: 1 }}
|
||||
>
|
||||
<Input placeholder="请输入职务" />
|
||||
</Form.Item>
|
||||
<Button type="text" danger icon={<MinusCircleOutlined />} onClick={() => remove(name)} />
|
||||
</div>
|
||||
))}
|
||||
<Form.Item>
|
||||
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
|
||||
添加联系人
|
||||
</Button>
|
||||
</Form.Item>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</div>
|
||||
</ModalForm>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user