对接注册接口 对接一半, 问卷对接完了

This commit is contained in:
linxd
2025-06-17 14:03:57 +08:00
parent cd844a3231
commit e8804d6140
10 changed files with 17194 additions and 321 deletions

View File

@ -5,11 +5,11 @@ export default {
// changeOrigin: true, // changeOrigin: true,
// pathRewrite: { '^': '' }, // pathRewrite: { '^': '' },
// }, // },
'/api/*': { '/api': {
// target: 'http://10.242.37.148:18022',//连接天宫的ng // target: 'http://10.242.37.148:18022',//连接天宫的ng
target: 'http://localhost:3000',//连接天宫的ng target: 'http://10.0.0.14:18012',//连接天宫的ng
changeOrigin: true, changeOrigin: true,
pathRewrite: { '^': '' }, pathRewrite: { '^/api': '' },
}, },
}, },
UAT: { UAT: {

16608
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,19 +1,44 @@
// 供应商注册 // 供应商注册
import React, { useState } from 'react'; import React, { useState, useEffect } from 'react';
import { useIntl, history } from 'umi'; 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 { HomeOutlined } from '@ant-design/icons';
import DomesticForm from './supplier/DomesticForm'; import DomesticForm from './supplier/DomesticForm';
import ForeignForm from './supplier/ForeignForm'; import ForeignForm from './supplier/ForeignForm';
import { coscoSupplierBaseAdd, fetchSurveyQuestions } from '@/servers/api/register';
import './register.less'; import './register.less';
const SupplierRegister: React.FC = () => { const SupplierRegister: React.FC = () => {
const [form] = Form.useForm(); const [form] = Form.useForm();
const intl = useIntl(); const intl = useIntl();
const [supplierType, setSupplierType] = useState<string>('domestic'); const [supplierType, setSupplierType] = useState<string>('dvs');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [countdown, setCountdown] = useState(0); const [countdown, setCountdown] = useState(0);
const [modalVisible, setModalVisible] = useState(false); 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 = () => { const handleGetCaptcha = () => {
@ -37,17 +62,30 @@ const SupplierRegister: React.FC = () => {
}); });
}; };
const onFinish = (values: any) => { const onFinish = async (values: any) => {
setLoading(true); setLoading(true);
// 手动将 supplierType 添加到表单值中 try {
values.supplierType = supplierType; // 确保供应商类型添加到表单值中
console.log('供应商注册信息:', values); values.coscoSupplierBase = values.coscoSupplierBase || {};
// 这里添加注册逻辑 values.coscoSupplierBase.supplierType = supplierType;
setTimeout(() => {
console.log('供应商注册信息:', values);
// 直接调用API
const response = await coscoSupplierBaseAdd(values);
if (response.success) {
message.success('注册成功,请登录');
history.push('/login');
} else {
message.error(response.message || '注册失败,请重试');
}
} catch (error) {
console.error('注册出错:', error);
message.error('注册失败,请稍后重试');
} finally {
setLoading(false); setLoading(false);
message.success('注册成功,请登录'); }
history.push('/login');
}, 1000);
}; };
const handleSupplierTypeChange = (e: any) => { const handleSupplierTypeChange = (e: any) => {
@ -68,65 +106,77 @@ const SupplierRegister: React.FC = () => {
{intl.formatMessage({ id: 'register.supplier.title' })} {intl.formatMessage({ id: 'register.supplier.title' })}
</div> </div>
<Form <Spin spinning={fetchingQuestions}>
form={form} <Form
name="supplier_register" form={form}
className="register-form" name="supplier_register"
onFinish={onFinish} className="register-form"
layout="horizontal" onFinish={onFinish}
labelAlign="right" layout="horizontal"
size="large" labelAlign="right"
labelCol={{ span: 7 }} size="large"
wrapperCol={{ span: 17 }} labelCol={{ span: 7 }}
> 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>
</Form.Item>
{supplierType === 'domestic' ? (
<DomesticForm form={form} countdown={countdown} handleGetCaptcha={handleGetCaptcha} />
) : (
<ForeignForm form={form} countdown={countdown} handleGetCaptcha={handleGetCaptcha} />
)}
<Form.Item
name="agreement"
valuePropName="checked"
labelCol={{ span: 2 }}
wrapperCol={{ span: 19 }}
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error('请阅读并同意注册信息承诺书')),
},
]}
> >
<Checkbox> <Form.Item label="企业类型" labelCol={{ span: 2 }} wrapperCol={{ span: 19 }}>
<Radio.Group onChange={handleSupplierTypeChange} buttonStyle="solid" value={supplierType}>
<Button <Radio.Button value="dvs">/</Radio.Button>
type="link" <Radio.Button value="ovs"></Radio.Button>
onClick={(e) => { </Radio.Group>
e.preventDefault(); </Form.Item>
e.stopPropagation();
setModalVisible(true); {supplierType === 'dvs' ? (
}} <DomesticForm
> form={form}
countdown={countdown}
</Button> surveyQuestions={surveyQuestions}
</Checkbox> handleGetCaptcha={handleGetCaptcha}
</Form.Item> />
<Form.Item wrapperCol={{ span: 24 }}> ) : (
<div style={{ textAlign: 'center' }}> <ForeignForm
<Button type="primary" htmlType="submit" loading={loading}> form={form}
{intl.formatMessage({ id: 'register.submit' })} countdown={countdown}
</Button> handleGetCaptcha={handleGetCaptcha}
</div> surveyQuestions={surveyQuestions}
</Form.Item> />
</Form> )}
<Form.Item
name="agreement"
valuePropName="checked"
labelCol={{ span: 2 }}
wrapperCol={{ span: 19 }}
rules={[
{
validator: (_, value) =>
value
? Promise.resolve()
: Promise.reject(new Error('请阅读并同意注册信息承诺书')),
},
]}
>
<Checkbox>
<Button
type="link"
onClick={(e) => {
e.preventDefault();
e.stopPropagation();
setModalVisible(true);
}}
>
</Button>
</Checkbox>
</Form.Item>
<Form.Item wrapperCol={{ span: 24 }}>
<div style={{ textAlign: 'center' }}>
<Button type="primary" htmlType="submit" loading={loading}>
{intl.formatMessage({ id: 'register.submit' })}
</Button>
</div>
</Form.Item>
</Form>
</Spin>
</div> </div>
{/* 注册信息承诺书弹窗 */} {/* 注册信息承诺书弹窗 */}

