封装导出工具类
This commit is contained in:
@ -2,13 +2,11 @@ import React, { useState, useEffect } from 'react';
|
|||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Table,
|
Table,
|
||||||
Space,
|
|
||||||
Input,
|
Input,
|
||||||
Select,
|
Select,
|
||||||
Form,
|
Form,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Tag,
|
Tag,
|
||||||
DatePicker,
|
|
||||||
message
|
message
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import type { TablePaginationConfig } from 'antd';
|
import type { TablePaginationConfig } from 'antd';
|
||||||
@ -17,10 +15,10 @@ import {
|
|||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
ExportOutlined
|
ExportOutlined
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import CategorySelector from '@/components/CategorySelector/CategorySelector';
|
import { AnnualReviewYears, AnnualReviewResultText, AnnualReviewResultColor } from '@/dicts/dataStatistics';
|
||||||
import { AnnualReviewYears, AnnualReviewResultText, AnnualReviewResultColor, SupplierTypeText } from '@/dicts/dataStatistics';
|
import { getSupplierAnnualReviewStatistics } from '@/servers/api/dataStatistics';
|
||||||
import { getSupplierAnnualReviewStatistics, exportSupplierAnnualReviewStatistics } from '@/servers/api/dataStatistics';
|
|
||||||
import './supplierAnnualStatistics.less';
|
import './supplierAnnualStatistics.less';
|
||||||
|
import { downloadFile } from '@/utils/download';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
|
|
||||||
@ -190,21 +188,7 @@ const SupplierAnnualStatistics: React.FC = () => {
|
|||||||
// 导出功能
|
// 导出功能
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
const values = form.getFieldsValue();
|
const values = form.getFieldsValue();
|
||||||
exportSupplierAnnualReviewStatistics(values)
|
downloadFile('/dataStatistics/exportSupplierAnnualReviewStatistics', 'GET', values);
|
||||||
.then(response => {
|
|
||||||
// 创建a标签进行下载
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', `供应商年审情况统计_${new Date().getTime()}.xlsx`);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('导出失败:', error);
|
|
||||||
message.error('导出失败');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -23,6 +23,7 @@ import { getSupplierEvaluateStatistics, exportSupplierEvaluateStatistics } from
|
|||||||
import { getAllEvaluateRules } from '@/servers/api/supplierEvaluate';
|
import { getAllEvaluateRules } from '@/servers/api/supplierEvaluate';
|
||||||
import type { EvaluateRuleItem } from '@/servers/dao/supplierEvaluateTask';
|
import type { EvaluateRuleItem } from '@/servers/dao/supplierEvaluateTask';
|
||||||
import './supplierEvaluateStatistics.less';
|
import './supplierEvaluateStatistics.less';
|
||||||
|
import { downloadFile } from '@/utils/download';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
@ -209,21 +210,7 @@ const SupplierEvaluateStatistics: React.FC = () => {
|
|||||||
// 更新handleExport方法实现真实导出功能
|
// 更新handleExport方法实现真实导出功能
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
const values = form.getFieldsValue();
|
const values = form.getFieldsValue();
|
||||||
exportSupplierEvaluateStatistics(values)
|
downloadFile('/dataStatistics/exportSupplierEvaluateStatistics', 'GET', values);
|
||||||
.then(response => {
|
|
||||||
// 创建a标签进行下载
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', `供应商评价情况统计_${new Date().getTime()}.xlsx`);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('导出失败:', error);
|
|
||||||
message.error('导出失败');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -22,6 +22,7 @@ import { SupplierTypeText } from '@/dicts/dataStatistics';
|
|||||||
import { getSupplierExitStatistics, exportSupplierExitStatistics } from '@/servers/api/dataStatistics';
|
import { getSupplierExitStatistics, exportSupplierExitStatistics } from '@/servers/api/dataStatistics';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import './supplierExitStatistics.less';
|
import './supplierExitStatistics.less';
|
||||||
|
import { downloadFile } from '@/utils/download';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
@ -199,21 +200,7 @@ const SupplierExitStatistics: React.FC = () => {
|
|||||||
// 导出功能
|
// 导出功能
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
const values = form.getFieldsValue();
|
const values = form.getFieldsValue();
|
||||||
exportSupplierExitStatistics(values)
|
downloadFile('/dataStatistics/exportSupplierExitStatistics', 'GET', values);
|
||||||
.then(response => {
|
|
||||||
// 创建a标签进行下载
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', `供应商退出情况统计_${new Date().getTime()}.xlsx`);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('导出失败:', error);
|
|
||||||
message.error('导出失败');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -22,6 +22,7 @@ import { SupplierTypeText } from '@/dicts/dataStatistics';
|
|||||||
import { getSupplierQualificationExpire, exportSupplierQualificationExpire } from '@/servers/api/dataStatistics';
|
import { getSupplierQualificationExpire, exportSupplierQualificationExpire } from '@/servers/api/dataStatistics';
|
||||||
import moment from 'moment';
|
import moment from 'moment';
|
||||||
import './supplierQualificationWarningStatistics.less';
|
import './supplierQualificationWarningStatistics.less';
|
||||||
|
import { downloadFile } from '@/utils/download';
|
||||||
|
|
||||||
const { Option } = Select;
|
const { Option } = Select;
|
||||||
const { RangePicker } = DatePicker;
|
const { RangePicker } = DatePicker;
|
||||||
@ -230,21 +231,7 @@ const SupplierQualificationWarningStatistics: React.FC = () => {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
exportSupplierQualificationExpire(exportParams)
|
downloadFile('/dataStatistics/exportSupplierQualificationExpire', 'GET', exportParams);
|
||||||
.then(response => {
|
|
||||||
// 创建a标签进行下载
|
|
||||||
const url = window.URL.createObjectURL(new Blob([response]));
|
|
||||||
const link = document.createElement('a');
|
|
||||||
link.href = url;
|
|
||||||
link.setAttribute('download', `供应商资质预警统计_${new Date().getTime()}.xlsx`);
|
|
||||||
document.body.appendChild(link);
|
|
||||||
link.click();
|
|
||||||
document.body.removeChild(link);
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
console.error('导出失败:', error);
|
|
||||||
message.error('导出失败');
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,58 +1,57 @@
|
|||||||
/**
|
|
||||||
* 通用文件下载工具(基于 umi-request + file-saver)
|
|
||||||
*/
|
|
||||||
|
|
||||||
import { extend } from 'umi-request';
|
|
||||||
import { saveAs } from 'file-saver';
|
import { saveAs } from 'file-saver';
|
||||||
|
|
||||||
// 单独配置一个不拦截响应的 request 实例
|
|
||||||
const downloadRequest = extend({
|
|
||||||
timeout: 10000,
|
|
||||||
responseType: 'blob', // 关键
|
|
||||||
credentials: 'include', // 根据实际需要携带 cookie
|
|
||||||
prefix: REQUEST_BASE,
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 下载文件通用函数
|
* 更稳妥的文件下载方法(绕过 umi-request,避免被 JSON 解析)
|
||||||
* @param url 请求地址
|
|
||||||
* @param params 请求参数(可选)
|
|
||||||
* @param filename 下载后的文件名(可选)
|
|
||||||
* @param method 请求方法(默认 POST)
|
|
||||||
*/
|
*/
|
||||||
export async function downloadFile({
|
export async function downloadFile(
|
||||||
url,
|
url: string,
|
||||||
params,
|
method: 'GET' | 'POST' = 'POST',
|
||||||
filename,
|
params?: Record<string, any>
|
||||||
method = 'POST',
|
) {
|
||||||
}: {
|
|
||||||
url: string;
|
|
||||||
params?: Record<string, any>;
|
|
||||||
filename?: string;
|
|
||||||
method?: 'GET' | 'POST';
|
|
||||||
}) {
|
|
||||||
try {
|
try {
|
||||||
const blob: Blob = await downloadRequest(url, {
|
const cleanedParams: Record<string, any> = {};
|
||||||
method,
|
if (params) {
|
||||||
data: method === 'POST' ? params : undefined,
|
Object.entries(params).forEach(([key, value]) => {
|
||||||
params: method === 'GET' ? params : undefined,
|
if (value !== undefined && value !== null && value !== '') {
|
||||||
});
|
cleanedParams[key] = value;
|
||||||
|
}
|
||||||
// 尝试从响应头中获取文件名
|
});
|
||||||
const contentDisposition = (blob as any).response?.headers?.get?.('content-disposition');
|
|
||||||
let finalFilename = filename;
|
|
||||||
|
|
||||||
if (!finalFilename && contentDisposition) {
|
|
||||||
const match = contentDisposition.match(/filename="?([^"]+)"?/);
|
|
||||||
if (match && match[1]) {
|
|
||||||
finalFilename = decodeURIComponent(match[1]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
finalFilename = finalFilename || '下载文件';
|
const fetchUrl =
|
||||||
|
method === 'GET' && params
|
||||||
|
? `${REQUEST_BASE}${url}?${new URLSearchParams(cleanedParams as any).toString()}`
|
||||||
|
: `${REQUEST_BASE}${url}`;
|
||||||
|
|
||||||
saveAs(blob, finalFilename);
|
const response = await fetch(fetchUrl, {
|
||||||
} catch (error) {
|
method,
|
||||||
console.error('文件下载失败:', error);
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
},
|
||||||
|
body: method === 'POST' ? JSON.stringify(params) : undefined,
|
||||||
|
credentials: 'include',
|
||||||
|
});
|
||||||
|
|
||||||
|
const contentType = response.headers.get('content-type') || '';
|
||||||
|
if (contentType.includes('text/html')) {
|
||||||
|
const htmlText = await response.text();
|
||||||
|
console.error('服务器返回 HTML 页面,可能是未登录或接口错误:', htmlText.slice(0, 300));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const text = await response.text();
|
||||||
|
console.error(`请求失败(${response.status}):`, text);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const disposition = response.headers.get('content-disposition') || '';
|
||||||
|
const match = disposition.match(/filename="?([^"]+)"?/);
|
||||||
|
const fileName = match ? decodeURIComponent(match[1]) : '下载文件.xlsx';
|
||||||
|
|
||||||
|
const blob = await response.blob();
|
||||||
|
saveAs(blob, fileName);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('下载失败:', err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user