This commit is contained in:
孙景学
2025-07-21 14:04:20 +08:00
parent 58dd501cb2
commit e9ebd6ac1c
13 changed files with 320 additions and 265 deletions

View File

@ -2,7 +2,7 @@ import { history } from 'umi';
export function onRouteChange({ location }: any) { export function onRouteChange({ location }: any) {
const token = sessionStorage.getItem('token'); const token = sessionStorage.getItem('token');
const whiteList = ['/login', '/forgot', '/403', '/404']; const whiteList = ['/login', '/forgot', '/register/supplier', '/register/expert', '/403', '/404'];
if (!token && !whiteList.includes(location.pathname)) { if (!token && !whiteList.includes(location.pathname)) {
history.replace('/login'); history.replace('/login');
} }

View File

@ -4,7 +4,7 @@ import { treeData } from './services'; // 你的接口
export interface AccessDepartmentSelectProps { export interface AccessDepartmentSelectProps {
value?: string | number; value?: string | number;
onChange?: (value: string | number) => void; onChange?: (value: string | number, label: any, extra: any) => void;
placeholder?: string; placeholder?: string;
disabled?: boolean; disabled?: boolean;
orgCategory?: string; orgCategory?: string;

View File

@ -100,7 +100,7 @@ const SupplierRegister: React.FC<supplierWithInputProps> = (props) => {
fileType: values.attachments.file.response.fileType, fileType: values.attachments.file.response.fileType,
fileSize: values.attachments.file.response.fileSize, fileSize: values.attachments.file.response.fileSize,
filePath: values.attachments.file.response.filePath, filePath: values.attachments.file.response.filePath,
fileUrl: values.attachments.file.response.filePath, fileUrl: values.attachments.file.response.url,
}, },
]; ];
} }

View File

