import { RESPONSE_CODE } from '@/constants/enum'; import { postPrepaidAudit, postServiceOrderAfterSalesCheck, postServiceOrderAudit, postServiceOrderFileProcess, postServiceOrderFinanceCheckOrder, postServiceOrderLeaderAudit, postServiceOrderToProcureAudit, } from '@/services'; import { ModalForm, ProFormTextArea, ProList, } from '@ant-design/pro-components'; import { Button, Col, Divider, Form, Image, Modal, Row, Space, Tag, UploadFile, message, } from 'antd'; import Upload, { RcFile, UploadProps } from 'antd/es/upload'; import { useEffect, useRef, useState } from 'react'; import { AFTE_SALES_PLAN_OPTIONS, CHECK_TYPE, COMFIR_RECEIPT_IMAGES_NUMBER, } from '../../constant'; // import { cloneDeep } from 'lodash'; import InvoiceSubOrderInfoTable from '@/pages/Order/Order/components/InvoiceSubOrderInfoTable'; import { enumValueToLabel, transImageFile } from '@/utils'; import { PlusOutlined } from '@ant-design/icons'; import { cloneDeep } from 'lodash'; export default ({ setCheckVisible, data, subOrders, orderCheckType, openOrderDrawer, onClose, }) => { const [previewOpen, setPreviewOpen] = useState(false); const [aPopoverTitle, setAPopoverTitle] = useState('审核'); const [previewImage, setPreviewImage] = useState(''); const [previewTitle, setPreviewTitle] = useState(''); const [paymentReceiptsImages, setPymentReceiptsImages] = useState<any[]>([]); const fileListObj = useRef<UploadFile[]>([]); //使用引用类型,使得在useEffect里面设置监听事件后,不用更新监听事件也能保持obj与外界一致 const getBase64 = (file: RcFile): Promise<string> => new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => resolve(reader.result as string); reader.onerror = (error) => reject(error); }); const [fileList, setFileList] = useState<UploadFile[]>([]); const handleCancel = () => setPreviewOpen(false); const [messageApi, contextHolder] = message.useMessage(); const [form] = Form.useForm<{ name: string; company: string }>(); let subOrderIds: any[] = subOrders?.map((subOrder) => subOrder.id); const [mainOrderId] = useState(data.id); const [afterSalesInfo, setAfterSalesInfo] = useState<any>(); const [prepaidProofImages, setPrepaidProofImages] = useState<any[]>([]); /** * 审核类型 */ function checkType(check: string) { if (orderCheckType === check) { return true; } return false; } const getOrderAfterSalesInfo = async () => { // let res = await postServiceOrderQueryAfterSalesInfoSnapshot({ // data: { subOrderIds: subOrderIds }, // }); //附件 let annex = subOrders[0].afterSalesAnnexList; let index = 1; let annexLinks = annex?.map((f) => { return ( <Button className="p-0 pr-1" type="link" key="key" href={f}> {'附件' + index++} </Button> ); }); console.log(annexLinks); setAfterSalesInfo( <div className="my-5"> <Row gutter={[16, 24]}> <Col span={6}> <span className="text-[#333333]">售后方案</span> </Col> <Col span={18}> {enumValueToLabel( subOrders[0]?.afterSalesPlan, AFTE_SALES_PLAN_OPTIONS, )} </Col> <Col span={6}> <span className="className='text-[#333333]'">售后原因</span> </Col> <Col span={18}>{subOrders[0]?.afterSalesNotes}</Col> <Col span={6}> <span className="className='text-[#333333]'">附件</span> </Col> <Col span={18}>{annexLinks}</Col> </Row> </div>, ); }; useEffect(() => { if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) { setAPopoverTitle('确认发货'); } getOrderAfterSalesInfo(); let paymentReceiptsImagesList: any[] = []; subOrders?.forEach((item: any) => { if (item.paymentReceiptAnnexList) { paymentReceiptsImagesList.push(...item.paymentReceiptAnnexList); } }); //去重 paymentReceiptsImagesList = [...new Set(paymentReceiptsImagesList)]; setPymentReceiptsImages(paymentReceiptsImagesList); //预存审核的凭证 let proofImages: any[] = []; subOrders?.forEach((item) => { let images = item.proofImages; if (images !== null && images !== undefined) { proofImages.push(...images); } }); setPrepaidProofImages(proofImages); }, []); const handleChange: UploadProps['onChange'] = ({ fileList: newFileList }) => { //fileListObj得在change里变化,change的参数是已经处理过的file数组 //beforeUpload中的参数file是未处理过,还需要Base64拿到文件数据处理 fileListObj.current = newFileList; setFileList(newFileList); }; /** 粘贴快捷键的回调 */ const onPaste = async (e: any) => { /** 获取剪切板的数据clipboardData */ let clipboardData = e.clipboardData, i = 0, items, item, types; /** 为空判断 */ if (clipboardData) { items = clipboardData.items; if (!items) { message.info('您的剪贴板中没有照片'); return; } item = items[0]; types = clipboardData.types || []; /** 遍历剪切板的数据 */ for (; i < types.length; i++) { if (types[i] === 'Files') { item = items[i]; break; } } /** 判断文件是否为图片 */ if (item && item.kind === 'file' && item.type.match(/^image\//i)) { const imgItem = item.getAsFile(); const newFileList = cloneDeep(fileListObj.current); let filteredArray = newFileList.filter( (obj) => obj.status !== 'removed', ); //过滤掉状态为已删除的照片 const listItem = { ...imgItem, status: 'done', url: await getBase64(imgItem), originFileObj: imgItem, }; if (filteredArray.length >= COMFIR_RECEIPT_IMAGES_NUMBER) { message.info('发货照片数量不能超过3'); return; } fileListObj.current = filteredArray; filteredArray.push(listItem); setFileList(filteredArray); return; } } message.info('您的剪贴板中没有照片'); }; useEffect(() => { //回显售后信息 // if (checkType(CHECK_TYPE.AFTER_SALES)) { // getOrderAfterSalesInfo(); // } document.addEventListener('paste', onPaste); return () => { document.removeEventListener('paste', onPaste); }; }, []); const uploadButton = ( <div> <PlusOutlined /> <div style={{ marginTop: 8 }}>上传凭证</div> </div> ); const handlePreview = async (file: UploadFile) => { if (!file.url && !file.preview) { file.preview = await getBase64(file.originFileObj as RcFile); } setPreviewImage(file.url || (file.preview as string)); setPreviewOpen(true); setPreviewTitle( file.name || file.originFileObj?.name || file.url!.substring(file.url!.lastIndexOf('/') + 1), ); }; const handleBeforeUpload = (file: any) => { setFileList([...fileList, file]); return false; }; const props: UploadProps = { onRemove: (file) => { const index = fileList.indexOf(file); const newFileList = fileList.slice(); newFileList.splice(index, 1); setFileList(newFileList); }, beforeUpload: handleBeforeUpload, listType: 'picture-card', onPreview: handlePreview, fileList, onChange: handleChange, accept: 'image/png, image/jpeg, image/png', // action: '/api/service/order/fileProcess', name: 'files', headers: { Authorization: localStorage.getItem('token') }, }; //仓库审核 async function doCheck(body: object) { const data = await postServiceOrderAudit({ data: body, }); if (data.result === RESPONSE_CODE.SUCCESS) { message.success(data.message); onClose(); } } /** * * @param body 财务审核 */ async function doFinancailCheck(values: any, isAgree: boolean) { if (fileList.length <= 0) { message.error('凭证不能为空'); return; } messageApi.open({ type: 'loading', content: '正在上传图片...', duration: 0, }); //附件处理 let formData = new FormData(); //附件处理 for (let file of fileList) { if (file.originFileObj) { formData.append('files', file.originFileObj as RcFile); } else { //有url的话取url(源文件),没url取thumbUrl。有url的时候thumbUrl是略缩图 if (file?.url === undefined || file?.url === null) { formData.append( 'files', transImageFile(file?.thumbUrl), file?.originFileObj?.name, ); } else { formData.append( 'files', transImageFile(file?.url), file?.originFileObj?.name, ); } } } let res = await postServiceOrderFileProcess({ data: formData, }); messageApi.destroy(); if (res.result === RESPONSE_CODE.SUCCESS) { message.success('上传成功!'); let fileUrls = res?.data?.map((item) => { return { url: item }; }); //财务审核 const data = await postServiceOrderFinanceCheckOrder({ data: { checkNotes: values.name, ids: subOrderIds, checkPassOrReject: isAgree, invoicingCheckAnnex: fileUrls, }, }); if (data.result === RESPONSE_CODE.SUCCESS) { message.success(data.message); onClose(); } } else { message.success('上传失败'); } } /** * * @param body 售后审核 */ async function doAfterSalesCheck(body: object) { const data = await postServiceOrderAfterSalesCheck({ data: body, }); if (data.result === RESPONSE_CODE.SUCCESS) { message.success(data.message); onClose(); } } /** * * @param body 领导审核 */ async function doLeaderCheck(body: object) { const data = await postServiceOrderLeaderAudit({ data: body, }); if (data.result === RESPONSE_CODE.SUCCESS) { message.success(data.message); onClose(); } } /** * 预存审核 * @param body */ async function doPrepaidAudit(body: any) { const data = await postPrepaidAudit({ data: body, }); if (data.result === RESPONSE_CODE.SUCCESS) { message.success(data.message); onClose(); } } function computeType() { let type: string = ''; if (checkType(CHECK_TYPE.CONFIRM_DELIVER)) { type = 'confirm_deliver'; } if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) { type = 'warehouse_audit'; } if (checkType(CHECK_TYPE.WAITING_FOR_POST_AUDIT)) { type = 'post_audit'; } if (checkType(CHECK_TYPE.NODE_OPERATING_AUDIT)) { type = 'node_operating_audit'; } if (checkType(CHECK_TYPE.MODIFY_LEADER_AUDIT)) { type = 'modify_leader_audit'; } if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING)) { type = 'urgent_invoice_audit'; } if (checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT)) { type = 'payment_receipt_audit'; } if (checkType(CHECK_TYPE.CONFIRM_REISSUE)) { type = 'confirm_reissue'; } if (checkType(CHECK_TYPE.CREDIT_AUDIT)) { type = 'credit_audit'; } if (checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING_OLD)) { type = 'urgent_invoice_audit_old'; } if (checkType(CHECK_TYPE.CONFIRM_REISSUE_OLD)) { type = 'confirm_reissue_old'; } return type; } return ( <> <ModalForm<{ name: string; company: string; }> width={500} open title={aPopoverTitle} form={form} autoFocusFirstInput modalProps={{ okText: '通过', cancelText: '驳回', destroyOnClose: true, onCancel: () => { setCheckVisible(false); }, }} submitter={{ render: (props, defaultDoms) => { let myDoms = []; if (!checkType(CHECK_TYPE.CONFIRM_DELIVER)) { myDoms.push( <Button key="驳回" onClick={async () => { if (checkType(CHECK_TYPE.AFTER_SALES)) { doAfterSalesCheck({ applyType: 'after-sales', isAfterSalesSuccess: false, subOrderIds: subOrderIds, mainId: mainOrderId, afterSalesRejectionNotes: form.getFieldValue('name'), }); return; } if (checkType(CHECK_TYPE.FINALCIAL)) { let values = { name: form.getFieldValue('name') }; doFinancailCheck(values, false); return; } if (checkType(CHECK_TYPE.LEADER_AUDIT)) { doLeaderCheck({ pass: false, subOrderIds: subOrderIds, reason: form.getFieldValue('name'), }); return; } if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) { doAfterSalesCheck({ applyType: 'order-change-normal', isAfterSalesSuccess: false, subOrderIds: subOrderIds, mainId: mainOrderId, afterSalesRejectionNotes: form.getFieldValue('name'), }); return; } //预存审核,先暂时共用同一个审核弹窗 if (checkType(CHECK_TYPE.PREPAID_AUDIT)) { return doPrepaidAudit({ pass: false, ids: subOrderIds, auditNotes: form.getFieldValue('name'), }); } let type = ''; type = computeType(); console.log('type:' + type); doCheck({ pass: false, subOrderIds: subOrderIds, type: type, notes: form.getFieldValue('name'), }); }} > 驳回 </Button>, ); } //如果是仓库审核,那么显示这个外部采购 if (checkType(CHECK_TYPE.WEARHOUSE_KEEPER)) { myDoms.push( <Button key="外部采购" onClick={async () => { let res = await postServiceOrderToProcureAudit({ data: { subOrderIds: subOrderIds, }, }); if (res && res.result === RESPONSE_CODE.SUCCESS) { message.success(res.message); onClose(); } }} > 外部采购 </Button>, ); } //确认 myDoms.push(defaultDoms[1]); return myDoms; }, }} submitTimeout={2000} onFinish={async (values) => { if (checkType(CHECK_TYPE.AFTER_SALES)) { //审核通过 return doAfterSalesCheck({ applyType: 'after-sales', isAfterSalesSuccess: true, subOrderIds: subOrderIds, mainId: mainOrderId, afterSalesRejectionNotes: values.name, }); } console.log('h'); if (checkType(CHECK_TYPE.FINALCIAL)) { doFinancailCheck(values, true); return; } if (checkType(CHECK_TYPE.LEADER_AUDIT)) { doLeaderCheck({ pass: true, subOrderIds: subOrderIds, reason: values.name, }); return; } if (checkType(CHECK_TYPE.MODIFY_APPLY_WAIT_FOR_AUDIT)) { //审核通过 return doAfterSalesCheck({ applyType: 'order-change-normal', isAfterSalesSuccess: true, subOrderIds: subOrderIds, mainId: mainOrderId, afterSalesRejectionNotes: values.name, }); } //预存审核,先暂时共用同一个审核弹窗 if (checkType(CHECK_TYPE.PREPAID_AUDIT)) { return doPrepaidAudit({ pass: true, ids: subOrderIds, auditNotes: form.getFieldValue('name'), }); } let type = ''; type = computeType(); doCheck({ pass: true, subOrderIds: subOrderIds, type: type, notes: form.getFieldValue('name'), }); }} onOpenChange={setCheckVisible} > {checkType(CHECK_TYPE.AFTER_SALES) ? ( <> {afterSalesInfo} <Button className="px-0" type="link" onClick={() => { console.log(data); openOrderDrawer('after-sales-check', mainOrderId); }} > 查看旧订单 </Button> </> ) : ( '' )} {checkType(CHECK_TYPE.PAYMENT_RECEIPTS_AUDIT) ? ( <> <Divider orientation="center"> <span className="text-sm">回款凭证</span> </Divider> <Image.PreviewGroup className="mr-10" preview={{ onChange: (current, prev) => console.log(`current index: ${current}, prev index: ${prev}`), }} > {paymentReceiptsImages.map((url) => ( <> <Image width={120} src={url} /> <Divider type="vertical" /> </> ))} </Image.PreviewGroup> <Divider></Divider> </> ) : ( '' )} {checkType(CHECK_TYPE.PREPAID_AUDIT) && ( <> <Divider orientation="center"> <span className="text-sm">凭证</span> </Divider> <Image.PreviewGroup className="mr-10" preview={{ onChange: (current, prev) => console.log(`current index: ${current}, prev index: ${prev}`), }} > {prepaidProofImages.map((url) => ( <> <Image width={120} src={url} /> <Divider type="vertical" /> </> ))} </Image.PreviewGroup> <Divider></Divider> </> )} {checkType('prepaidAudit') ? ( <div>请特别注意手机号码和充值金额。</div> ) : ( <div>请特别注意订单总金额与订单金额。</div> )} {!checkType(CHECK_TYPE.CONFIRM_DELIVER) ? ( <ProFormTextArea width="lg" name="name" placeholder="若驳回,请填写驳回理由" /> ) : ( <></> )} {checkType(CHECK_TYPE.FINALCIAL) ? ( <> <div className="pb-4 text-xs decoration-gray-50"> 可复制照片粘贴 </div> <Upload {...props}> {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER ? uploadButton : ''} </Upload> </> ) : ( '' )} {checkType(CHECK_TYPE.CONFIRM_REISSUE) && ( <> <InvoiceSubOrderInfoTable subOrderIds={subOrderIds} ></InvoiceSubOrderInfoTable> </> )} {checkType(CHECK_TYPE.URGENT_INVOICE_AUDITING) ? ( <> <ProList rowKey="id" headerTitle="发票信息" metas={{ title: { dataIndex: 'name', }, avatar: { dataIndex: 'image', editable: false, }, description: { dataIndex: 'desc', }, subTitle: { render: () => { return ( <Space size={0}> <Tag color="blue">Ant Design</Tag> <Tag color="#5BD8A6">TechUI</Tag> </Space> ); }, }, actions: { render: (text, row, index, action) => [ <a onClick={() => { action?.startEditable(row.id); }} key="link" > 编辑 </a>, ], }, }} ></ProList> </> ) : ( '' )} </ModalForm> <Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handleCancel} > <img alt="图片预览" style={{ width: '100%' }} src={previewImage} /> </Modal> {contextHolder} </> ); };