Files
fe_portal_frontend/src/pages/register/supplier/CommonFormSections.tsx

657 lines
22 KiB
TypeScript
Raw Normal View History

/**
*
*
*/
2025-06-16 19:33:33 +08:00
import React from 'react';
import { Form, Input, Button, Select, Upload, DatePicker, Row, Col, Table, Radio, Cascader } from 'antd';
2025-06-16 19:33:33 +08:00
import {
UploadOutlined,
PlusOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { message } from 'antd';
const { Option } = Select;
const { LIST_IGNORE } = Upload;
2025-06-16 19:33:33 +08:00
// 中国省市区级联数据
export const addressOptions = [
2025-06-16 19:33:33 +08:00
{
value: '330000',
label: '浙江省',
children: [
{
value: '330100',
label: '杭州市',
children: [
{ value: '330102', label: '上城区' },
{ value: '330103', label: '下城区' },
{ value: '330104', label: '江干区' },
{ value: '330105', label: '拱墅区' },
{ value: '330106', label: '西湖区' },
{ value: '330108', label: '滨江区' },
],
},
],
},
{
value: '310000',
label: '上海市',
children: [
{
value: '310100',
label: '上海市',
children: [
{ value: '310101', label: '黄浦区' },
{ value: '310104', label: '徐汇区' },
{ value: '310105', label: '长宁区' },
],
},
],
},
];
interface CommonFormSectionsProps {
2025-06-16 19:33:33 +08:00
form: any;
}
/**
*
*
*/
export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
2025-06-16 19:33:33 +08:00
return (
<>
<div className="form-section-title"></div>
<Form.List name="qualifications">
{(fields, { add, remove }) => (
<>
<Table
dataSource={fields.map((field) => ({
...field,
key: field.key,
fieldKey: field.name,
}))}
pagination={false}
bordered
size="middle"
rowKey="key"
columns={[
{
title: '序号',
dataIndex: 'name',
width: 60,
render: (_, __, index) => index + 1,
},
{
title: '资质证书类型',
dataIndex: 'certType',
render: (_, record) => (
<Form.Item
name={[record.name, 'certType']}
noStyle
rules={[{ required: true, message: '请选择资质证书类型' }]}
>
<Select placeholder="请选择类型" style={{ width: '100%' }}>
<Option value="机构资质"></Option>
<Option value="CMMI资质等级">CMMI资质等级</Option>
<Option value="质量体系认证"></Option>
<Option value="环境管理体系认证"></Option>
<Option value="行业资质"></Option>
</Select>
</Form.Item>
),
},
{
title: '资质名称',
dataIndex: 'certName',
render: (_, record) => (
<Form.Item
name={[record.name, 'certName']}
noStyle
rules={[{ required: true, message: '请输入资质名称' }]}
>
<Input placeholder="请输入资质名称" />
</Form.Item>
),
},
{
title: '资质证书编号',
dataIndex: 'certNumber',
render: (_, record) => (
<Form.Item
name={[record.name, 'certNumber']}
noStyle
rules={[{ required: true, message: '请输入资质证书编号' }]}
>
<Input placeholder="请输入证书编号" />
</Form.Item>
),
},
{
title: '资质类别和等级',
dataIndex: 'certLevel',
render: (_, record) => (
<Form.Item name={[record.name, 'certLevel']} noStyle>
<Input placeholder="请输入资质类别和等级" />
</Form.Item>
),
},
{
title: '发证机构',
dataIndex: 'issuingAuthority',
render: (_, record) => (
<Form.Item
name={[record.name, 'issuingAuthority']}
noStyle
rules={[{ required: true, message: '请输入发证机构' }]}
>
<Input placeholder="请输入发证机构" />
</Form.Item>
),
},
{
title: '发证日期',
dataIndex: 'issueDate',
render: (_, record) => (
<Form.Item
name={[record.name, 'issueDate']}
noStyle
rules={[{ required: true, message: '请选择发证日期' }]}
>
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} />
</Form.Item>
),
},
{
title: '资质有效期至',
dataIndex: 'expiryDate',
render: (_, record) => (
<Form.Item
name={[record.name, 'expiryDate']}
noStyle
rules={[{ required: true, message: '请选择资质有效期' }]}
>
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} />
</Form.Item>
),
},
{
title: '附件',
dataIndex: 'certFile',
render: (_, record) => (
<Form.Item
name={[record.name, 'certFile']}
noStyle
rules={[{ required: true, message: '请上传资质证书附件' }]}
>
<Upload name="certFile" action="/api/upload" listType="text" maxCount={1}>
<Button type="link" size="small"></Button>
</Upload>
</Form.Item>
),
},
{
title: '操作',
width: 70,
render: (_, record) => (
<Button
type="link"
danger
icon={<DeleteOutlined />}
onClick={() => remove(record.name)}
>
</Button>
),
},
]}
/>
<Form.Item style={{ marginTop: 16 }} wrapperCol={{ span: 24 }}>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
</Button>
</Form.Item>
</>
)}
</Form.List>
</>
);
};
2025-06-16 19:33:33 +08:00
/**
*
*
*/
export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
return (
<>
2025-06-16 19:33:33 +08:00
<div className="form-section-title"></div>
<Row gutter={24}>
<Col span={8}>
<Form.Item
name="invoiceType"
label="纳税人类型"
rules={[{ required: true, message: '请选择纳税人类型' }]}
>
<Select placeholder="请选择纳税人类型">
<Option value="general"></Option>
<Option value="small"></Option>
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="invoiceTitle"
label="开票抬头"
rules={[{ required: true, message: '请输入开票抬头' }]}
>
<Input placeholder="请输入开票抬头" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="taxpayerNumber"
label="纳税人识别号"
rules={[{ required: true, message: '请输入纳税人识别号' }]}
>
<Input placeholder="请输入纳税人识别号" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="invoiceAddress" label="开票地址">
<Input placeholder="请输入开票地址" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="invoicePhone" label="开票电话">
<Input placeholder="请输入开票电话" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="invoiceBank" label="开票户行">
<Input placeholder="请输入开票银行" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="bankAccountNumber" label="开票户行账号">
<Input placeholder="请输入开票户行账号" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="generalTaxpayerCert" label="一般纳税人资格证明">
<Upload
name="generalTaxpayerCert"
action="/api/upload"
listType="text"
maxCount={1}
beforeUpload={(file) => {
const isValidFormat =
file.type === 'application/pdf' ||
file.type === 'image/jpeg' ||
file.type === 'image/png';
if (!isValidFormat) {
message.error('只能上传PDF/JPG/PNG格式文件!');
}
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('文件大小不能超过10MB!');
}
return isValidFormat && isLt10M;
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
</Col>
</Row>
</>
);
};
2025-06-16 19:33:33 +08:00
/**
*
*
*/
export const BankAccountSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
return (
<>
2025-06-16 19:33:33 +08:00
<div className="form-section-title"></div>
<Form.List name="bankAccounts">
{(fields, { add, remove }) => (
<>
<Table
dataSource={fields.map((field) => ({
...field,
key: field.key,
fieldKey: field.name,
}))}
pagination={false}
bordered
size="middle"
rowKey="key"
columns={[
{
title: '序号',
dataIndex: 'name',
width: 60,
render: (_, __, index) => index + 1,
},
{
title: '开户银行',
dataIndex: 'bankName',
render: (_, record) => (
<Form.Item
name={[record.name, 'bankName']}
noStyle
rules={[{ required: true, message: '请输入开户银行' }]}
>
<Input placeholder="请输入开户银行" />
</Form.Item>
),
},
{
title: '账户名称',
dataIndex: 'accountName',
render: (_, record) => (
<Form.Item
name={[record.name, 'accountName']}
noStyle
rules={[{ required: true, message: '请输入账户名称' }]}
>
<Input placeholder="请输入账户名称" />
</Form.Item>
),
},
{
title: '账号',
dataIndex: 'accountNumber',
render: (_, record) => (
<Form.Item
name={[record.name, 'accountNumber']}
noStyle
rules={[{ required: true, message: '请输入账号' }]}
>
<Input placeholder="请输入账号" />
</Form.Item>
),
},
{
title: '国家、省、市',
dataIndex: 'location',
render: (_, record) => (
<Form.Item
name={[record.name, 'address']}
noStyle
rules={[{ required: true, message: '请选择地址' }]}
>
<Cascader
options={addressOptions}
placeholder="请选择省市区"
showSearch={{
filter: (inputValue, path) => {
return path.some((option) => {
if (typeof option.label === 'string') {
return (
option.label.toLowerCase().indexOf(inputValue.toLowerCase()) > -1
);
}
return false;
});
},
}}
/>
</Form.Item>
),
},
{
title: '操作',
width: 70,
render: (_, record) => (
<Button
type="link"
danger
icon={<DeleteOutlined />}
onClick={() => remove(record.name)}
>
</Button>
),
},
]}
/>
<Form.Item style={{ marginTop: 16 }} wrapperCol={{ span: 24 }}>
<Button type="dashed" onClick={() => add()} block icon={<PlusOutlined />}>
</Button>
</Form.Item>
</>
)}
</Form.List>
</>
);
};
2025-06-16 19:33:33 +08:00
/**
*
*
*/
export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
return (
<>
2025-06-16 19:33:33 +08:00
<div className="form-section-title"></div>
<div className="questionnaire-header"></div>
<Row gutter={24}>
<Col span={8}>
<Form.Item
name="surveyCompanyName"
label="供应商名称"
rules={[{ required: true, message: '请输入供应商名称' }]}
>
<Input placeholder="请输入供应商名称" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="surveyPersonName"
label="姓名"
rules={[{ required: true, message: '请输入姓名' }]}
>
<Input placeholder="请输入姓名" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="surveyPosition"
label="职位"
rules={[{ required: true, message: '请输入职位' }]}
>
<Input placeholder="请输入职位" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="surveyPhone"
label="电话号"
rules={[{ required: true, message: '请输入电话号' }]}
>
<Input placeholder="请输入电话号" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="surveyEmail"
label="邮箱"
rules={[
{ type: 'email', message: '请输入有效的电子邮箱' },
{ required: true, message: '请输入电子邮箱' },
]}
>
<Input placeholder="请输入电子邮箱" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="surveyDate"
label="日期"
rules={[{ required: true, message: '请选择日期' }]}
>
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} />
</Form.Item>
</Col>
</Row>
<div className="questionnaire-header" style={{ marginTop: '20px' }}>
</div>
<Table
pagination={false}
bordered
size="middle"
rowKey="id"
dataSource={[
{
id: 1,
question:
'法律法规:\n我们确保经营和提供的产品服务遵守国家及各业务所在地的所有使用法律、法规及健康和安全',
},
{
id: 2,
question:
'健康和安全:\n我们为员工提供符合法律法规的安全且健康的工作场所。我们建立安全管理体系并向员工传达工作场所或生活设施的健康和安全标准致力于减少工作对员工造成的伤害和疾病。',
},
{
id: 3,
question:
'环境:\n我们能够以环境友好的方式经营。我们遵守适用的环境法律、法规和标准并建立有效的环境管理体系。\n我们遵守贵集团对相关产品或服务的部分附加环境要求这些要求和规定体现在设计与产品规范的合同文档中。',
},
{
id: 4,
question:
'监督和记录\n我们保留记录遵守所有法律和此行为准则的必要文件并根据要求为贵集团提供对文件的查看权。我们接允许贵集团在适当的时候以验证行为准则执行为目的的现场勘查',
},
]}
columns={[
{
title: '序号',
dataIndex: 'id',
width: 60,
align: 'center',
},
{
title: '问题',
dataIndex: 'question',
render: (text) => <div style={{ whiteSpace: 'pre-line' }}>{text}</div>,
},
{
title: '回复',
width: 650,
render: (_, record) => (
<Form.Item
name={['survey', `question${record.id}`]}
rules={[{ required: true, message: '请选择答案' }]}
wrapperCol={{ span: 24 }}
2025-06-16 19:33:33 +08:00
>
<Radio.Group>
<Radio value="yes"></Radio>
<Radio value="no"></Radio>
{record.id !== 1 && (
<>
<Radio value="partialYes"></Radio>
<Radio value="noPlan"></Radio>
</>
)}
</Radio.Group>
</Form.Item>
),
},
]}
/>
</>
);
};
2025-06-16 19:33:33 +08:00
/**
* 贿
*/
export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
return (
<>
2025-06-16 19:33:33 +08:00
<div className="form-section-title">贿</div>
<Row gutter={24}>
<Col span={12}>
<div className="upload-label">
<Button
type="link"
href="/templates/anti-bribery-template.docx"
download="供应商反商业贿赂承诺书模板.docx"
>
</Button>
</div>
<Form.Item
name="antiBriberyDoc"
rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]}
>
<Upload
name="antiBriberyDoc"
action="/api/upload"
listType="text"
maxCount={1}
beforeUpload={(file) => {
const isValidFormat =
file.type === 'application/pdf' ||
file.type === 'application/msword' ||
file.type ===
'application/vnd.openxmlformats-officedocument.wordprocessingml.document';
if (!isValidFormat) {
message.error('只能上传PDF/DOC/DOCX格式文件!');
return LIST_IGNORE;
2025-06-16 19:33:33 +08:00
}
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('文件大小不能超过10MB!');
return LIST_IGNORE;
2025-06-16 19:33:33 +08:00
}
return isValidFormat && isLt10M;
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
</Col>
</Row>
<div className="form-section-title"></div>
<Row gutter={24}>
<Col span={24}>
<Form.Item name="otherAttachments">
<div className="upload-label"></div>
<Upload
name="otherAttachments"
action="/api/upload"
listType="text"
multiple
beforeUpload={(file) => {
const isLt20M = file.size / 1024 / 1024 < 20;
if (!isLt20M) {
message.error('文件大小不能超过20MB!');
return LIST_IGNORE;
2025-06-16 19:33:33 +08:00
}
return isLt20M;
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
</Col>
</Row>
</>
);
};