@ -16,6 +16,7 @@ import {
Radio, Radio,
Cascader, Cascader,
Empty, Empty,
Descriptions
} from 'antd'; } from 'antd';
import { UploadOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons'; import { UploadOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
import { message } from 'antd'; import { message } from 'antd';
@ -257,9 +258,8 @@ export const QualificationSection: React.FC<CommonFormSectionsProps> = ({ form }
<FileUpload <FileUpload
listType="text" listType="text"
maxCount={1} maxCount={1}
allowedTypes={['pdf', 'jpg', 'jpeg', 'png']} allowedTypes={['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png']}
maxSize={10} maxSize={10}
tip="pdf,jpg,jpeg,png类型的文件,大小不超过10MB"
/> />
</Form.Item> </Form.Item>
), ),
@ -379,9 +379,8 @@ export const InvoiceSection: React.FC<CommonFormSectionsProps> = ({ form }) => {
<FileUpload <FileUpload
listType="text" listType="text"
maxCount={1} maxCount={1}
allowedTypes={['pdf', 'jpg', 'jpeg', 'png']} allowedTypes={['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png']}
maxSize={10} maxSize={10}
tip="pdf,jpg,jpeg,png类型的文件,大小不超过10MB"
/> />
</Form.Item> </Form.Item>
</Col> </Col>
@ -818,10 +817,14 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
return ( return (
<> <>
<div className="form-section-title">贿</div> <div className="form-section-title">贿</div>
<Row gutter={24}> <Descriptions
<Col span={12}> column={1}
<div className="upload-label"> bordered
size="middle"
labelStyle={{ width: 240 }}
style={{ background: '#fff' }}
>
<Descriptions.Item label="请下载模版,按模版填写">
<Button <Button
type="link" type="link"
href="/templates/anti-bribery-template.docx" href="/templates/anti-bribery-template.docx"
@ -829,8 +832,9 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
> >
</Button> </Button>
</div>
</Descriptions.Item>
<Descriptions.Item label="请加盖公司公章后上传">
<Form.List name="coscoSupplierSurveyAttachments"> <Form.List name="coscoSupplierSurveyAttachments">
{(fields, { add, remove }) => { {(fields, { add, remove }) => {
// 确保至少有一项用于反商业贿赂承诺书 // 确保至少有一项用于反商业贿赂承诺书
@ -863,6 +867,7 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
<Form.Item <Form.Item
name={[field.name, 'fileUrl']} name={[field.name, 'fileUrl']}
rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]} rules={[{ required: true, message: '请上传已盖章的反商业贿赂承诺书' }]}
style={{marginBottom: 0}}
getValueFromEvent={(value) => { getValueFromEvent={(value) => {
if (value && value.length > 0) { if (value && value.length > 0) {
const file = value[0]; const file = value[0];
@ -891,7 +896,6 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
maxCount={1} maxCount={1}
allowedTypes={['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png']} allowedTypes={['pdf', 'doc', 'docx', 'jpg', 'jpeg', 'png']}
maxSize={10} maxSize={10}
tip="pdf,doc,docx,jpg,jpeg,png类型的文件,大小不超过10MB"
/> />
</Form.Item> </Form.Item>
</div> </div>
@ -900,16 +904,23 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
); );
}} }}
</Form.List> </Form.List>
</Col>
</Row> </Descriptions.Item>
</Descriptions>
<div className="form-section-title"></div> <div className="form-section-title"></div>
<Row gutter={24}> <Descriptions
<Col span={24}> column={1}
bordered
size="middle"
labelStyle={{ width: 240 }}
style={{ background: '#fff' }}
>
<Descriptions.Item label="其他附件(非必须上传)">
<Form.List name="coscoSupplierSurveyAttachments"> <Form.List name="coscoSupplierSurveyAttachments">
{(fields, { add, remove }) => ( {(fields, { add, remove }) => (
<> <>
<div className="upload-label"></div>
{fields.map((field, index) => ( {fields.map((field, index) => (
<div <div
key={field.key} key={field.key}
@ -987,8 +998,8 @@ export const AttachmentSection: React.FC<CommonFormSectionsProps> = ({ form }) =
</> </>
)} )}
</Form.List> </Form.List>
</Col> </Descriptions.Item>
</Row> </Descriptions>
</> </>
); );
}; };

View File

@ -337,7 +337,7 @@ const ForeignForm: React.FC<ForeignFormProps> = ({
{/* 使用通用表单组件 */} {/* 使用通用表单组件 */}
<QualificationSection form={form} /> <QualificationSection form={form} />
<InvoiceSection form={form} /> {/* <InvoiceSection form={form} /> */}
<BankAccountSection form={form} supplierType={'ovs'} /> <BankAccountSection form={form} supplierType={'ovs'} />
<SurveySection form={form} surveyQuestions={surveyQuestions} /> <SurveySection form={form} surveyQuestions={surveyQuestions} />
<AttachmentSection form={form} /> <AttachmentSection form={form} />

View File

@ -20,6 +20,8 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
const [supplierModalVisible, setSupplierModalVisible] = useState(false); const [supplierModalVisible, setSupplierModalVisible] = useState(false);
//品类选择渲染数据 //品类选择渲染数据
const [categoriesTreeData, setCategoriesTreeData] = useState([]); const [categoriesTreeData, setCategoriesTreeData] = useState([]);
//提交防抖
const [submitting, setSubmitting] = useState(false);
//品类选择数据中字段转换 //品类选择数据中字段转换
const convertTreeData = (data: any) => { const convertTreeData = (data: any) => {
return data.map((item: any) => ({ return data.map((item: any) => ({
@ -58,7 +60,7 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
const leafKeys = findLeafKeys(convertTreeData(categoriesTreeData)); const leafKeys = findLeafKeys(convertTreeData(categoriesTreeData));
const onlyLeafChecked = keys.filter(key => leafKeys.includes(String(key))); const onlyLeafChecked = keys.filter(key => leafKeys.includes(String(key)));
console.log(onlyLeafChecked,'onlyLeafChecked', leafKeys ,keys); console.log(onlyLeafChecked, 'onlyLeafChecked', leafKeys, keys);
setCheckedKeys(keys); // UI 显示用,还是全量 setCheckedKeys(keys); // UI 显示用,还是全量
@ -91,20 +93,20 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
const categoryNames = findNamesByIds(categoriesTreeData, onlyLeafChecked); const categoryNames = findNamesByIds(categoriesTreeData, onlyLeafChecked);
let autoTitle = supplierName; let autoTitle = supplierName;
if (supplierName && categoryNames.length) { if (supplierName && categoryNames.length) {
if (categoryNames.length === 1) { if (categoryNames.length === 1) {
autoTitle = `${supplierName}-${categoryNames[0]}-品类准入工作`; autoTitle = `${supplierName}-${categoryNames[0]}-品类准入工作`;
} else { } else {
autoTitle = `${supplierName}-${categoryNames[0]}等-品类准入工作`; autoTitle = `${supplierName}-${categoryNames[0]}等-品类准入工作`;
} }
} else if (!supplierName && categoryNames.length) { } else if (!supplierName && categoryNames.length) {
if (categoryNames.length === 1) { if (categoryNames.length === 1) {
autoTitle = categoryNames[0]; autoTitle = categoryNames[0];
} else { } else {
autoTitle = `${categoryNames[0]}等-品类准入工作`; autoTitle = `${categoryNames[0]}等-品类准入工作`;
} }
} }
form.setFieldsValue({ accessWorkName: autoTitle }); form.setFieldsValue({ accessWorkName: autoTitle });
} }
}; };
@ -132,12 +134,16 @@ form.setFieldsValue({ accessWorkName: autoTitle });
//品类选择 //品类选择
finalPayload.categoryIds = values.categoryIds; finalPayload.categoryIds = values.categoryIds;
//选择供应商 //选择供应商
if(values.supplier.length != 0) { if (values.supplier.length != 0) {
values.supplier.forEach((item: { id: string }) => { values.supplier.forEach((item: { id: string }) => {
finalPayload.supplierIds.push(item.id) finalPayload.supplierIds.push(item.id)
}) })
} }
console.log( finalPayload, values); console.log(finalPayload, values);
if (submitting) return; // 防重复提交
setSubmitting(true);
try {
const res = await add(finalPayload); const res = await add(finalPayload);
if (res?.success) { if (res?.success) {
message.success('创建成功'); message.success('创建成功');
@ -147,10 +153,14 @@ form.setFieldsValue({ accessWorkName: autoTitle });
} else { } else {
message.error('创建失败'); message.error('创建失败');
} }
}
finally {
setSubmitting(false); // 无论成功失败都解锁
}
}; };
//初始化 //初始化
useEffect(() => { useEffect(() => {
if(visible) { if (visible) {
categoryTree().then((res) => { categoryTree().then((res) => {
const { code, data } = res; const { code, data } = res;
if (code == 200) { if (code == 200) {
@ -190,14 +200,14 @@ form.setFieldsValue({ accessWorkName: autoTitle });
} else { } else {
setAccessWorkNameEdited(false); setAccessWorkNameEdited(false);
} }
}}/> }} />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
label="准入部门" label="准入部门"
name="deptId" name="deptId"
rules={[{ required: true, message: '请选择准入部门' }]} rules={[{ required: true, message: '请选择准入部门' }]}
> >
<AccessDepartmentSelect style={{width: '100%'}} orgCategory='' /> <AccessDepartmentSelect style={{ width: '100%' }} orgCategory='' />
</Form.Item> </Form.Item>
@ -209,7 +219,7 @@ form.setFieldsValue({ accessWorkName: autoTitle });
<Button onClick={() => setSupplierModalVisible(true)}> <Button onClick={() => setSupplierModalVisible(true)}>
</Button> </Button>
<span style={{marginLeft: 10}}>{`${form.getFieldValue('supplier')? form.getFieldValue('supplier')[0].supplierType === 'ovs' ? form.getFieldValue('supplier')[0].nameEn : form.getFieldValue('supplier')[0].name : ''}`}</span> <span style={{ marginLeft: 10 }}>{`${form.getFieldValue('supplier') ? form.getFieldValue('supplier')[0].supplierType === 'ovs' ? form.getFieldValue('supplier')[0].nameEn : form.getFieldValue('supplier')[0].name : ''}`}</span>
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@ -235,7 +245,7 @@ form.setFieldsValue({ accessWorkName: autoTitle });
</Form.Item> </Form.Item>
<Form.Item wrapperCol={{ offset: 6 }}> <Form.Item wrapperCol={{ offset: 6 }}>
<Button type="primary" htmlType="submit" style={{ marginRight: 8 }}> <Button type="primary" htmlType="submit" style={{ marginRight: 8 }} disabled={submitting}>
</Button> </Button>
<Button <Button

View File

@ -46,6 +46,8 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
const [supplierModalVisible, setSupplierModalVisible] = useState(false); const [supplierModalVisible, setSupplierModalVisible] = useState(false);
const [reviewerModalVisible, setReviewerModalVisible] = useState(false); const [reviewerModalVisible, setReviewerModalVisible] = useState(false);
const [divisionModalVisible, setDivisionModalVisible] = useState(false); const [divisionModalVisible, setDivisionModalVisible] = useState(false);
//提交防抖
const [submitting, setSubmitting] = useState(false);
//品类选择渲染数据 //品类选择渲染数据
const [categoriesTreeData, setCategoriesTreeData] = useState([]); const [categoriesTreeData, setCategoriesTreeData] = useState([]);
//品类选择数据中字段转换 //品类选择数据中字段转换
@ -132,8 +134,16 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
message.error('上传失败'); message.error('上传失败');
} }
}; };
//获取 cuCompanyNumber
const onChangeDepartmentSelect = (value: any, label: any, extra: any) => {
form.setFieldsValue({ orgId: extra?.triggerNode?.props.cuCompanyNumber });
}
// 提交 // 提交
const onFinish = async (values: any) => { const onFinish = async (values: any) => {
if (submitting) return; // 防重复提交
setSubmitting(true);
try {
const finalPayload: { const finalPayload: {
coscoAccessWork: { coscoAccessWork: {
startTime: string; startTime: string;
@ -141,6 +151,7 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
accessType: string; accessType: string;
accessWorkName: string; accessWorkName: string;
deptId: string; deptId: string;
orgId: string;
accessDesc: string; accessDesc: string;
}; };
categoryIds: string[]; categoryIds: string[];
@ -156,6 +167,7 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
accessType: '', accessType: '',
accessWorkName: '', accessWorkName: '',
deptId: '', deptId: '',
orgId: '',
accessDesc: '', accessDesc: '',
}, },
categoryIds: [], categoryIds: [],
@ -172,6 +184,8 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
finalPayload.coscoAccessWork.accessType = values.accessType; finalPayload.coscoAccessWork.accessType = values.accessType;
//准入部门 //准入部门
finalPayload.coscoAccessWork.deptId = values.deptId; finalPayload.coscoAccessWork.deptId = values.deptId;
//准入单位
finalPayload.coscoAccessWork.orgId = values.orgId;
// 准入说明 // 准入说明
finalPayload.coscoAccessWork.accessDesc = values.accessDesc; finalPayload.coscoAccessWork.accessDesc = values.accessDesc;
//品类选择 //品类选择
@ -207,7 +221,6 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
finalPayload.coscoAccessWorkAttachments = values.supplierCompliance[0].response; finalPayload.coscoAccessWorkAttachments = values.supplierCompliance[0].response;
finalPayload.coscoAccessWorkAttachments.fileUrl = values.supplierCompliance[0].response.url; finalPayload.coscoAccessWorkAttachments.fileUrl = values.supplierCompliance[0].response.url;
} }
const res = await add(finalPayload); const res = await add(finalPayload);
if (res?.success) { if (res?.success) {
message.success('创建成功'); message.success('创建成功');
@ -219,6 +232,9 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
} else { } else {
message.error('创建失败'); message.error('创建失败');
} }
} finally {
setSubmitting(false); // 无论成功失败都解锁
}
}; };
//初始化 //初始化
useEffect(() => { useEffect(() => {
@ -273,7 +289,10 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
name="deptId" name="deptId"
rules={[{ required: true, message: '请选择准入部门' }]} rules={[{ required: true, message: '请选择准入部门' }]}
> >
<AccessDepartmentSelect style={{width: '100%'}} orgCategory='' /> <AccessDepartmentSelect style={{width: '100%'}} orgCategory='' onChange={onChangeDepartmentSelect} />
</Form.Item>
<Form.Item name="orgId" noStyle>
<Input type="hidden" />
</Form.Item> </Form.Item>
<Form.Item <Form.Item
@ -474,7 +493,7 @@ const CreateModal: React.FC<{ visible: boolean; onCancel: () => void; }> = ({ vi
)} )}
<Form.Item wrapperCol={{ offset: 6 }}> <Form.Item wrapperCol={{ offset: 6 }}>
<Button type="primary" htmlType="submit" style={{ marginRight: 8 }}> <Button type="primary" htmlType="submit" style={{ marginRight: 8 }} disabled={submitting}>
{admissionMethod === 'online' ? '确认' : admissionMethod === 'offline' ? '提交审批' : '提交'} {admissionMethod === 'online' ? '确认' : admissionMethod === 'offline' ? '提交审批' : '提交'}
</Button> </Button>

View File

@ -51,7 +51,8 @@ const SupplierAddModal: React.FC<{
const [categoryInfo, setCategoryInfo] = useState<CategoryInfo>({}); const [categoryInfo, setCategoryInfo] = useState<CategoryInfo>({});
// loading // loading
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
//提交防抖
const [submitting, setSubmitting] = useState(false);
const supplierDetailModal = useSupplierDetailModal(); const supplierDetailModal = useSupplierDetailModal();
//供应商符合性审查 //供应商符合性审查
const [fileList, setFileList] = useState<UploadFile<any>[]>([]); const [fileList, setFileList] = useState<UploadFile<any>[]>([]);
@ -145,7 +146,9 @@ const SupplierAddModal: React.FC<{
attachmentsType: 'accessory' attachmentsType: 'accessory'
} }
} }
if (submitting) return; // 防重复提交
setSubmitting(true);
try {
apply({ categoryLibraryId: storeId, supplierIds: selectedIds, ...values }).then((res) => { apply({ categoryLibraryId: storeId, supplierIds: selectedIds, ...values }).then((res) => {
if(res.code == 200) { if(res.code == 200) {
message.success('操作成功'); message.success('操作成功');
@ -153,7 +156,9 @@ const SupplierAddModal: React.FC<{
onSuccess && onSuccess(); onSuccess && onSuccess();
} }
}) })
} finally {
setSubmitting(false); // 无论成功失败都解锁
}
}; };
// 自定义上传 // 自定义上传
@ -233,7 +238,7 @@ const SupplierAddModal: React.FC<{
visible={visible} visible={visible}
onCancel={onCancel} onCancel={onCancel}
footer={[ footer={[
<Button key="ok" type="primary" onClick={handleOk}></Button>, <Button key="ok" type="primary" onClick={handleOk} disabled={submitting}></Button>,
<Button key="cancel" onClick={onCancel}></Button>, <Button key="cancel" onClick={onCancel}></Button>,
]} ]}
width={820} width={820}

View File

@ -60,6 +60,8 @@ const CategoryAddModal: React.FC<Props> = ({ visible, onCancel, onSuccess }) =>
const [expandedKeys, setExpandedKeys] = useState<string[]>([]); const [expandedKeys, setExpandedKeys] = useState<string[]>([]);
//供应商符合性审查 //供应商符合性审查
const [fileList, setFileList] = useState<UploadFile<any>[]>([]); const [fileList, setFileList] = useState<UploadFile<any>[]>([]);
//提交防抖
const [submitting, setSubmitting] = useState(false);
const [deptOptions, setDeptOptions] = useState<DeptOption[]>([]); const [deptOptions, setDeptOptions] = useState<DeptOption[]>([]);
// 自定义上传 // 自定义上传
@ -142,6 +144,8 @@ const CategoryAddModal: React.FC<Props> = ({ visible, onCancel, onSuccess }) =>
// 提交校验 // 提交校验
const handleOk = async () => { const handleOk = async () => {
if (submitting) return; // 防重复提交
setSubmitting(true);
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
const submitData = { const submitData = {
@ -172,7 +176,9 @@ const CategoryAddModal: React.FC<Props> = ({ visible, onCancel, onSuccess }) =>
onSuccess && onSuccess(); onSuccess && onSuccess();
} }
}) })
} catch { } } finally {
setSubmitting(false); // 无论成功失败都解锁
}
}; };
return ( return (
<Modal <Modal
@ -339,7 +345,7 @@ const CategoryAddModal: React.FC<Props> = ({ visible, onCancel, onSuccess }) =>
<Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: 'center', marginTop: 30 }}> <Form.Item wrapperCol={{ span: 24 }} style={{ textAlign: 'center', marginTop: 30 }}>
<Button type="primary" style={{ width: 160 }} onClick={handleOk}> <Button type="primary" style={{ width: 160 }} onClick={handleOk} disabled={submitting}>
</Button> </Button>
<Button style={{ width: 120, marginLeft: 32 }} onClick={onCancel}> <Button style={{ width: 120, marginLeft: 32 }} onClick={onCancel}>

View File

@ -197,6 +197,7 @@ const SupplierRegisterAgent: React.FC = () => {
visible={exitModalVisible} visible={exitModalVisible}
exitId={exitId} exitId={exitId}
onOk={() => { onOk={() => {
fetchData(1, pagination.pageSize);
setExitModalVisible(false) setExitModalVisible(false)
}} }}
/> />

View File

@ -38,7 +38,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
const [suppliers, setSuppliers] = useState<Supplier[]>([]); const [suppliers, setSuppliers] = useState<Supplier[]>([]);
const [timelimitOption, setTimelimitOption] = useState<any[]>([]); const [timelimitOption, setTimelimitOption] = useState<any[]>([]);
const supplierDetailModal = useSupplierDetailModal(); const supplierDetailModal = useSupplierDetailModal();
//提交防抖
const [submitting, setSubmitting] = useState(false);
const removeSupplier = (id: string) => { const removeSupplier = (id: string) => {
setSuppliers(suppliers.filter((s) => s.id !== id)); setSuppliers(suppliers.filter((s) => s.id !== id));
}; };
@ -49,6 +50,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
if (submitting) return; // 防重复提交
setSubmitting(true);
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
if (suppliers.length === 0) { if (suppliers.length === 0) {
@ -75,6 +78,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
} }
} catch (err) { } catch (err) {
// 校验失败 // 校验失败
} finally {
setSubmitting(false); // 无论成功失败都解锁
} }
}; };
useEffect(() => { useEffect(() => {
@ -114,7 +119,7 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
return ( return (
<> <>
<Modal <Modal
title="供应商退出" title="供应商黑名单"
visible={visible} visible={visible}
onCancel={onCancel} onCancel={onCancel}
width={900} width={900}
@ -144,18 +149,6 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
layout="horizontal" layout="horizontal"
> >
{/* <Form.Item
label="黑名单类型"
name="backlistType"
rules={[{ required: true, message: '请选择黑名单类型' }]}
>
<Select placeholder="请选择黑名单类型">
{DEPT_OPTIONS.map((opt) => (
<Option key={opt.value} value={opt.value}>{opt.label}</Option>
))}
</Select>
</Form.Item> */}
<Form.Item <Form.Item
label="时限类型" label="时限类型"
name="timelimitType" name="timelimitType"
@ -181,7 +174,7 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
</div> </div>
<div style={{ marginTop: 28, textAlign: "center" }}> <div style={{ marginTop: 28, textAlign: "center" }}>
<Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit}></Button> <Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit} disabled={submitting}></Button>
<Button onClick={onCancel}></Button> <Button onClick={onCancel}></Button>
</div> </div>
</Modal> </Modal>

View File

@ -35,7 +35,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
const [selectVisible, setSelectVisible] = useState(false); const [selectVisible, setSelectVisible] = useState(false);
const [suppliers, setSuppliers] = useState<Supplier[]>([]); const [suppliers, setSuppliers] = useState<Supplier[]>([]);
const [form] = Form.useForm(); const [form] = Form.useForm();
//提交防抖
const [submitting, setSubmitting] = useState(false);
const removeSupplier = (id: number) => { const removeSupplier = (id: number) => {
setSuppliers(suppliers.filter((s) => s.id !== id)); setSuppliers(suppliers.filter((s) => s.id !== id));
}; };
@ -46,6 +47,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
}; };
const handleSubmit = async () => { const handleSubmit = async () => {
if (submitting) return; // 防重复提交
setSubmitting(true);
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
if (suppliers.length === 0) { if (suppliers.length === 0) {
@ -76,6 +79,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
} }
} catch (err) { } catch (err) {
// 校验失败 // 校验失败
} finally {
setSubmitting(false); // 无论成功失败都解锁
} }
}; };
useEffect(() => { useEffect(() => {
@ -162,7 +167,7 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
</div> </div>
<div style={{ marginTop: 28, textAlign: "center" }}> <div style={{ marginTop: 28, textAlign: "center" }}>
<Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit}></Button> <Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit} disabled={submitting}></Button>
<Button onClick={onCancel}></Button> <Button onClick={onCancel}></Button>
</div> </div>
</Modal> </Modal>

View File

@ -39,7 +39,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
const [userDeptId, setUserDeptId] = useState(''); const [userDeptId, setUserDeptId] = useState('');
const currentUserStr = sessionStorage.getItem('currentUser'); const currentUserStr = sessionStorage.getItem('currentUser');
const currentUser = currentUserStr ? JSON.parse(currentUserStr) : null; const currentUser = currentUserStr ? JSON.parse(currentUserStr) : null;
//提交防抖
const [submitting, setSubmitting] = useState(false);
//移除已选供应商 //移除已选供应商
const removeSupplier = (id: number) => { const removeSupplier = (id: number) => {
setSuppliers(suppliers.filter((s) => s.id !== id)); setSuppliers(suppliers.filter((s) => s.id !== id));
@ -51,6 +52,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
}; };
//提交 //提交
const handleSubmit = async () => { const handleSubmit = async () => {
if (submitting) return; // 防重复提交
setSubmitting(true);
try { try {
const values = await form.validateFields(); const values = await form.validateFields();
if (suppliers.length === 0) { if (suppliers.length === 0) {
@ -80,6 +83,8 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
message.error("提交失败"); message.error("提交失败");
} }
} catch (err) { } catch (err) {
} finally {
setSubmitting(false); // 无论成功失败都解锁
} }
}; };
useEffect(() => { useEffect(() => {
@ -165,7 +170,7 @@ const CreateBlacklistModal: React.FC<CreateBlacklistModalProps> = ({
</div> </div>
<div style={{ marginTop: 28, textAlign: "center" }}> <div style={{ marginTop: 28, textAlign: "center" }}>
<Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit}></Button> <Button type="primary" style={{ marginRight: 24 }} onClick={handleSubmit} disabled={submitting}></Button>
<Button onClick={onCancel}></Button> <Button onClick={onCancel}></Button>
</div> </div>
</Modal> </Modal>