【React导出表格表单组件】

导出表格表单组件

import { storage } from '@/utils';
import { codeMessage } from '@/utils/request';
import { history } from '@umijs/max';
import { message, notification } from 'antd';
import React, { useState } from 'react';
import { extend } from 'umi-request';

interface IDownloadProps {
  params?: any;
  accept?: string;
  method?: string;
  data?: any;
  action: string;
  isToken?: boolean; // 是否带token
  beforeDownload?: () => any; // 下载前回调
  callback?: () => void; // 成功后回调
  children?: (loading: boolean) => React.ReactElement<any>; // 下载组件子组件
}
/**
 * @class 下载组件
 */
const Download: React.FC<IDownloadProps> = (props) => {
  const [loading, setLoading] = useState<boolean>(false);
  const {
    params = {},
    accept = '*/*',
    method = 'get',
    action,
    isToken = true,
    callback,
    children,
    data,
    beforeDownload,
  } = props;
  const errorHandler = (error: any) => {
    const { response = {} } = error;
    const errortext = codeMessage[response.status] || response.statusText;
    const { status, url } = response;
    let errorMessage;
    notification.destroy();
    if (status === 401 && url.indexOf('user/signout') === -1) {
      errorMessage = '未登录或登录已过期,请重新登录。';
      notification.error({
        message: errorMessage,
      });
      window?.g_app?._store?.dispatch({
        type: 'login/logout',
      });
    } else {
      errorMessage = `${errortext}`;
    }
    message.error(errorMessage);
    throw error;
  };
  // 浏览器保存本地
  const downFile = (blob: any, fileName: string) => {
    if (window?.navigator && window.navigator?.msSaveOrOpenBlob) {
      window?.navigator.msSaveBlob(blob, fileName);
    } else {
      const link = document.createElement('a');
      link.href = window.URL.createObjectURL(blob);
      link.download = fileName;
      link.click();
      window?.URL?.revokeObjectURL(link.href);
    }
  };
  /**
   * 下载
   */
  const downloadTmpl = async () => {
    const token = storage.get('token');
    if (!token) {
      message.error('未登录或登录已过期,请重新登录。');
      storage.clear();
      history.replace('/login');
      return;
    }

    const headers: any = {
      ...(isToken ? { 'x-Token': token } : null),
      Accept: accept,
    };
    const request = extend({
      errorHandler,
      credentials: 'include',
      timeout: 600000,
    });
    setLoading(true);
    return request(action, {
      method,
      headers,
      responseType: 'arrayBuffer',
      getResponse: true,
      params,
      data,
      ...(Object.keys(params).length ? { data: JSON.stringify(params) } : null),
    })
      .then((props: any) => {
        const { data, response } = props;
        if (data?.code === 1000) {
          const { code, msg } = data;
          const errorDesc = {
            message: `请求错误 ${code}`,
            description: msg,
          };
          notification.error(errorDesc);
          return;
        }
        const contentDisposition = response?.headers?.get(
          'content-disposition',
        );
        if (contentDisposition) {
          let [fileName]: any = contentDisposition?.split('=').slice(-1);
          fileName = fileName.replace(`utf-8''`, '');
          const blob = new Blob([data]);
          downFile(blob, decodeURI(fileName));
        } else {
          return notification.error({ message: '请求错误' });
        }
      })
      .then(() => callback && callback())
      .finally(() => {
        setLoading(false);
      });
  };

  const start = () => {
    beforeDownload
      ? beforeDownload()
          .then(() => downloadTmpl())
          .catch((e: any) => message.error(e.message))
      : downloadTmpl();
  };
  return (
    <div onClick={start} style={{ display: 'inline-block' }}>
      {children && children(loading)}
    </div>
  );
};

export default Download;

使用方法

 <Download
        isToken={true}
        action={}//接口地址
        params={}//get方式的参数,post使用data
      >
        {(option: any) => (
          <Button
            className={styles.exportBtn}
            icon={<DownloadOutlined />}
            {...option}
          >
            {useLocale('导出')}
          </Button>
        )}
      </Download>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值