对接注册接口 对接一半, 问卷对接完了
This commit is contained in:
@ -5,11 +5,11 @@ export default {
|
||||
// changeOrigin: true,
|
||||
// pathRewrite: { '^': '' },
|
||||
// },
|
||||
'/api/*': {
|
||||
'/api': {
|
||||
// target: 'http://10.242.37.148:18022',//连接天宫的ng
|
||||
target: 'http://localhost:3000',//连接天宫的ng
|
||||
target: 'http://10.0.0.14:18012',//连接天宫的ng
|
||||
changeOrigin: true,
|
||||
pathRewrite: { '^': '' },
|
||||
pathRewrite: { '^/api': '' },
|
||||
},
|
||||
},
|
||||
UAT: {
|
||||
|
16608
pnpm-lock.yaml
generated
Normal file
16608
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,19 +1,44 @@
|
||||
// 供应商注册
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { useIntl, history } from 'umi';
|
||||
import { Form, Button, message, Radio, Checkbox, Modal } from 'antd';
|
||||
import { Form, Button, message, Radio, Checkbox, Modal, Spin } from 'antd';
|
||||
import { HomeOutlined } from '@ant-design/icons';
|
||||
import DomesticForm from './supplier/DomesticForm';
|
||||
import ForeignForm from './supplier/ForeignForm';
|
||||
import { coscoSupplierBaseAdd, fetchSurveyQuestions } from '@/servers/api/register';
|
||||
import './register.less';
|
||||
|
||||
const SupplierRegister: React.FC = () => {
|
||||
const [form] = Form.useForm();
|
||||
const intl = useIntl();
|
||||
const [supplierType, setSupplierType] = useState<string>('domestic');
|
||||
const [supplierType, setSupplierType] = useState<string>('dvs');
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [countdown, setCountdown] = useState(0);
|
||||
const [modalVisible, setModalVisible] = useState(false);
|
||||
const [surveyQuestions, setSurveyQuestions] = useState<API.SurveyQuestionResponse>([]);
|
||||
const [fetchingQuestions, setFetchingQuestions] = useState(false);
|
||||
|
||||
// 获取问卷列表
|
||||
useEffect(() => {
|
||||
const fetchQuestions = async () => {
|
||||
setFetchingQuestions(true);
|
||||
try {
|
||||
const response = await fetchSurveyQuestions();
|
||||
if (response.success) {
|
||||
setSurveyQuestions(response.data || []);
|
||||
} else {
|
||||
message.error(response.message || '获取问卷列表失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取问卷列表出错:', error);
|
||||
message.error('获取问卷列表出错');
|
||||
} finally {
|
||||
setFetchingQuestions(false);
|
||||
}
|
||||
};
|
||||
|
||||
fetchQuestions();
|
||||
}, []);
|
||||
|
||||
// 获取短信验证码
|
||||
const handleGetCaptcha = () => {
|
||||
@ -37,17 +62,30 @@ const SupplierRegister: React.FC = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const onFinish = (values: any) => {
|
||||
const onFinish = async (values: any) => {
|
||||
setLoading(true);
|
||||
// 手动将 supplierType 添加到表单值中
|
||||
values.supplierType = supplierType;
|
||||
try {
|
||||
// 确保供应商类型添加到表单值中
|
||||
values.coscoSupplierBase = values.coscoSupplierBase || {};
|
||||
values.coscoSupplierBase.supplierType = supplierType;
|
||||
|
||||
console.log('供应商注册信息:', values);
|
||||
// 这里添加注册逻辑
|
||||
setTimeout(() => {
|
||||
setLoading(false);
|
||||
|
||||
// 直接调用API
|
||||
const response = await coscoSupplierBaseAdd(values);
|
||||
|
||||
if (response.success) {
|
||||
message.success('注册成功,请登录');
|
||||
history.push('/login');
|
||||
}, 1000);
|
||||
} else {
|
||||
message.error(response.message || '注册失败,请重试');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('注册出错:', error);
|
||||
message.error('注册失败,请稍后重试');
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
};
|
||||
|
||||
const handleSupplierTypeChange = (e: any) => {
|
||||
@ -68,6 +106,7 @@ const SupplierRegister: React.FC = () => {
|
||||
{intl.formatMessage({ id: 'register.supplier.title' })}
|
||||
</div>
|
||||
|
||||
<Spin spinning={fetchingQuestions}>
|
||||
<Form
|
||||
form={form}
|
||||
name="supplier_register"
|
||||
@ -80,16 +119,26 @@ const SupplierRegister: React.FC = () => {
|
||||
wrapperCol={{ span: 17 }}
|
||||
>
|
||||
<Form.Item label="企业类型" labelCol={{ span: 2 }} wrapperCol={{ span: 19 }}>
|
||||
<Radio.Group onChange={handleSupplierTypeChange} value={supplierType}>
|
||||
<Radio.Button value="domestic">境内企业/机构</Radio.Button>
|
||||
<Radio.Button value="foreign">境外企业</Radio.Button>
|
||||
<Radio.Group onChange={handleSupplierTypeChange} buttonStyle="solid" value={supplierType}>
|
||||
<Radio.Button value="dvs">境内企业/机构</Radio.Button>
|
||||
<Radio.Button value="ovs">境外企业</Radio.Button>
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
|
||||
{supplierType === 'domestic' ? (
|
||||
<DomesticForm form={form} countdown={countdown} handleGetCaptcha={handleGetCaptcha} />
|
||||
{supplierType === 'dvs' ? (
|
||||
<DomesticForm
|
||||
form={form}
|
||||
countdown={countdown}
|
||||
surveyQuestions={surveyQuestions}
|
||||
handleGetCaptcha={handleGetCaptcha}
|
||||
/>
|
||||
) : (
|
||||
<ForeignForm form={form} countdown={countdown} handleGetCaptcha={handleGetCaptcha} />
|
||||
<ForeignForm
|
||||
form={form}
|
||||
countdown={countdown}
|
||||
handleGetCaptcha={handleGetCaptcha}
|
||||
surveyQuestions={surveyQuestions}
|
||||
/>
|
||||
)}
|
||||
<Form.Item
|
||||
name="agreement"
|
||||
@ -127,6 +176,7 @@ const SupplierRegister: React.FC = () => {
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Spin>
|
||||
</div>
|
||||
|
||||
{/* 注册信息承诺书弹窗 */}
|
||||
|
@ -3,16 +3,25 @@
|
||||
* 封装了国内企业和境外企业注册表单相同的部分
|
||||
*/
|
||||
import React from 'react';
|
||||
import { Form, Input, Button, Select, Upload, DatePicker, Row, Col, Table, Radio, Cascader } from 'antd';
|
||||
import {
|
||||
UploadOutlined,
|
||||
PlusOutlined,
|
||||
DeleteOutlined,
|
||||
} from '@ant-design/icons';
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Select,
|
||||
Upload,
|
||||
DatePicker,
|
||||
Row,
|
||||
Col,
|
||||
Table,
|
||||
Radio,
|
||||
Cascader,
|
||||
Empty,
|
||||
} from 'antd';
|
||||
import { UploadOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
import { message } from 'antd';
|
||||
import { validateFileSize } from '@/utils/utils';
|
||||
|
||||
const { Option } = Select;
|
||||
const { LIST_IGNORE } = Upload;
|
||||
|
||||
// 中国省市区级联数据
|
||||
export const addressOptions = [
|
||||
@ -55,6 +64,11 @@ interface CommonFormSectionsProps {
|
||||
form: any;
|
||||
}
|
||||
|
||||
// 扩展问卷部分的属性接口
|
||||
interface SurveySectionProps extends CommonFormSectionsProps {
|
||||
surveyQuestions?: API.SurveyQuestionResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 资质信息表单部分
|
||||
* 包含资质证书类型、名称、编号、等级、发证机构、发证日期、有效期等
|
||||
@ -64,7 +78,7 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
|
||||
<>
|
||||
<div className="form-section-title">资质信息</div>
|
||||
|
||||
<Form.List name="qualifications">
|
||||
<Form.List name="coscoSupplierQualifications">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
<Table
|
||||
@ -156,11 +170,15 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
|
||||
dataIndex: 'issueDate',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={[record.name, 'issueDate']}
|
||||
name={[record.name, 'dateTime']}
|
||||
noStyle
|
||||
rules={[{ required: true, message: '请选择发证日期' }]}
|
||||
>
|
||||
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} />
|
||||
<DatePicker
|
||||
placeholder="年/月/日"
|
||||
style={{ width: '100%' }}
|
||||
format="YYYY-MM-DD"
|
||||
/>
|
||||
</Form.Item>
|
||||
),
|
||||
},
|
||||
@ -169,11 +187,15 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
|
||||
dataIndex: 'expiryDate',
|
||||
render: (_, record) => (
|
||||
<Form.Item
|
||||
name={[record.name, 'expiryDate']}
|
||||
name={[record.name, 'termOfValidity']}
|
||||
noStyle
|
||||
rules={[{ required: true, message: '请选择资质有效期' }]}
|
||||
>
|
||||
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} />
|
||||
<DatePicker
|
||||
placeholder="年/月/日"
|
||||
style={{ width: '100%' }}
|
||||
format="YYYY-MM-DD"
|
||||
/>
|
||||
</Form.Item>
|
||||
),
|
||||
},
|
||||
@ -187,7 +209,9 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
|
||||
rules={[{ required: true, message: '请上传资质证书附件' }]}
|
||||
>
|
||||
<Upload name="certFile" action="/api/upload" listType="text" maxCount={1}>
|
||||
<Button type="link" size="small">上传</Button>
|
||||
<Button type="link" size="small">
|
||||
上传
|
||||
</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
),
|
||||
@ -232,7 +256,7 @@ export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
<Row gutter={24}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="invoiceType"
|
||||
name={['coscoSupplierInvoice', 'taxpayerType']}
|
||||
label="纳税人类型"
|
||||
rules={[{ required: true, message: '请选择纳税人类型' }]}
|
||||
>
|
||||
@ -287,20 +311,7 @@ export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
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;
|
||||
}}
|
||||
beforeUpload={(file) => validateFileSize(file, 10, ['pdf', 'jpg', 'jpeg', 'png'])}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传文件</Button>
|
||||
</Upload>
|
||||
@ -320,7 +331,7 @@ export const BankAccountSection: React.FC<CommonFormSectionsProps> = ({ form })
|
||||
<>
|
||||
<div className="form-section-title">银行账户</div>
|
||||
|
||||
<Form.List name="bankAccounts">
|
||||
<Form.List name="coscoSupplierBank">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
<Table
|
||||
@ -439,7 +450,10 @@ export const BankAccountSection: React.FC<CommonFormSectionsProps> = ({ form })
|
||||
* 社会准则符合性自查问卷部分
|
||||
* 包含填写人信息和问卷内容
|
||||
*/
|
||||
export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
export const SurveySection: React.FC<SurveySectionProps> = ({ form, surveyQuestions }) => {
|
||||
// 使用API获取的问卷数据,如果没有则显示无数据状态
|
||||
const hasQuestions = surveyQuestions && surveyQuestions.length > 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="form-section-title">社会准则符合性自查问卷</div>
|
||||
@ -448,7 +462,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
<Row gutter={24}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyCompanyName"
|
||||
name={['coscoSupplierSurvey', 'supplierName']}
|
||||
label="供应商名称"
|
||||
rules={[{ required: true, message: '请输入供应商名称' }]}
|
||||
>
|
||||
@ -457,7 +471,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyPersonName"
|
||||
name={['coscoSupplierSurvey', 'name']}
|
||||
label="姓名"
|
||||
rules={[{ required: true, message: '请输入姓名' }]}
|
||||
>
|
||||
@ -466,7 +480,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyPosition"
|
||||
name={['coscoSupplierSurvey', 'position']}
|
||||
label="职位"
|
||||
rules={[{ required: true, message: '请输入职位' }]}
|
||||
>
|
||||
@ -475,7 +489,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyPhone"
|
||||
name={['coscoSupplierSurvey', 'phone']}
|
||||
label="电话号"
|
||||
rules={[{ required: true, message: '请输入电话号' }]}
|
||||
>
|
||||
@ -484,7 +498,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyEmail"
|
||||
name={['coscoSupplierSurvey', 'email']}
|
||||
label="邮箱"
|
||||
rules={[
|
||||
{ type: 'email', message: '请输入有效的电子邮箱' },
|
||||
@ -496,11 +510,11 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="surveyDate"
|
||||
name={['coscoSupplierSurvey', 'dateTime']}
|
||||
label="日期"
|
||||
rules={[{ required: true, message: '请选择日期' }]}
|
||||
>
|
||||
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} />
|
||||
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} format="YYYY-MM-DD" />
|
||||
</Form.Item>
|
||||
</Col>
|
||||
</Row>
|
||||
@ -508,69 +522,76 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
|
||||
<div className="questionnaire-header" style={{ marginTop: '20px' }}>
|
||||
问卷:
|
||||
</div>
|
||||
|
||||
{hasQuestions ? (
|
||||
<Form.List name="coscoSupplierSurveyQuestionReply">
|
||||
{(fields, { add, remove }) => {
|
||||
// 确保有足够的表单项对应每个问题
|
||||
if (fields.length < surveyQuestions.length) {
|
||||
const diff = surveyQuestions.length - fields.length;
|
||||
for (let i = 0; i < diff; i++) {
|
||||
add();
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<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我们保留记录遵守所有法律和此行为准则的必要文件,并根据要求为贵集团提供对文件的查看权。我们接允许贵集团在适当的时候,以验证行为准则执行为目的的现场勘查',
|
||||
},
|
||||
]}
|
||||
dataSource={surveyQuestions}
|
||||
columns={[
|
||||
{
|
||||
title: '序号',
|
||||
dataIndex: 'id',
|
||||
width: 60,
|
||||
align: 'center',
|
||||
render: (text, record, index) => index + 1,
|
||||
},
|
||||
{
|
||||
title: '问题',
|
||||
dataIndex: 'question',
|
||||
dataIndex: 'questionName',
|
||||
render: (text) => <div style={{ whiteSpace: 'pre-line' }}>{text}</div>,
|
||||
},
|
||||
{
|
||||
title: '回复',
|
||||
width: 650,
|
||||
render: (_, record) => (
|
||||
render: (_, record, index) => (
|
||||
<>
|
||||
<Form.Item
|
||||
name={['survey', `question${record.id}`]}
|
||||
name={[index, 'surveyQuestionId']}
|
||||
initialValue={record.id}
|
||||
hidden
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={[index, 'replyValue']}
|
||||
rules={[{ required: true, message: '请选择答案' }]}
|
||||
wrapperCol={{ span: 24 }}
|
||||
>
|
||||
<Radio.Group>
|
||||
<Radio value="yes">是</Radio>
|
||||
<Radio value="no">否</Radio>
|
||||
{record.id !== 1 && (
|
||||
<>
|
||||
<Radio value="partialYes">尚未完全符合,但将在企业发展中完善</Radio>
|
||||
<Radio value="noPlan">无任何计划</Radio>
|
||||
</>
|
||||
)}
|
||||
{record.coscoSurveyQuestionOptionList?.map((option: any) => (
|
||||
<Radio key={option.id} value={option.opentionValue}>
|
||||
{option.optionName}
|
||||
</Radio>
|
||||
))}
|
||||
</Radio.Group>
|
||||
</Form.Item>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
) : (
|
||||
<div style={{ padding: '30px 0' }}>
|
||||
<Empty description="暂无问卷数据" image={Empty.PRESENTED_IMAGE_SIMPLE} />
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -594,61 +615,154 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
|
||||
下载模版
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<Form.List name="coscoSupplierSurveyAttachments">
|
||||
{(fields, { add, remove }) => {
|
||||
// 确保至少有一项用于反商业贿赂承诺书
|
||||
if (fields.length === 0) {
|
||||
add({ attachmentsType: 'commitment' });
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
{fields.map((field, index) => (
|
||||
<div key={field.key} style={{ display: field.name === 0 ? 'block' : 'none' }}>
|
||||
<Form.Item
|
||||
name="antiBriberyDoc"
|
||||
name={[field.name, 'attachmentsType']}
|
||||
initialValue="commitment"
|
||||
hidden
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
|
||||
<Form.Item
|
||||
name={[field.name, 'fileUrl']}
|
||||
rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]}
|
||||
>
|
||||
<Upload
|
||||
name="antiBriberyDoc"
|
||||
name="file"
|
||||
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;
|
||||
beforeUpload={(file) =>
|
||||
validateFileSize(file, 10, ['pdf', 'doc', 'docx'])
|
||||
}
|
||||
onChange={(info) => {
|
||||
if (info.file.status === 'done') {
|
||||
const response = info.file.response;
|
||||
if (response && response.success) {
|
||||
// 填充文件信息
|
||||
form.setFieldsValue({
|
||||
coscoSupplierSurveyAttachments: [
|
||||
{
|
||||
...form.getFieldValue([
|
||||
'coscoSupplierSurveyAttachments',
|
||||
field.name,
|
||||
]),
|
||||
fileName: info.file.name,
|
||||
fileType: info.file.type,
|
||||
fileSize: info.file.size.toString(),
|
||||
filePath: response.filePath || response.url,
|
||||
},
|
||||
],
|
||||
});
|
||||
message.success(`${info.file.name} 上传成功`);
|
||||
} else {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
}
|
||||
const isLt10M = file.size / 1024 / 1024 < 10;
|
||||
if (!isLt10M) {
|
||||
message.error('文件大小不能超过10MB!');
|
||||
return LIST_IGNORE;
|
||||
}
|
||||
return isValidFormat && isLt10M;
|
||||
}}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传文件</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}}
|
||||
</Form.List>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
<div className="form-section-title">其他附件</div>
|
||||
<Row gutter={24}>
|
||||
<Col span={24}>
|
||||
<Form.Item name="otherAttachments">
|
||||
<Form.List name="coscoSupplierSurveyAttachments">
|
||||
{(fields, { add, remove }) => (
|
||||
<>
|
||||
<div className="upload-label">其他附件(非必须上传)</div>
|
||||
{fields.map((field, index) => (
|
||||
<div
|
||||
key={field.key}
|
||||
style={{
|
||||
display: index > 0 || fields.length === 1 ? 'block' : 'none',
|
||||
marginBottom: 8,
|
||||
}}
|
||||
>
|
||||
{index > 0 && (
|
||||
<Form.Item
|
||||
name={[field.name, 'attachmentsType']}
|
||||
initialValue="accessory"
|
||||
hidden
|
||||
>
|
||||
<Input />
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
{index > 0 && (
|
||||
<Form.Item name={[field.name, 'fileUrl']}>
|
||||
<Upload
|
||||
name="otherAttachments"
|
||||
name="file"
|
||||
action="/api/upload"
|
||||
listType="text"
|
||||
multiple
|
||||
beforeUpload={(file) => {
|
||||
const isLt20M = file.size / 1024 / 1024 < 20;
|
||||
if (!isLt20M) {
|
||||
message.error('文件大小不能超过20MB!');
|
||||
return LIST_IGNORE;
|
||||
maxCount={1}
|
||||
beforeUpload={(file) => validateFileSize(file, 20, ['*'])}
|
||||
onChange={(info) => {
|
||||
if (info.file.status === 'done') {
|
||||
const response = info.file.response;
|
||||
if (response && response.success) {
|
||||
// 填充文件信息
|
||||
const fieldValue = form.getFieldValue([
|
||||
'coscoSupplierSurveyAttachments',
|
||||
field.name,
|
||||
]);
|
||||
form.setFieldsValue({
|
||||
coscoSupplierSurveyAttachments: [
|
||||
{
|
||||
...fieldValue,
|
||||
fileName: info.file.name,
|
||||
fileType: info.file.type,
|
||||
fileSize: info.file.size.toString(),
|
||||
filePath: response.filePath || response.url,
|
||||
},
|
||||
],
|
||||
});
|
||||
message.success(`${info.file.name} 上传成功`);
|
||||
} else {
|
||||
message.error(`${info.file.name} 上传失败`);
|
||||
}
|
||||
}
|
||||
return isLt20M;
|
||||
}}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传</Button>
|
||||
</Upload>
|
||||
</Form.Item>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
|
||||
<Button
|
||||
type="dashed"
|
||||
onClick={() => add({ attachmentsType: 'accessory' })}
|
||||
icon={<PlusOutlined />}
|
||||
style={{ marginTop: 8 }}
|
||||
>
|
||||
添加更多附件
|
||||
</Button>
|
||||
</>
|
||||
)}
|
||||
</Form.List>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
|
@ -18,6 +18,7 @@ import {
|
||||
SurveySection,
|
||||
AttachmentSection,
|
||||
} from './CommonFormSections';
|
||||
import { validateFileSize } from '@/utils/utils';
|
||||
|
||||
const { Option } = Select;
|
||||
const { TextArea } = Input;
|
||||
@ -28,6 +29,7 @@ interface DomesticFormProps {
|
||||
form: any;
|
||||
countdown: number;
|
||||
handleGetCaptcha: () => void;
|
||||
surveyQuestions?: API.SurveyQuestionResponse; // 本身就是数组类型
|
||||
}
|
||||
|
||||
/**
|
||||
@ -35,7 +37,12 @@ interface DomesticFormProps {
|
||||
* 基本信息部分为境内企业特有
|
||||
* 其他部分使用通用表单组件
|
||||
*/
|
||||
const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetCaptcha }) => {
|
||||
const DomesticForm: React.FC<DomesticFormProps> = ({
|
||||
form,
|
||||
countdown,
|
||||
handleGetCaptcha,
|
||||
surveyQuestions,
|
||||
}) => {
|
||||
return (
|
||||
<>
|
||||
<div className="form-section-title">基本信息</div>
|
||||
@ -44,8 +51,9 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
<Row gutter={24}>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="businessLicense"
|
||||
name={['coscoSupplierBase', 'licenceAccessory']}
|
||||
label="营业执照附件"
|
||||
extra="pdf,jpg,jpeg,png类型的文件,大小不超过10MB"
|
||||
rules={[{ required: true, message: '请上传营业执照附件' }]}
|
||||
>
|
||||
<Upload
|
||||
@ -53,20 +61,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
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;
|
||||
}}
|
||||
beforeUpload={(file) => validateFileSize(file, 10, ['pdf', 'jpg', 'jpeg', 'png'])}
|
||||
>
|
||||
<Button icon={<UploadOutlined />}>上传文件</Button>
|
||||
</Upload>
|
||||
@ -74,16 +69,20 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="businessLicenseExpiry"
|
||||
name={['coscoSupplierBase', 'licenceDate']}
|
||||
label="营业执照有效期"
|
||||
rules={[{ required: false, message: '请选择营业执照有效期' }]}
|
||||
>
|
||||
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} />
|
||||
<DatePicker
|
||||
placeholder="请选择日期"
|
||||
style={{ width: '100%' }}
|
||||
format="YYYY-MM-DD"
|
||||
/>
|
||||
</Form.Item>
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="companyName"
|
||||
name={['coscoSupplierBase', 'name']}
|
||||
label="企业名称"
|
||||
rules={[{ required: true, message: '请输入企业名称' }]}
|
||||
>
|
||||
@ -113,50 +112,17 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
</Col>
|
||||
<Col span={8}>
|
||||
<Form.Item
|
||||
name="registeredCapitalGroup"
|
||||
name="registeredCapital"
|
||||
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' }}
|
||||
addonBefore="人民币"
|
||||
addonAfter="万元"
|
||||
/>
|
||||
</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
|
||||
@ -214,7 +180,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
label="经营范围"
|
||||
rules={[{ required: true, message: '请输入经营范围' }]}
|
||||
labelCol={{ span: 2 }}
|
||||
wrapperCol={{ span: 21 }}
|
||||
wrapperCol={{ span: 22 }}
|
||||
>
|
||||
<TextArea
|
||||
placeholder="金融专用产品、广告传媒"
|
||||
@ -306,7 +272,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
|
||||
<QualificationSection form={form} />
|
||||
<InvoiceSection form={form} />
|
||||
<BankAccountSection form={form} />
|
||||
<SurveySection form={form} />
|
||||
<SurveySection form={form} surveyQuestions={surveyQuestions} />
|
||||
<AttachmentSection form={form} />
|
||||
</>
|
||||
);
|
||||
|
@ -24,6 +24,7 @@ interface ForeignFormProps {
|
||||
form: any;
|
||||
countdown: number;
|
||||
handleGetCaptcha: () => void;
|
||||
surveyQuestions?: API.SurveyQuestionResponse; // 本身就是数组类型
|
||||
}
|
||||
|
||||
/**
|
||||
@ -31,7 +32,7 @@ interface ForeignFormProps {
|
||||
* 基本信息部分为境外企业特有
|
||||
* 其他部分使用通用表单组件
|
||||
*/
|
||||
const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCaptcha }) => {
|
||||
const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCaptcha, surveyQuestions }) => {
|
||||
return (
|
||||
<>
|
||||
{/* 境外企业特有的基本信息部分 */}
|
||||
@ -212,7 +213,7 @@ const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCap
|
||||
name="businessScope"
|
||||
label="经营范围"
|
||||
labelCol={{ span: 2 }}
|
||||
wrapperCol={{ span: 21 }}
|
||||
wrapperCol={{ span: 22 }}
|
||||
rules={[{ required: true, message: '请输入经营范围' }]}
|
||||
>
|
||||
<TextArea placeholder="请输入经营范围" rows={2} maxLength={200} showCount />
|
||||
@ -309,7 +310,7 @@ const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCap
|
||||
<QualificationSection form={form} />
|
||||
<InvoiceSection form={form} />
|
||||
<BankAccountSection form={form} />
|
||||
<SurveySection form={form} />
|
||||
<SurveySection form={form} surveyQuestions={surveyQuestions} />
|
||||
<AttachmentSection form={form} />
|
||||
</>
|
||||
);
|
||||
|
17
src/servers/api/register.ts
Normal file
17
src/servers/api/register.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { request } from 'umi';
|
||||
|
||||
// 供应商注册
|
||||
export async function coscoSupplierBaseAdd(data: API.RegisterRequest) {
|
||||
return request('/api/coscoSupplierBase/add', {
|
||||
method: 'POST',
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
// 获取调查问卷
|
||||
export async function fetchSurveyQuestions(): Promise<API.APIResponse<API.SurveyQuestionResponse>> {
|
||||
return request('/api/coscoSurveyQuestion/list', {
|
||||
method: 'GET',
|
||||
})
|
||||
}
|
115
src/servers/api/typings.d.ts
vendored
Normal file
115
src/servers/api/typings.d.ts
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
declare namespace API {
|
||||
type APIResponse<T> = {
|
||||
code: number;
|
||||
success: boolean;
|
||||
message: string;
|
||||
data: T;
|
||||
}
|
||||
|
||||
export type RegisterRequest = {
|
||||
coscoSupplierBank: CoscoSupplierBank[];
|
||||
coscoSupplierBase: CoscoSupplierBase;
|
||||
coscoSupplierInvoice: CoscoSupplierInvoice;
|
||||
coscoSupplierQualifications: CoscoSupplierQualification[];
|
||||
coscoSupplierSurvey: CoscoSupplierSurvey;
|
||||
coscoSupplierSurveyAttachments: CoscoSupplierSurveyAttachment[];
|
||||
coscoSupplierSurveyQuestionReply: CoscoSupplierSurveyQuestionReply[];
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierBank = {
|
||||
account?: string;
|
||||
accountName?: string;
|
||||
bank?: string;
|
||||
city?: string;
|
||||
currency?: string;
|
||||
interbankNumber?: string;
|
||||
nation?: string;
|
||||
province?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierBase = {
|
||||
capital: number;
|
||||
contactsEmail: string;
|
||||
contactsName: string;
|
||||
contactsPhone: string;
|
||||
contactsType: string;
|
||||
enterpriseType: string;
|
||||
idCard: string;
|
||||
legalPerson: string;
|
||||
licenceAccessory: string;
|
||||
licenceDate: string;
|
||||
name: string;
|
||||
nameEn: string;
|
||||
parentCompanyInvestor: string;
|
||||
range: string;
|
||||
regAddress: string;
|
||||
socialCreditCode: string;
|
||||
supplierType: string;
|
||||
telephone: string;
|
||||
workAddress: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierInvoice = {
|
||||
account: string;
|
||||
address: string;
|
||||
bank: string;
|
||||
head: string;
|
||||
phone: string;
|
||||
qualificationCertificate: string;
|
||||
taxpayerCode: string;
|
||||
taxpayerType: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierQualification = {
|
||||
accessory?: string;
|
||||
authority?: string;
|
||||
certificateType?: string;
|
||||
code?: string;
|
||||
dateTime?: string;
|
||||
name?: string;
|
||||
termOfValidity?: string;
|
||||
typeLevel?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierSurvey = {
|
||||
dateTime: string;
|
||||
email: string;
|
||||
name: string;
|
||||
phone: string;
|
||||
position: string;
|
||||
supplierName: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierSurveyAttachment = {
|
||||
attachmentsType: string;
|
||||
fileName: string;
|
||||
filePath: string;
|
||||
fileSize: string;
|
||||
fileType: string;
|
||||
fileUrl: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
|
||||
export type CoscoSupplierSurveyQuestionReply = {
|
||||
replyValue?: string;
|
||||
surveyQuestionId?: string;
|
||||
[property: string]: any;
|
||||
}
|
||||
// 调查问卷返回类型
|
||||
type SurveyQuestionResponse = {
|
||||
id: string;
|
||||
question: string;
|
||||
orderBy: string;
|
||||
coscoSurveyQuestionOptionList: {
|
||||
id: string;
|
||||
opentionValue: string;
|
||||
optionName: string;
|
||||
}[];
|
||||
}[]
|
||||
}
|
@ -4,7 +4,6 @@
|
||||
*/
|
||||
import { extend } from 'umi-request';
|
||||
import { message } from 'antd';
|
||||
import { getSessionRoleData, getUserToken } from '@/utils/session';
|
||||
import { history } from 'umi';
|
||||
|
||||
const codeMessage = {
|
||||
@ -54,7 +53,7 @@ const codeMessage = {
|
||||
*/
|
||||
const request = extend({
|
||||
// errorHandler, // 默认错误处理
|
||||
credentials: 'include', // 默认请求是否带上cookie
|
||||
credentials: 'include' // 默认请求是否带上cookie
|
||||
});
|
||||
// request拦截器, 改变url 或 options.
|
||||
request.interceptors.request.use(async (url, options) => {
|
||||
@ -65,44 +64,12 @@ request.interceptors.request.use(async (url, options) => {
|
||||
options.method === 'get'
|
||||
) {
|
||||
//如果是获取token的url,则不加token
|
||||
let headers = {};
|
||||
if (
|
||||
url.startsWith('/api/auth/partnerLogin') ||
|
||||
url.startsWith('/api/auth/login') ||
|
||||
url.startsWith('/api/auth/partnerLogin') ||
|
||||
url.startsWith('/api/api/mall-prox') ||
|
||||
url.startsWith('/api/auth/oauth/token') ||
|
||||
url.startsWith('/api/auth/reloadToken') ||
|
||||
url.startsWith('/api/auth/reloadPartnerToken') ||
|
||||
url.startsWith('/api/api/mall-expe') ||
|
||||
url == '/api/core-service-ebtp-userinfo/v1/userpassword/validatePassword' ||
|
||||
url.startsWith('/api/notification') ||
|
||||
url == '/api/core-service-ebtp-userinfo/outer/v1/ebtp/face/faceCompare' ||
|
||||
url == '/api/core-service-ebtp-userinfo/outer/v1/ebtp/face/rgbArray2Base64' ||
|
||||
url == '/api/notification/v1/notification/savaSmsByPhoneNew'
|
||||
) {
|
||||
headers = {
|
||||
...options.headers,
|
||||
};
|
||||
url.startsWith('/api/api/mall-prox') ||
|
||||
url.startsWith('/api/api/mall-expe') ||
|
||||
url == '/api/core-service-ebtp-userinfo/v1/userpassword/validatePassword' ||
|
||||
url == '/api/notification/v1/notification/savaSmsByPhoneNew'
|
||||
? (options.credentials = 'omit')
|
||||
: null;
|
||||
} else {
|
||||
headers = {
|
||||
Authorization: getUserToken() == null ? null : getUserToken(),
|
||||
currentRoleCode: getSessionRoleData()?.roleCode,
|
||||
...options.headers,
|
||||
};
|
||||
}
|
||||
// headers = {
|
||||
// Authorization: getUserToken() == null ? null : getUserToken(),
|
||||
// JwtToken: getSessionUserData() == null ? null : getSessionUserData().userId,
|
||||
// ...options.headers
|
||||
// }
|
||||
options.headers = headers;
|
||||
// options.headers = headers;
|
||||
}
|
||||
return {
|
||||
url,
|
||||
|
35
src/utils/utils.ts
Normal file
35
src/utils/utils.ts
Normal file
@ -0,0 +1,35 @@
|
||||
import { message,Upload } from 'antd';
|
||||
|
||||
// 验证上传文件大小是否符合要求
|
||||
// 参数说明:
|
||||
// file: 上传的文件
|
||||
// maxSize: 最大文件大小
|
||||
// type: 文件类型,支持*表示所有类型
|
||||
const FileTypeMap = {
|
||||
'application/pdf': 'pdf',
|
||||
'image/jpeg': 'jpg',
|
||||
'image/png': 'png',
|
||||
'application/msword': 'doc',
|
||||
'application/zip': 'zip',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': 'docx',
|
||||
'application/vnd.ms-excel': 'xls',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': 'xlsx',
|
||||
'application/vnd.ms-powerpoint': 'ppt',
|
||||
'application/vnd.openxmlformats-officedocument.presentationml.presentation': 'pptx',
|
||||
|
||||
}
|
||||
export const validateFileSize = (file: File, maxSize: number,type: string[]) => {
|
||||
console.log(file)
|
||||
const { LIST_IGNORE } = Upload;
|
||||
const isLtMaxSize = file.size / 1024 / 1024 < maxSize;
|
||||
if (!isLtMaxSize) {
|
||||
message.error(`文件大小不能超过${maxSize}MB!`);
|
||||
return LIST_IGNORE;
|
||||
}
|
||||
const isValidFormat = type.includes('*') || type.includes(FileTypeMap[file.type as keyof typeof FileTypeMap]);
|
||||
if (!isValidFormat) {
|
||||
message.error(`只能上传${type.join(',')}格式文件!`);
|
||||
return LIST_IGNORE;
|
||||
}
|
||||
return isValidFormat && isLtMaxSize;
|
||||
};
|
Reference in New Issue
Block a user