View File

@ -3,16 +3,25 @@
* 封装了国内企业和境外企业注册表单相同的部分 * 封装了国内企业和境外企业注册表单相同的部分
*/ */
import React from 'react'; import React from 'react';
import { Form, Input, Button, Select, Upload, DatePicker, Row, Col, Table, Radio, Cascader } from 'antd';
import { import {
UploadOutlined, Form,
PlusOutlined, Input,
DeleteOutlined, Button,
} from '@ant-design/icons'; Select,
Upload,
DatePicker,
Row,
Col,
Table,
Radio,
Cascader,
Empty,
} from 'antd';
import { UploadOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { message } from 'antd'; import { message } from 'antd';
import { validateFileSize } from '@/utils/utils';
const { Option } = Select; const { Option } = Select;
const { LIST_IGNORE } = Upload;
// 中国省市区级联数据 // 中国省市区级联数据
export const addressOptions = [ export const addressOptions = [
@ -55,6 +64,11 @@ interface CommonFormSectionsProps {
form: any; 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> <div className="form-section-title"></div>
<Form.List name="qualifications"> <Form.List name="coscoSupplierQualifications">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<> <>
<Table <Table
@ -156,11 +170,15 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
dataIndex: 'issueDate', dataIndex: 'issueDate',
render: (_, record) => ( render: (_, record) => (
<Form.Item <Form.Item
name={[record.name, 'issueDate']} name={[record.name, 'dateTime']}
noStyle noStyle
rules={[{ required: true, message: '请选择发证日期' }]} rules={[{ required: true, message: '请选择发证日期' }]}
> >
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} /> <DatePicker
placeholder="年/月/日"
style={{ width: '100%' }}
format="YYYY-MM-DD"
/>
</Form.Item> </Form.Item>
), ),
}, },
@ -169,11 +187,15 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
dataIndex: 'expiryDate', dataIndex: 'expiryDate',
render: (_, record) => ( render: (_, record) => (
<Form.Item <Form.Item
name={[record.name, 'expiryDate']} name={[record.name, 'termOfValidity']}
noStyle noStyle
rules={[{ required: true, message: '请选择资质有效期' }]} rules={[{ required: true, message: '请选择资质有效期' }]}
> >
<DatePicker placeholder="年/月/日" style={{ width: '100%' }} /> <DatePicker
placeholder="年/月/日"
style={{ width: '100%' }}
format="YYYY-MM-DD"
/>
</Form.Item> </Form.Item>
), ),
}, },
@ -187,7 +209,9 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
rules={[{ required: true, message: '请上传资质证书附件' }]} rules={[{ required: true, message: '请上传资质证书附件' }]}
> >
<Upload name="certFile" action="/api/upload" listType="text" maxCount={1}> <Upload name="certFile" action="/api/upload" listType="text" maxCount={1}>
<Button type="link" size="small"></Button> <Button type="link" size="small">
</Button>
</Upload> </Upload>
</Form.Item> </Form.Item>
), ),
@ -232,7 +256,7 @@ export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
<Row gutter={24}> <Row gutter={24}>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="invoiceType" name={['coscoSupplierInvoice', 'taxpayerType']}
label="纳税人类型" label="纳税人类型"
rules={[{ required: true, message: '请选择纳税人类型' }]} rules={[{ required: true, message: '请选择纳税人类型' }]}
> >
@ -287,20 +311,7 @@ export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
action="/api/upload" action="/api/upload"
listType="text" listType="text"
maxCount={1} maxCount={1}
beforeUpload={(file) => { beforeUpload={(file) => validateFileSize(file, 10, ['pdf', 'jpg', 'jpeg', 'png'])}
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> <Button icon={<UploadOutlined />}></Button>
</Upload> </Upload>
@ -320,7 +331,7 @@ export const BankAccountSection: React.FC<CommonFormSectionsProps> = ({ form })
<> <>
<div className="form-section-title"></div> <div className="form-section-title"></div>
<Form.List name="bankAccounts"> <Form.List name="coscoSupplierBank">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<> <>
<Table <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 ( return (
<> <>
<div className="form-section-title"></div> <div className="form-section-title"></div>
@ -448,7 +462,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
<Row gutter={24}> <Row gutter={24}>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyCompanyName" name={['coscoSupplierSurvey', 'supplierName']}
label="供应商名称" label="供应商名称"
rules={[{ required: true, message: '请输入供应商名称' }]} rules={[{ required: true, message: '请输入供应商名称' }]}
> >
@ -457,7 +471,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyPersonName" name={['coscoSupplierSurvey', 'name']}
label="姓名" label="姓名"
rules={[{ required: true, message: '请输入姓名' }]} rules={[{ required: true, message: '请输入姓名' }]}
> >
@ -466,7 +480,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyPosition" name={['coscoSupplierSurvey', 'position']}
label="职位" label="职位"
rules={[{ required: true, message: '请输入职位' }]} rules={[{ required: true, message: '请输入职位' }]}
> >
@ -475,7 +489,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyPhone" name={['coscoSupplierSurvey', 'phone']}
label="电话号" label="电话号"
rules={[{ required: true, message: '请输入电话号' }]} rules={[{ required: true, message: '请输入电话号' }]}
> >
@ -484,7 +498,7 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyEmail" name={['coscoSupplierSurvey', 'email']}
label="邮箱" label="邮箱"
rules={[ rules={[
{ type: 'email', message: '请输入有效的电子邮箱' }, { type: 'email', message: '请输入有效的电子邮箱' },
@ -496,11 +510,11 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="surveyDate" name={['coscoSupplierSurvey', 'dateTime']}
label="日期" label="日期"
rules={[{ required: true, message: '请选择日期' }]} rules={[{ required: true, message: '请选择日期' }]}
> >
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} /> <DatePicker placeholder="请选择日期" style={{ width: '100%' }} format="YYYY-MM-DD" />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
@ -508,69 +522,76 @@ export const SurveySection: React.FC<CommonFormSectionsProps> = ({ form }) => {
<div className="questionnaire-header" style={{ marginTop: '20px' }}> <div className="questionnaire-header" style={{ marginTop: '20px' }}>
</div> </div>
<Table
pagination={false} {hasQuestions ? (
bordered <Form.List name="coscoSupplierSurveyQuestionReply">
size="middle" {(fields, { add, remove }) => {
rowKey="id" // 确保有足够的表单项对应每个问题
dataSource={[ if (fields.length < surveyQuestions.length) {
{ const diff = surveyQuestions.length - fields.length;
id: 1, for (let i = 0; i < diff; i++) {
question: add();
'法律法规:\n我们确保经营和提供的产品服务遵守国家及各业务所在地的所有使用法律、法规及健康和安全', }
}, }
{
id: 2, return (
question: <Table
'健康和安全:\n我们为员工提供符合法律法规的安全且健康的工作场所。我们建立安全管理体系并向员工传达工作场所或生活设施的健康和安全标准致力于减少工作对员工造成的伤害和疾病。', pagination={false}
}, bordered
{ size="middle"
id: 3, rowKey="id"
question: dataSource={surveyQuestions}
'环境:\n我们能够以环境友好的方式经营。我们遵守适用的环境法律、法规和标准并建立有效的环境管理体系。\n我们遵守贵集团对相关产品或服务的部分附加环境要求这些要求和规定体现在设计与产品规范的合同文档中。', columns={[
}, {
{ title: '序号',
id: 4, dataIndex: 'id',
question: width: 60,
'监督和记录\n我们保留记录遵守所有法律和此行为准则的必要文件并根据要求为贵集团提供对文件的查看权。我们接允许贵集团在适当的时候以验证行为准则执行为目的的现场勘查', align: 'center',
}, render: (text, record, index) => index + 1,
]} },
columns={[ {
{ title: '问题',
title: '序号', dataIndex: 'questionName',
dataIndex: 'id', render: (text) => <div style={{ whiteSpace: 'pre-line' }}>{text}</div>,
width: 60, },
align: 'center', {
}, title: '回复',
{ width: 650,
title: '问题', render: (_, record, index) => (
dataIndex: 'question', <>
render: (text) => <div style={{ whiteSpace: 'pre-line' }}>{text}</div>, <Form.Item
}, name={[index, 'surveyQuestionId']}
{ initialValue={record.id}
title: '回复', hidden
width: 650, >
render: (_, record) => ( <Input />
<Form.Item </Form.Item>
name={['survey', `question${record.id}`]} <Form.Item
rules={[{ required: true, message: '请选择答案' }]} name={[index, 'replyValue']}
wrapperCol={{ span: 24 }} rules={[{ required: true, message: '请选择答案' }]}
> wrapperCol={{ span: 24 }}
<Radio.Group> >
<Radio value="yes"></Radio> <Radio.Group>
<Radio value="no"></Radio> {record.coscoSurveyQuestionOptionList?.map((option: any) => (
{record.id !== 1 && ( <Radio key={option.id} value={option.opentionValue}>
<> {option.optionName}
<Radio value="partialYes"></Radio> </Radio>
<Radio value="noPlan"></Radio> ))}
</> </Radio.Group>
)} </Form.Item>
</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> </Button>
</div> </div>
<Form.Item
name="antiBriberyDoc" <Form.List name="coscoSupplierSurveyAttachments">
rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]} {(fields, { add, remove }) => {
> // 确保至少有一项用于反商业贿赂承诺书
<Upload if (fields.length === 0) {
name="antiBriberyDoc" add({ attachmentsType: 'commitment' });
action="/api/upload" }
listType="text"
maxCount={1} return (
beforeUpload={(file) => { <div>
const isValidFormat = {fields.map((field, index) => (
file.type === 'application/pdf' || <div key={field.key} style={{ display: field.name === 0 ? 'block' : 'none' }}>
file.type === 'application/msword' || <Form.Item
file.type === name={[field.name, 'attachmentsType']}
'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; initialValue="commitment"
if (!isValidFormat) { hidden
message.error('只能上传PDF/DOC/DOCX格式文件!'); >
return LIST_IGNORE; <Input />
} </Form.Item>
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) { <Form.Item
message.error('文件大小不能超过10MB!'); name={[field.name, 'fileUrl']}
return LIST_IGNORE; rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]}
} >
return isValidFormat && isLt10M; <Upload
}} name="file"
> action="/api/upload"
<Button icon={<UploadOutlined />}></Button> listType="text"
</Upload> maxCount={1}
</Form.Item> 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} 上传失败`);
}
}
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
</div>
))}
</div>
);
}}
</Form.List>
</Col> </Col>
</Row> </Row>
<div className="form-section-title"></div> <div className="form-section-title"></div>
<Row gutter={24}> <Row gutter={24}>
<Col span={24}> <Col span={24}>
<Form.Item name="otherAttachments"> <Form.List name="coscoSupplierSurveyAttachments">
<div className="upload-label"></div> {(fields, { add, remove }) => (
<Upload <>
name="otherAttachments" <div className="upload-label"></div>
action="/api/upload" {fields.map((field, index) => (
listType="text" <div
multiple key={field.key}
beforeUpload={(file) => { style={{
const isLt20M = file.size / 1024 / 1024 < 20; display: index > 0 || fields.length === 1 ? 'block' : 'none',
if (!isLt20M) { marginBottom: 8,
message.error('文件大小不能超过20MB!'); }}
return LIST_IGNORE; >
} {index > 0 && (
return isLt20M; <Form.Item
}} name={[field.name, 'attachmentsType']}
> initialValue="accessory"
<Button icon={<UploadOutlined />}></Button> hidden
</Upload> >
</Form.Item> <Input />
</Form.Item>
)}
{index > 0 && (
<Form.Item name={[field.name, 'fileUrl']}>
<Upload
name="file"
action="/api/upload"
listType="text"
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} 上传失败`);
}
}
}}
>
<Button icon={<UploadOutlined />}></Button>
</Upload>
</Form.Item>
)}
</div>
))}
<Button
type="dashed"
onClick={() => add({ attachmentsType: 'accessory' })}
icon={<PlusOutlined />}
style={{ marginTop: 8 }}
>
</Button>
</>
)}
</Form.List>
</Col> </Col>
</Row> </Row>
</> </>

View File

@ -18,6 +18,7 @@ import {
SurveySection, SurveySection,
AttachmentSection, AttachmentSection,
} from './CommonFormSections'; } from './CommonFormSections';
import { validateFileSize } from '@/utils/utils';
const { Option } = Select; const { Option } = Select;
const { TextArea } = Input; const { TextArea } = Input;
@ -28,6 +29,7 @@ interface DomesticFormProps {
form: any; form: any;
countdown: number; countdown: number;
handleGetCaptcha: () => void; 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 ( return (
<> <>
<div className="form-section-title"></div> <div className="form-section-title"></div>
@ -44,8 +51,9 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
<Row gutter={24}> <Row gutter={24}>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="businessLicense" name={['coscoSupplierBase', 'licenceAccessory']}
label="营业执照附件" label="营业执照附件"
extra="pdf,jpg,jpeg,png类型的文件,大小不超过10MB"
rules={[{ required: true, message: '请上传营业执照附件' }]} rules={[{ required: true, message: '请上传营业执照附件' }]}
> >
<Upload <Upload
@ -53,20 +61,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
action="/api/upload" action="/api/upload"
listType="text" listType="text"
maxCount={1} maxCount={1}
beforeUpload={(file) => { beforeUpload={(file) => validateFileSize(file, 10, ['pdf', 'jpg', 'jpeg', 'png'])}
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> <Button icon={<UploadOutlined />}></Button>
</Upload> </Upload>
@ -74,16 +69,20 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="businessLicenseExpiry" name={['coscoSupplierBase', 'licenceDate']}
label="营业执照有效期" label="营业执照有效期"
rules={[{ required: false, message: '请选择营业执照有效期' }]} rules={[{ required: false, message: '请选择营业执照有效期' }]}
> >
<DatePicker placeholder="请选择日期" style={{ width: '100%' }} /> <DatePicker
placeholder="请选择日期"
style={{ width: '100%' }}
format="YYYY-MM-DD"
/>
</Form.Item> </Form.Item>
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="companyName" name={['coscoSupplierBase', 'name']}
label="企业名称" label="企业名称"
rules={[{ required: true, message: '请输入企业名称' }]} rules={[{ required: true, message: '请输入企业名称' }]}
> >
@ -113,49 +112,16 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
</Col> </Col>
<Col span={8}> <Col span={8}>
<Form.Item <Form.Item
name="registeredCapitalGroup" name="registeredCapital"
label="注册资本" label="注册资本"
rules={[{ required: true, message: '请输入注册资本' }]} rules={[{ required: true, message: '请输入注册资本' }]}
> >
<Input.Group compact style={{ display: 'flex' }}> <Input
<span type="number"
style={{ placeholder="请输入金额"
display: 'flex', addonBefore="人民币"
alignItems: 'center', addonAfter="万元"
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> </Form.Item>
</Col> </Col>
<Col span={8}> <Col span={8}>
@ -214,7 +180,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
label="经营范围" label="经营范围"
rules={[{ required: true, message: '请输入经营范围' }]} rules={[{ required: true, message: '请输入经营范围' }]}
labelCol={{ span: 2 }} labelCol={{ span: 2 }}
wrapperCol={{ span: 21 }} wrapperCol={{ span: 22 }}
> >
<TextArea <TextArea
placeholder="金融专用产品、广告传媒" placeholder="金融专用产品、广告传媒"
@ -306,7 +272,7 @@ const DomesticForm: React.FC<DomesticFormProps> = ({ form, countdown, handleGetC
<QualificationSection form={form} /> <QualificationSection form={form} />
<InvoiceSection form={form} /> <InvoiceSection form={form} />
<BankAccountSection form={form} /> <BankAccountSection form={form} />
<SurveySection form={form} /> <SurveySection form={form} surveyQuestions={surveyQuestions} />
<AttachmentSection form={form} /> <AttachmentSection form={form} />
</> </>
); );

View File

@ -24,6 +24,7 @@ interface ForeignFormProps {
form: any; form: any;
countdown: number; countdown: number;
handleGetCaptcha: () => void; 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 ( return (
<> <>
{/* 境外企业特有的基本信息部分 */} {/* 境外企业特有的基本信息部分 */}
@ -212,7 +213,7 @@ const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCap
name="businessScope" name="businessScope"
label="经营范围" label="经营范围"
labelCol={{ span: 2 }} labelCol={{ span: 2 }}
wrapperCol={{ span: 21 }} wrapperCol={{ span: 22 }}
rules={[{ required: true, message: '请输入经营范围' }]} rules={[{ required: true, message: '请输入经营范围' }]}
> >
<TextArea placeholder="请输入经营范围" rows={2} maxLength={200} showCount /> <TextArea placeholder="请输入经营范围" rows={2} maxLength={200} showCount />
@ -309,7 +310,7 @@ const ForeignForm: React.FC<ForeignFormProps> = ({ form, countdown, handleGetCap
<QualificationSection form={form} /> <QualificationSection form={form} />
<InvoiceSection form={form} /> <InvoiceSection form={form} />
<BankAccountSection form={form} /> <BankAccountSection form={form} />
<SurveySection form={form} /> <SurveySection form={form} surveyQuestions={surveyQuestions} />
<AttachmentSection form={form} /> <AttachmentSection form={form} />
</> </>
); );

View 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
View 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;
}[];
}[]
}

View File

@ -4,7 +4,6 @@
*/ */
import { extend } from 'umi-request'; import { extend } from 'umi-request';
import { message } from 'antd'; import { message } from 'antd';
import { getSessionRoleData, getUserToken } from '@/utils/session';
import { history } from 'umi'; import { history } from 'umi';
const codeMessage = { const codeMessage = {
@ -54,7 +53,7 @@ const codeMessage = {
*/ */
const request = extend({ const request = extend({
// errorHandler, // 默认错误处理 // errorHandler, // 默认错误处理
credentials: 'include', // 默认请求是否带上cookie credentials: 'include' // 默认请求是否带上cookie
}); });
// request拦截器, 改变url 或 options. // request拦截器, 改变url 或 options.
request.interceptors.request.use(async (url, options) => { request.interceptors.request.use(async (url, options) => {
@ -65,44 +64,12 @@ request.interceptors.request.use(async (url, options) => {
options.method === 'get' options.method === 'get'
) { ) {
//如果是获取token的url则不加token //如果是获取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 = { // headers = {
// Authorization: getUserToken() == null ? null : getUserToken(), // Authorization: getUserToken() == null ? null : getUserToken(),
// JwtToken: getSessionUserData() == null ? null : getSessionUserData().userId, // JwtToken: getSessionUserData() == null ? null : getSessionUserData().userId,
// ...options.headers // ...options.headers
// } // }
options.headers = headers; // options.headers = headers;
} }
return { return {
url, url,

35
src/utils/utils.ts Normal file
View 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;
};