import { RESPONSE_CODE } from '@/constants/enum'; import { postServiceOrderAfterSalesCheck, postServiceOrderCheckOrder, postServiceOrderFileProcess, postServiceOrderFinanceCheckOrder, } from '@/services'; import { ModalForm, ProFormTextArea } from '@ant-design/pro-components'; import { Button, Col, Form, Modal, Row, 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 { enumValueToLabel, getAliYunOSSFileNameFromUrl, 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 [previewImage, setPreviewImage] = useState(''); const [previewTitle, setPreviewTitle] = useState(''); 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>(); /** * 审核类型 */ 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].afterAnnexList; let annexLinks = annex?.map((f) => { return ( <Button className="p-0 pr-1" type="link" key="key" href={f}> {getAliYunOSSFileNameFromUrl(f)} </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(() => { getOrderAfterSalesInfo(); }, []); 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 postServiceOrderCheckOrder({ 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(); } } return ( <> <ModalForm<{ name: string; company: string; }> width={500} open title="审核" form={form} autoFocusFirstInput modalProps={{ okText: '通过', cancelText: '驳回', destroyOnClose: true, onCancel: () => { setCheckVisible(false); }, }} submitter={{ render: (props, defaultDoms) => { let myDoms = []; myDoms.push( <Button key="驳回" onClick={async () => { if (checkType(CHECK_TYPE.NORMAL)) { doCheck({ flag: false, ids: subOrderIds, externalProcurement: 0, checkNotes: form.getFieldValue('name'), }); return; } if (checkType(CHECK_TYPE.AFTER_SALES)) { doAfterSalesCheck({ 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); } }} > 驳回 </Button>, ); //如果是仓库审核,那么显示这个外部采购 if (checkType(CHECK_TYPE.NORMAL)) { myDoms.push( <Button key="外部采购" onClick={() => { doCheck({ flag: false, ids: subOrderIds, externalProcurement: 1, checkNotes: form.getFieldValue('name'), }); }} > 外部采购 </Button>, ); } //确认 myDoms.push(defaultDoms[1]); return myDoms; }, }} submitTimeout={2000} onFinish={async (values) => { if (checkType(CHECK_TYPE.NORMAL)) { //审核通过mainOrderId return doCheck({ flag: true, ids: subOrderIds, externalProcurement: 0, checkNotes: values.name, }); } if (checkType(CHECK_TYPE.AFTER_SALES)) { //审核通过 return doAfterSalesCheck({ isAfterSalesSuccess: true, subOrderIds: subOrderIds, mainId: mainOrderId, afterSalesRejectionNotes: values.name, }); } if (checkType(CHECK_TYPE.FINALCIAL)) { doFinancailCheck(values, true); } }} onOpenChange={setCheckVisible} > {checkType(CHECK_TYPE.AFTER_SALES) ? ( <> {afterSalesInfo} <Button className="px-0" type="link" onClick={() => { console.log(data); openOrderDrawer('after-sales-check', mainOrderId); }} > 查看旧订单 </Button> </> ) : ( '' )} <div>请特别注意订单总金额与订单金额。</div> <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> </> ) : ( '' )} </ModalForm> <Modal open={previewOpen} title={previewTitle} footer={null} onCancel={handleCancel} > <img alt="图片预览" style={{ width: '100%' }} src={previewImage} /> </Modal> {contextHolder} </> ); };