Files
shz-admin/src/pages/Management/List/edit.tsx
francis-fh ed37133c69
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
面试功能开发
2026-06-25 13:32:03 +08:00

465 lines
16 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
ModalForm,
ProForm,
ProFormDigit,
ProFormSelect,
ProFormText,
ProFormTextArea,
ProDescriptions,
} from '@ant-design/pro-components';
import { Form, Button, Input } from 'antd';
import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
import React, { useEffect, useRef, useState } from 'react';
import { DictValueEnumObj } from '@/components/DictTag';
import { getCmsCompanyList } from '@/services/company/list';
import { getCmsJobDetail } from '@/services/Management/list';
export type ListFormProps = {
onCancel: (flag?: boolean, formVals?: unknown) => void;
onSubmit: (values: API.ManagementList.Manage) => Promise<void>;
open: boolean;
values?: Partial<API.ManagementList.Manage>;
educationEnum: DictValueEnumObj;
experienceEnum: DictValueEnumObj;
areaEnum: DictValueEnumObj;
jobTypeEnum: DictValueEnumObj;
mode?: 'view' | 'edit' | 'create';
};
const waitTime = (time: number = 100) => {
return new Promise((resolve) => {
setTimeout(() => {
resolve(true);
}, time);
});
};
const listEdit: React.FC<ListFormProps> = (props) => {
const [form] = Form.useForm<API.ManagementList.Manage>();
const companyNameMap = useRef<Record<number, string>>({});
const [jobDetail, setJobDetail] = useState<API.ManagementList.Manage | null>(null);
const [loading, setLoading] = useState(false);
const { educationEnum, experienceEnum, areaEnum, jobTypeEnum } = props;
const { mode = props.values ? 'edit' : 'create' } = props;
useEffect(() => {
if(props.open){
form.resetFields();
if (props.values) {
form.setFieldsValue({
...props.values,
jobLocationAreaCode: String(props.values.jobLocationAreaCode || ''),
});
}
}
}, [form, props.values?.jobId,props.open]);
// 在查看模式和编辑模式下调用API获取详情
useEffect(() => {
if (props.open && (mode === 'view' || mode === 'edit') && props.values?.jobId) {
fetchJobDetail();
}
}, [props.open, mode, props.values?.jobId]);
const fetchJobDetail = async () => {
if (!props.values?.jobId) return;
setLoading(true);
try {
const response = await getCmsJobDetail(props.values.jobId.toString());
if (response.code === 200) {
setJobDetail(response.data);
// 如果是编辑模式,将获取到的详情数据设置到表单中
if (mode === 'edit') {
form.setFieldsValue({
...response.data,
jobLocationAreaCode: String(response.data.jobLocationAreaCode || ''),
});
}
}
} catch (error) {
console.error('获取岗位详情失败:', error);
} finally {
setLoading(false);
}
};
const handleCancel = () => {
props.onCancel();
form.resetFields();
};
const handleFinish = async (values: Record<string, any>) => {
const payload: API.ManagementList.Manage = {
jobTitle: values.jobTitle,
companyId: values.companyId,
companyName:
typeof values.companyName === 'string'
? values.companyName
: companyNameMap.current[values.companyId] ?? '',
minSalary: values.minSalary,
maxSalary: values.maxSalary,
education: values.education,
experience: values.experience,
jobLocationAreaCode: values.jobLocationAreaCode,
vacancies: values.vacancies,
jobType: values.jobType,
jobLocation: values.jobLocation,
description: values.description,
jobContactList: (values.jobContactList ?? []).map((item: API.ManagementList.ContactPerson) => ({
contactPerson: item.contactPerson,
contactPersonPhone: item.contactPersonPhone,
position: item.position,
})),
};
if (mode === 'edit' && values.jobId) {
payload.jobId = values.jobId;
}
await props.onSubmit(payload);
return true;
};
if (mode === 'view') {
return (
<ModalForm
title="岗位详情"
open={props.open}
width={800}
modalProps={{
destroyOnClose: true,
onCancel: () => handleCancel(),
footer: null,
}}
submitter={false}
>
<ProDescriptions<API.ManagementList.Manage>
column={2}
dataSource={jobDetail || props.values || {}}
loading={loading}
>
<ProDescriptions.Item dataIndex="jobTitle" label="岗位名称" />
<ProDescriptions.Item dataIndex="companyName" label="招聘公司" />
<ProDescriptions.Item dataIndex="minSalary" label="最低薪资(元/月)" />
<ProDescriptions.Item dataIndex="maxSalary" label="最高薪资(元/月)" />
<ProDescriptions.Item
dataIndex="education"
label="学历要求"
valueEnum={educationEnum}
/>
<ProDescriptions.Item
dataIndex="experience"
label="工作经验"
valueEnum={experienceEnum}
/>
<ProDescriptions.Item
dataIndex="jobLocationAreaCode"
label="工作区县"
valueEnum={areaEnum}
/>
<ProDescriptions.Item dataIndex="vacancies" label="招聘人数" />
<ProDescriptions.Item dataIndex="jobLocation" label="工作地点" />
<ProDescriptions.Item
dataIndex="jobType"
label="岗位类型"
valueEnum={jobTypeEnum}
/>
<ProDescriptions.Item
dataIndex="description"
label="岗位描述"
span={2} // 跨两列显示
/>
<ProDescriptions.Item
dataIndex="company"
label="公司信息"
span={2}
render={(_, record) => {
const company = record?.company;
if (!company) {
return <span style={{ color: '#999' }}></span>;
}
return (
<div style={{ width: '100%' }}>
<div style={{ marginBottom: 8 }}>
<strong style={{ color: '#000', marginRight: 16 }}></strong>
<span style={{ color: '#000' }}>{company.name}</span>
</div>
<div style={{ marginBottom: 8 }}>
<strong style={{ color: '#000', marginRight: 16 }}></strong>
<span style={{ color: '#000' }}>{company.location}</span>
</div>
<div style={{ marginBottom: 8 }}>
<strong style={{ color: '#000', marginRight: 16 }}></strong>
<span style={{ color: '#000' }}>{company.scale}</span>
</div>
<div style={{ marginBottom: 8 }}>
<strong style={{ color: '#000', marginRight: 16 }}></strong>
<span style={{ color: '#000' }}>{company.nature}</span>
</div>
{company.description && (
<div style={{ marginBottom: 8 }}>
<strong style={{ color: '#000', marginRight: 16 }}></strong>
<span style={{ color: '#000' }}>{company.description}</span>
</div>
)}
</div>
);
}}
/>
<ProDescriptions.Item
dataIndex="jobContactList"
label="联系人信息"
span={2}
render={(_, record) => {
const contactList = record?.jobContactList || [];
if (!contactList || contactList.length === 0) {
return <span style={{ color: '#999' }}></span>;
}
return (
<div style={{ width: '100%' }}>
<table style={{
width: '100%',
borderCollapse: 'collapse',
border: '1px solid #d9d9d9',
borderRadius: '6px',
overflow: 'hidden'
}}>
<thead>
<tr style={{ backgroundColor: '#fafafa' }}>
<th style={{
padding: '12px 16px',
textAlign: 'left',
borderBottom: '1px solid #d9d9d9',
fontWeight: 600,
color: '#000'
}}>
</th>
<th style={{
padding: '12px 16px',
textAlign: 'left',
borderBottom: '1px solid #d9d9d9',
fontWeight: 600,
color: '#000'
}}>
</th>
<th style={{
padding: '12px 16px',
textAlign: 'left',
borderBottom: '1px solid #d9d9d9',
fontWeight: 600,
color: '#000'
}}>
</th>
</tr>
</thead>
<tbody>
{contactList.map((contact: any, index: number) => (
<tr key={index} style={{ backgroundColor: index % 2 === 0 ? '#fff' : '#fafafa' }}>
<td style={{
padding: '12px 16px',
borderBottom: '1px solid #f0f0f0',
color: '#000'
}}>
{contact.contactPerson}
</td>
<td style={{
padding: '12px 16px',
borderBottom: '1px solid #f0f0f0',
color: '#000'
}}>
{contact.position}
</td>
<td style={{
padding: '12px 16px',
borderBottom: '1px solid #f0f0f0',
color: '#000',
fontWeight: 500
}}>
{contact.contactPersonPhone}
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}}
/>
</ProDescriptions>
</ModalForm>
);
}
return (
<ModalForm<API.ManagementList.Manage>
title={mode === 'edit' ? '编辑岗位' : '新建岗位'}
form={form}
autoFocusFirstInput
open={props.open}
width={900}
grid={true}
rowProps={{ gutter: [16, 16] }}
colProps={{ span: 12 }}
modalProps={{
destroyOnClose: true,
onCancel: () => handleCancel(),
style: { height: '80vh' },
styles: {
body: {
height: 'calc(80vh - 120px)',
overflowY: 'auto',
padding: '16px 24px',
},
},
}}
submitTimeout={2000}
onFinish={handleFinish}
>
<ProFormText width="md" hidden name="jobId" />
<ProFormText width="md" hidden name="companyName" />
<ProFormText width="md" name="jobTitle" label="岗位名称" placeholder="请输入岗位名称" />
<ProFormSelect
showSearch
width="md"
name="companyId"
request={async ({ keyWords }) => {
const resData = await getCmsCompanyList({ name: keyWords });
return resData.rows.map((item) => {
companyNameMap.current[item.companyId] = item.name;
return { label: item.name, value: item.companyId };
});
}}
fieldProps={{
onChange: (companyId: number) => {
form.setFieldValue('companyName', companyNameMap.current[companyId] ?? '');
},
}}
placeholder="请输入公司名称选择公司"
rules={[{ required: true, message: '请输入公司名称选择公司!' }]}
label="招聘公司"
/>
<ProFormDigit
name="minSalary"
width="md"
min={0}
label="最小薪资(元/月)"
placeholder="请输入最小薪资(元)"
/>
<ProFormDigit
name="maxSalary"
width="md"
min={0}
label="最大薪资(元/月)"
placeholder="请输入最大薪资(元)"
/>
<ProFormSelect
width="md"
name="education"
label={'学历要求'}
valueEnum={educationEnum}
placeholder="请选择学历要求"
rules={[{ required: true, message: '请选择学历要求!' }]}
/>
<ProFormSelect
width="md"
name="experience"
label={'工作经验'}
valueEnum={experienceEnum}
placeholder="请选择岗位"
rules={[{ required: true, message: '请选择工作经验!' }]}
/>
<ProFormSelect
width="md"
name="jobLocationAreaCode"
label={'工作区县'}
valueEnum={areaEnum}
placeholder="请选择区县"
rules={[{ required: true, message: '请选择区县!' }]}
/>
<ProFormDigit
label="招聘人数"
name="vacancies"
width="md"
min={0}
placeholder="请输入招聘人数"
/>
<ProFormSelect
width="md"
name="jobType"
label={'岗位类型'}
valueEnum={jobTypeEnum}
placeholder="请选择类型"
rules={[{ required: true, message: '请选择类型!' }]}
/>
<ProFormText width="md" name="jobLocation" label="工作地点" placeholder="请输入工作地点" />
<ProFormTextArea
width="xl"
name="description"
label="岗位描述"
placeholder="请输入岗位描述"
colProps={{ span: 24 }}
/>
{/* 岗位联系人动态表单 - 绕过网格系统 */}
<div style={{ width: '100%', marginBottom: 16 }}>
<div style={{ marginBottom: 8, fontWeight: 500 }}></div>
<Form.List name="jobContactList" initialValue={[{}]}>
{(fields, { add, remove }) => (
<>
{fields.map(({ key, name, ...restField }) => (
<div key={key} style={{ display: 'flex', width: '100%', marginBottom: 8, alignItems: 'center', gap: '8px' }}>
<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)}
style={{ marginBottom: 0 }}
/>
</div>
))}
<Form.Item>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
</Button>
</Form.Item>
</>
)}
</Form.List>
</div>
</ModalForm>
);
};
export default listEdit;