Files
fe_portal_frontend/src/pages/register/DomesticForm.tsx
2025-06-16 19:33:33 +08:00

950 lines
32 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 React from 'react';
import { Form, Input, Button, Select, Upload, DatePicker, Row, Col, Table, Cascader } from 'antd';
import {
MobileOutlined,
MailOutlined,
EnvironmentOutlined,
UploadOutlined,
PlusOutlined,
DeleteOutlined,
} from '@ant-design/icons';
import { Radio } from 'antd';
import { message } from 'antd';
const { Option } = Select;
const { TextArea } = Input;
// 中国省市区级联数据
const addressOptions = [
{
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: '330200',
label: '宁波市',
children: [
{ value: '330203', label: '海曙区' },
{ value: '330205', label: '江北区' },
{ value: '330206', label: '北仑区' },
{ value: '330211', label: '镇海区' },
{ value: '330212', label: '鄞州区' },
],
},
],
},
{
value: '310000',
label: '上海市',
children: [
{
value: '310100',
label: '上海市',
children: [
{ value: '310101', label: '黄浦区' },
{ value: '310104', label: '徐汇区' },
{ value: '310105', label: '长宁区' },
{ value: '310106', label: '静安区' },
{ value: '310107', label: '普陀区' },
{ value: '310109', label: '虹口区' },
{ value: '310110', label: '杨浦区' },
{ value: '310112', label: '闵行区' },
],
},
],
},
{
value: '440000',
label: '广东省',
children: [
{
value: '440100',
label: '广州市',
children: [
{ value: '440103', label: '荔湾区' },
{ value: '440104', label: '越秀区' },
{ value: '440105', label: '海珠区' },
{ value: '440106', label: '天河区' },
{ value: '440111', label: '白云区' },
{ value: '440112', label: '黄埔区' },
],
},
{
value: '440300',
label: '深圳市',
children: [
{ value: '440303', label: '罗湖区' },
{ value: '440304', label: '福田区' },
{ value: '440305', label: '南山区' },
{ value: '440306', label: '宝安区' },
{ value: '440307', label: '龙岗区' },
{ value: '440308', label: '盐田区' },
],
},
],
},
{
value: '110000',
label: '北京市',
children: [
{
value: '110100',
label: '北京市',
children: [
{ value: '110101', label: '东城区' },
{ value: '110102', label: '西城区' },
{ value: '110105', label: '朝阳区' },
{ value: '110106', label: '丰台区' },
{ value: '110107', label: '石景山区' },
{ value: '110108', label: '海淀区' },
],
},
],
},
];
interface DomesticFormProps {
form: any;
countdown: number;
handleGetCaptcha: () => void;
}
const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetCaptcha }) => {
return (
<>
<div className="form-section-title"></div>
{/* 营业执照附件和有效期 */}
<Row gutter={24}>
<Col span={8}>
<Form.Item
name="businessLicense"
label="营业执照附件"
rules={[{ required: true, message: '请上传营业执照附件' }]}
>
<Upload
name="businessLicense"
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>
<Col span={8}>
<Form.Item
name="businessLicenseExpiry"
label="营业执照有效期"
rules={[{ required: false, message: '请选择营业执照有效期' }]}
>
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="companyName"
label="企业名称"
rules={[{ required: true, message: '请输入企业名称' }]}
>
<Input placeholder="请输入企业名称" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="socialCreditCode"
label="统一社会信用代码"
rules={[
{ required: true, message: '请输入统一社会信用代码' },
{ pattern: /^[0-9A-HJ-NPQRTUWXY]{18}$/, message: '请输入正确的统一社会信用代码' },
]}
>
<Input placeholder="请输入正确的统一社会信用代码" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="legalPerson"
label="企业法定代表人"
rules={[{ required: true, message: '请输入企业法定代表人/负责人' }]}
>
<Input placeholder="张三" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="registeredCapitalGroup"
label="注册资本"
rules={[{ required: true, message: '请输入注册资本' }]}
>
<Input.Group compact style={{ display: 'flex' }}>
<span
style={{
display: 'flex',
alignItems: 'center',
padding: '0 11px',
border: '1px solid #d9d9d9',
borderRight: 0,
backgroundColor: '#f5f5f5',
borderRadius: '2px 0 0 2px',
}}
>
</span>
<Form.Item
name="registeredCapital"
noStyle
rules={[{ required: true, message: '请输入注册资本金额' }]}
>
<Input
type="number"
placeholder="请输入金额"
style={{ flex: 1, borderRadius: '0' }}
/>
</Form.Item>
<span
style={{
display: 'flex',
alignItems: 'center',
padding: '0 11px',
border: '1px solid #d9d9d9',
borderLeft: 0,
backgroundColor: '#f5f5f5',
borderRadius: '0 2px 2px 0',
}}
>
</span>
</Input.Group>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="companyType"
label="企业性质"
rules={[{ required: true, message: '请选择企业性质' }]}
>
<Select placeholder="请选择企业性质">
<Option value="limited"></Option>
<Option value="joint"></Option>
<Option value="individual"></Option>
<Option value="other"></Option>
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="supplierType"
label="供应商类型"
rules={[{ required: true, message: '请选择供应商类型' }]}
>
<Select placeholder="请选择类型">
<Option value="manufacturer"></Option>
<Option value="agent"></Option>
<Option value="service"></Option>
<Option value="other"></Option>
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="parentCompanyInfo" label="母公司/出资人">
<Input placeholder="请输入母公司或出资人信息" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="registeredAddress"
label="注册地址"
rules={[{ required: true, message: '请输入注册地址' }]}
>
<Input prefix={<EnvironmentOutlined />} placeholder="上海市普陀区XX路1888号" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="officeAddress" label="办公地址">
<Input
prefix={<EnvironmentOutlined />}
placeholder="请具体注明省、市、区、路、门牌号"
/>
</Form.Item>
</Col>
<Col span={24}>
<Form.Item
name="businessScope"
label="经营范围"
rules={[{ required: true, message: '请输入经营范围' }]}
labelCol={{ span: 2 }}
wrapperCol={{ span: 21 }}
>
<TextArea
placeholder="金融专用产品、广告传媒"
rows={2}
maxLength={200}
showCount
style={{ resize: 'none' }}
/>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="contactPerson"
label="联系人姓名"
rules={[{ required: true, message: '请输入联系人姓名' }]}
>
<Input placeholder="请输入联系人姓名" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="contactPhone"
label="联系人手机"
rules={[
{ required: true, message: '请输入联系人手机号' },
{ pattern: /^1[3-9]\d{9}$/, message: '请输入有效的手机号' },
]}
>
<Input prefix={<MobileOutlined />} placeholder="请输入11位手机号码" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="captcha"
label="验证码"
rules={[{ required: true, message: '请输入验证码' }]}
>
<Row gutter={8}>
<Col span={14}>
<Input placeholder="请输入短信验证码" />
</Col>
<Col span={10}>
<Button
type="primary"
style={{ marginTop: 0 }}
disabled={countdown > 0}
onClick={handleGetCaptcha}
>
{countdown > 0 ? `${countdown}s` : '获取验证码'}
</Button>
</Col>
</Row>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="contactIdType" label="联系人身份类别">
<Select placeholder="请选择类型">
<Option value="idcard"></Option>
<Option value="passport"></Option>
<Option value="other"></Option>
</Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="contactIdNumber" label="联系人证件号码">
<Input placeholder="请填写联系人正确的身份证号" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item
name="contactEmail"
label="联系人邮箱"
rules={[
{ type: 'email', message: '请输入有效的电子邮箱' },
{ required: true, message: '请输入电子邮箱' },
]}
>
<Input prefix={<MailOutlined />} placeholder="请输入企业联系电话" />
</Form.Item>
</Col>
<Col span={8}>
<Form.Item name="telephone" label="固定电话">
<Input placeholder="XXX@XXX.com" />
</Form.Item>
</Col>
</Row>
{/* 资质信息 */}
<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"
className="qualification-table"
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>
<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>
<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"
className="qualification-table"
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>
<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: '请选择答案' }]}
>
<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>
),
},
]}
/>
<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格式文件!');
}
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
message.error('文件大小不能超过10MB!');
}
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 isLt20M;
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
</Col>
</Row>
</>
);
};
export default DomesticForm;