ConfirmReceiptModal.tsx 6.16 KB
import { RESPONSE_CODE } from '@/constants/enum';
import { postServiceOrderConfirmReceipt } from '@/services';
import { PlusOutlined } from '@ant-design/icons';
import { Button, Modal, Upload, message } from 'antd';
import { RcFile, UploadFile, UploadProps } from 'antd/es/upload';
import { cloneDeep } from 'lodash';
import { useEffect, useRef, useState } from 'react';
import { COMFIR_RECEIPT_IMAGES_NUMBER } from '../../constant';
export default ({ data, onClose }) => {
  const subIds = data?.map((item) => {
    return item.id;
  });
  // const [form] = Form.useForm<{ name: string; company: string }>();
  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 [uploading, setUploading] = useState(false);
  const handleCancel = () => setPreviewOpen(false);

  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(() => {
    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 handleUpload = async () => {
    const formData = new FormData();
    fileList.forEach((file) => {
      //originFileObj二进制文件
      formData.append('files', file.originFileObj as RcFile);
    });
    // console.log(fileList[0] as RcFile)
    // formData.append('file', fileList[0] as RcFile);
    formData.append('subIds', subIds);
    setUploading(true);
    // You can use any AJAX library you like
    const res = await postServiceOrderConfirmReceipt({
      data: formData,
      headers: {
        'Content-Type':
          'multipart/form-data; boundary=----WebKitFormBoundarynl6gT1BKdPWIejNq',
      },
    });

    if (res.result === RESPONSE_CODE.SUCCESS) {
      message.success(res.message);
      onClose();
    }

    setUploading(false);
  };

  const props: UploadProps = {
    onRemove: (file) => {
      const index = fileList.indexOf(file);
      const newFileList = fileList.slice();
      newFileList.splice(index, 1);
      setFileList(newFileList);
    },
    beforeUpload: (file) => {
      setFileList([...fileList, file]);
      return false;
    },
    listType: 'picture-card',
    onPreview: handlePreview,
    fileList,
    onChange: handleChange,
    accept: 'image/png, image/jpeg, image/png',
  };

  return (
    <>
      <Modal
        width={500}
        open
        title="确认收货"
        footer={[
          <Button key="cancel" onClick={onClose}>
            取消
          </Button>,
          <Button
            type="primary"
            key="ok"
            onClick={handleUpload}
            disabled={fileList.length === 0}
            loading={uploading}
          >
            {uploading ? '上传中' : '提交'}
          </Button>,
        ]}
        onCancel={async () => {
          onClose();
        }}
      >
        <div className="pt-4 font-semibold">请将买家确认收货的凭证照片上传</div>
        <div className="pb-4 text-xs decoration-gray-50">可复制照片粘贴</div>
        <Upload {...props}>
          {fileList.length < COMFIR_RECEIPT_IMAGES_NUMBER ? uploadButton : ''}
        </Upload>
      </Modal>
      <Modal
        open={previewOpen}
        title={previewTitle}
        footer={null}
        onCancel={handleCancel}
      >
        <img alt="图片预览" style={{ width: '100%' }} src={previewImage} />
      </Modal>
    </>
  );
};