feat: Enhance Outdoor Fair and Public Job Fair features
- Added QR code functionality for companies signing up for outdoor fairs. - Implemented job management for outdoor fairs, including job listing and editing. - Updated Public Job Fair detail view to reflect new data structure. - Refactored EditModal to support dynamic lists for host, co-organizer, and organizing units. - Introduced cross-domain city selection for job fairs. - Enhanced API services for managing cross-domain jobs and cities. - Improved data handling for outdoor fair items, including review status and QR code content. - Updated type definitions to accommodate new fields and structures.
This commit is contained in:
@@ -102,8 +102,11 @@ const JobFairDetail: React.FC = () => {
|
||||
{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="协办单位">{detail?.jobFairHelpUnit}</Descriptions.Item>
|
||||
<Descriptions.Item label="承办单位">{detail?.jobFairOrganizeUnit}</Descriptions.Item>
|
||||
<Descriptions.Item label="跨域联盟城市" span={2}>
|
||||
{detail?.crossDomainCities || '-'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label="简介" span={2}>{detail?.jobFairIntroduction}</Descriptions.Item>
|
||||
</Descriptions>
|
||||
</Card>
|
||||
|
||||
@@ -6,9 +6,13 @@ import {
|
||||
ProFormTextArea,
|
||||
ProFormRadio,
|
||||
ProFormDateTimePicker,
|
||||
ProFormList,
|
||||
ProFormSelect,
|
||||
} from '@ant-design/pro-components';
|
||||
import { Button, Form } from 'antd';
|
||||
import ProFromMap from '@/components/ProFromMap';
|
||||
import { getDictValueEnum } from '@/services/system/dict';
|
||||
import { getCrossCityAllianceList } from '@/services/jobfair/crossCityAlliance';
|
||||
|
||||
interface EditModalProps {
|
||||
open: boolean;
|
||||
@@ -18,22 +22,54 @@ interface EditModalProps {
|
||||
onSubmit: (values: API.PublicJobFair.JobFairForm) => Promise<void>;
|
||||
}
|
||||
|
||||
/** 逗号串 -> 数组(空值返回 [''] 保证至少一行) */
|
||||
const toArr = (s?: string): string[] => {
|
||||
if (!s) return [''];
|
||||
const arr = s.split(',').map((x) => x.trim()).filter(Boolean);
|
||||
return arr.length ? arr : [''];
|
||||
};
|
||||
|
||||
/** 数组 -> 逗号串(过滤空串) */
|
||||
const toStr = (arr?: string[]): string =>
|
||||
(arr || []).map((x) => (x || '').trim()).filter(Boolean).join(',');
|
||||
|
||||
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 }>({});
|
||||
const [yesNoEnum, setYesNoEnum] = useState<any>({});
|
||||
|
||||
const isCrossDomain = Form.useWatch('isCrossDomain', form);
|
||||
|
||||
useEffect(() => {
|
||||
getDictValueEnum('sys_yes_no').then(setYesNoEnum);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (open) {
|
||||
form.resetFields();
|
||||
if (values) {
|
||||
form.setFieldsValue(values);
|
||||
form.setFieldsValue({
|
||||
...values,
|
||||
jobFairHostUnitList: toArr(values.jobFairHostUnit),
|
||||
jobFairHelpUnitList: toArr(values.jobFairHelpUnit),
|
||||
jobFairOrganizeUnitList: toArr(values.jobFairOrganizeUnit),
|
||||
crossDomainCityList: values.crossDomainCities
|
||||
? values.crossDomainCities.split(',').map((x) => x.trim()).filter(Boolean)
|
||||
: [],
|
||||
});
|
||||
setLocationInfo({
|
||||
address: values.jobFairAddress,
|
||||
latitude: values.latitude,
|
||||
longitude: values.longitude,
|
||||
});
|
||||
} else {
|
||||
form.setFieldsValue({
|
||||
jobFairHostUnitList: [''],
|
||||
jobFairHelpUnitList: [''],
|
||||
jobFairOrganizeUnitList: [''],
|
||||
crossDomainCityList: [],
|
||||
});
|
||||
setLocationInfo({});
|
||||
}
|
||||
}
|
||||
@@ -59,8 +95,26 @@ const EditModal: React.FC<EditModalProps> = ({ open, values, jobFairTypeEnum, on
|
||||
open={open}
|
||||
width={700}
|
||||
modalProps={{ destroyOnClose: true, onCancel }}
|
||||
initialValues={{ isCrossDomain: 'n' }}
|
||||
onFinish={async (formValues) => {
|
||||
await onSubmit({ ...formValues, jobFairId: values?.jobFairId } as API.PublicJobFair.JobFairForm);
|
||||
const v = formValues as any;
|
||||
const {
|
||||
jobFairHostUnitList,
|
||||
jobFairHelpUnitList,
|
||||
jobFairOrganizeUnitList,
|
||||
crossDomainCityList,
|
||||
...rest
|
||||
} = v;
|
||||
const payload: API.PublicJobFair.JobFairForm = {
|
||||
...rest,
|
||||
jobFairId: values?.jobFairId,
|
||||
jobFairHostUnit: toStr(jobFairHostUnitList),
|
||||
jobFairHelpUnit: toStr(jobFairHelpUnitList),
|
||||
jobFairOrganizeUnit: toStr(jobFairOrganizeUnitList),
|
||||
crossDomainCities:
|
||||
isCrossDomain === 'y' ? toStr(crossDomainCityList) : '',
|
||||
};
|
||||
await onSubmit(payload);
|
||||
}}
|
||||
>
|
||||
<ProFormText name="jobFairId" hidden />
|
||||
@@ -82,6 +136,48 @@ const EditModal: React.FC<EditModalProps> = ({ open, values, jobFairTypeEnum, on
|
||||
valueEnum={jobFairTypeEnum}
|
||||
rules={[{ required: true, message: '请选择招聘会类型' }]}
|
||||
/>
|
||||
<ProFormRadio.Group
|
||||
name="isCrossDomain"
|
||||
label="是否跨域"
|
||||
valueEnum={yesNoEnum}
|
||||
/>
|
||||
{isCrossDomain === 'y' && (
|
||||
<ProFormSelect
|
||||
name="crossDomainCityList"
|
||||
label="跨域联盟城市"
|
||||
mode="multiple"
|
||||
placeholder="请选择跨域联盟城市"
|
||||
rules={[{ required: true, message: '请选择跨域联盟城市' }]}
|
||||
request={async () => {
|
||||
const res = await getCrossCityAllianceList({ pageSize: 1000 });
|
||||
return (res.rows || []).map((c) => ({ label: c.name, value: c.name }));
|
||||
}}
|
||||
fieldProps={{
|
||||
tagRender: (props: any) => {
|
||||
const { label, closable, onClose } = props;
|
||||
return (
|
||||
<span
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
margin: '0 4px 4px 0',
|
||||
padding: '2px 8px',
|
||||
background: '#f0f5ff',
|
||||
border: '1px solid #adc6ff',
|
||||
borderRadius: 4,
|
||||
}}
|
||||
>
|
||||
{label}
|
||||
{closable && (
|
||||
<span style={{ marginLeft: 4, cursor: 'pointer' }} onClick={onClose}>
|
||||
×
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
);
|
||||
},
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<ProForm.Group>
|
||||
<ProFormDateTimePicker
|
||||
name="jobFairStartTime"
|
||||
@@ -100,14 +196,34 @@ const EditModal: React.FC<EditModalProps> = ({ open, values, jobFairTypeEnum, on
|
||||
<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>
|
||||
<ProFormList
|
||||
name="jobFairHostUnitList"
|
||||
label="主办单位"
|
||||
min={1}
|
||||
copyIconProps={false}
|
||||
creatorButtonProps={{ position: 'bottom', creatorButtonText: '添加主办单位' }}
|
||||
>
|
||||
<ProFormText placeholder="请输入主办单位" />
|
||||
</ProFormList>
|
||||
<ProFormList
|
||||
name="jobFairHelpUnitList"
|
||||
label="协办单位"
|
||||
min={1}
|
||||
copyIconProps={false}
|
||||
creatorButtonProps={{ position: 'bottom', creatorButtonText: '添加协办单位' }}
|
||||
>
|
||||
<ProFormText placeholder="请输入协办单位" />
|
||||
</ProFormList>
|
||||
<ProFormList
|
||||
name="jobFairOrganizeUnitList"
|
||||
label="承办单位"
|
||||
min={1}
|
||||
copyIconProps={false}
|
||||
creatorButtonProps={{ position: 'bottom', creatorButtonText: '添加承办单位' }}
|
||||
>
|
||||
<ProFormText placeholder="请输入承办单位" />
|
||||
</ProFormList>
|
||||
<ProFormText name="jobFairPhone" label="联系电话" placeholder="请输入联系电话" />
|
||||
<ProFormTextArea name="jobFairIntroduction" label="招聘会简介" placeholder="请输入招聘会简介" />
|
||||
|
||||
<ProForm.Item label="地图选点">
|
||||
|
||||
@@ -22,10 +22,12 @@ const PublicJobFairList: React.FC = () => {
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [currentRow, setCurrentRow] = useState<API.PublicJobFair.JobFairItem>();
|
||||
const [jobFairTypeEnum, setJobFairTypeEnum] = useState<any>({});
|
||||
const [yesNoEnum, setYesNoEnum] = useState<any>({});
|
||||
const [selectedRowKeys, setSelectedRowKeys] = useState<React.Key[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
getDictValueEnum('job_fair_type', true).then(setJobFairTypeEnum);
|
||||
getDictValueEnum('sys_yes_no').then(setYesNoEnum);
|
||||
}, []);
|
||||
|
||||
const handleDelete = async (ids: string) => {
|
||||
@@ -100,6 +102,13 @@ const PublicJobFairList: React.FC = () => {
|
||||
valueEnum: jobFairTypeEnum,
|
||||
render: (_, record) => <DictTag enums={jobFairTypeEnum} value={record.jobFairType} />,
|
||||
},
|
||||
{
|
||||
title: '是否跨域',
|
||||
dataIndex: 'isCrossDomain',
|
||||
valueType: 'select',
|
||||
valueEnum: yesNoEnum,
|
||||
render: (_, record) => <DictTag enums={yesNoEnum} value={record.isCrossDomain} />,
|
||||
},
|
||||
{
|
||||
title: '开始时间',
|
||||
dataIndex: 'jobFairStartTime',
|
||||
|
||||
Reference in New Issue
Block a user