美文网首页
学习 antd message 函数用法,包括 读取本地上传得文

学习 antd message 函数用法,包括 读取本地上传得文

作者: 随意_web | 来源:发表于2022-09-29 19:07 被阅读0次

    目标:类似 message.success() (调用函数)得方式,调起一个弹窗。弹窗功能:拿到上传excel文件得File,用于外部封装为FormData,传给后端。
    重点是createRoot和unmount两个api。

    /**
     * 下载文件
     * @param {any} data
     * @param {string} type 文件类型
     * @param {string} filename 文件名
     */
    export function downloadFile(
      data: any,
      filename: string = '文件.xlsx',
      type: string = 'text/plain;charset=utf-8'
    ) {
      let blob = new Blob([data], { type: type });
      let URL = window.URL || window.webkitURL;
      let src = URL.createObjectURL(blob);
      // 下载文件
      if ('download' in document.createElement('a')) {
        // 非IE下载
        if (src) {
          let link = document.createElement('a');
          link.style.display = 'none';
          link.href = src;
          link.setAttribute('download', filename);
          document.body.appendChild(link);
          link.click();
          link.remove();
          URL.revokeObjectURL(src);
        }
      } else {
        (navigator as any).msSaveBlob(blob, filename);
      }
    }
    // 生成dom
    function getContainer() {
      let _container: any = document.querySelector('#_container');
      if (!_container) {
        _container = document.createElement('div');
        _container.style.opacity = '0';
        _container.id = '_container';
        document.body.appendChild(_container);
      }
      return _container;
    }
    // 删除dom
    function removeContainer(ele: HTMLElement) {
      ele.remove();
    }
    // function
    interface IUploadFileObjProps extends ModalProps {
      /**
       * 处理弹窗确定按钮额外得操作
       *@param {RcFile[]} data 选中得文件或文件列表
       */
      onSubmit?: (data: RcFile[]) => Promise<boolean>;
      /** 透传antd modal属性 */
      antdModalProps?: ModalProps;
      /** 透传antd upload属性 */
      antdUploadProps?: UploadProps;
      /** 覆盖upload.dragger内容区得样式 */
      content?: ReactNode;
    }
    // tsx
    interface IUploadModalProps extends IUploadFileObjProps {
      /** 关闭弹窗时额外需要操作得内容 */
      hanldeClose?: () => void;
    }
    // tsx
    export const UploadModal = memo((props: IUploadModalProps) => {
      const { hanldeClose, onSubmit, antdModalProps, antdUploadProps, content } =
        props;
      const [state, { toggle }] = useToggle(true);
      const onOK = useMemoizedFn(() => {
        if (fileList.length) {
          onSubmit?.(fileList as RcFile[]).then((res: boolean) => {
            if (res) {
              toggle();
              hanldeClose?.();
            }
          });
        }
      });
      const [fileList, setFileList] = useState<UploadFile[]>([]);
      const beforeUpload = useMemoizedFn(
        (file: UploadFile, fileList: UploadFile[]) => {
          setFileList(fileList);
          return Promise.reject();
        }
      );
      const onRemove = useMemoizedFn((file: UploadFile) => {
        setFileList(fileList.filter((i) => i.uid !== file.uid));
      });
      const onPreview = useMemoizedFn((file: UploadFile) => {
        downloadFile(file, file.name);
      });
      const modalProps = useMemo(
        () => ({
          visible: state,
          onCancel() {
            toggle();
            hanldeClose?.();
          },
          onOk: onOK,
          ...antdModalProps,
        }),
        [antdModalProps, hanldeClose, onOK, state, toggle]
      );
      const uploadProps = useMemo(
        () => ({
          accept: '.xls,.xlsx',
          maxCount: 1,
          beforeUpload,
          fileList,
          showUploadList: false,
          ...antdUploadProps,
        }),
        [antdUploadProps, beforeUpload, fileList]
      );
      return (
        <Modal {...modalProps}>
          <Upload.Dragger {...uploadProps}>
            {content ?? (
              <div className="py-5">
                <p className="pb-3">
                  <img src={BatchImportImage} className="w-9 h-9" />
                </p>
                <p className="text-gray-400 pb-6">支持xls、xlsx文件</p>
                <div
                  className="inline-block px-5 py-3 text-xs text-white"
                  style={{
                    background: '#193C58',
                    borderRadius: '4px',
                    border: '1px solid rgba(25,60,88,0.24)',
                  }}
                >
                  <PlusOutlined
                    style={{
                      fontSize: '14px',
                      marginRight: '3px',
                      color: '#ffffff',
                    }}
                  />
                  添加附件
                </div>
              </div>
            )}
          </Upload.Dragger>
          {fileList.length ? (
            <div
              className="py-3 pl-3 pr-6 text-xs mt-3"
              style={{ background: '#F2F2F6' }}
            >
              {fileList.map((file, i) => (
                <div className="flex items-center justify-between" key={i}>
                  <div
                    className="flex items-center font-bold"
                    style={{ color: '#111F2C' }}
                  >
                    <FileTextOutlined className="mr-2" />
                    {file.name}
                  </div>
                  <div>
                    <a
                      className="mr-4"
                      style={{ color: '#0096FF' }}
                      onClick={() => onRemove(file)}
                    >
                      删除
                    </a>
                    <a
                      className="mr-4"
                      style={{ color: '#0096FF' }}
                      onClick={() => onPreview(file)}
                    >
                      预览
                    </a>
                  </div>
                </div>
              ))}
            </div>
          ) : null}
        </Modal>
      );
    });
    export function uploadFileObj(props: IUploadFileObjProps) {
      const container = getContainer();
      const _dom = createRoot(container);
      const hanldeClose = () => {
        _dom.unmount();
        removeContainer(container);
      };
      const _props = {
        ...props,
        hanldeClose,
      };
    // 这里就可以渲染任意得Node,我在这里就包了一个二次封装得modal
      _dom.render(<UploadModal {..._props} />);
    }
    

    使用

    uploadFileObj({
          onSubmit(file) {
            const formData = new FormData();
            formData.append('file', file[0]);
            return new Promise((resolve) => {
              boxImportBoxExcel(formData).then(({ success }) => {
                resolve(success);
                if (success) {
                  message.success('导入成功');
                } else {
                  message.error('导入失败');
                }
              });
            });
          },
          antdModalProps: {
            title: (
              <div className="w-5/6 flex justify-between items-center">
                <span>批量导入</span>
                <a
                  className="text-xs underline"
                  style={{ color: '#0096FF' }}
                  // TODO
                  href=""
                >
                  下载模板
                </a>
              </div>
            ),
          },
        });
    

    相关文章

      网友评论

          本文标题:学习 antd message 函数用法,包括 读取本地上传得文

          本文链接:https://www.haomeiwen.com/subject/gbpkartx.html