250 lines
7.4 KiB
TypeScript
250 lines
7.4 KiB
TypeScript
import { onBeforeUnmount } from 'vue';
|
|
import axios from 'axios';
|
|
import type { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
import type { MessageReactive } from 'naive-ui';
|
|
import type { MessageApiInjection } from 'naive-ui/es/message/src/MessageProvider';
|
|
import { useLoading } from '@sa/hooks';
|
|
import { getAuthorization } from '@/service/request/shared';
|
|
|
|
interface MimeMap {
|
|
xlsx: string;
|
|
zip: string;
|
|
oss: string;
|
|
}
|
|
|
|
const mimeMap: MimeMap = {
|
|
xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
|
zip: 'application/zip',
|
|
oss: 'application/octet-stream'
|
|
};
|
|
|
|
const baseUrl = import.meta.env.VITE_SERVICE_BASE_URL;
|
|
|
|
export function useDownLoadFile() {
|
|
let messageReactive: MessageReactive | undefined | null;
|
|
const { loading, startLoading, endLoading } = useLoading();
|
|
|
|
function paramsGetToUrl(url: string, params: Record<string, any> | null): string {
|
|
let urlparams = url;
|
|
if (params) {
|
|
urlparams = `${url}?`;
|
|
for (const propName of Object.keys(params)) {
|
|
const value = params[propName];
|
|
const part = `${encodeURIComponent(propName)}=`;
|
|
if (value !== null && typeof value !== 'undefined') {
|
|
if (typeof value === 'object') {
|
|
// eslint-disable-next-line max-depth
|
|
for (const key of Object.keys(value)) {
|
|
// eslint-disable-next-line max-depth
|
|
if (value[key] !== null && typeof value[key] !== 'undefined') {
|
|
const par = `${propName}[${key}]`;
|
|
const subPart = `${encodeURIComponent(par)}=`;
|
|
urlparams += `${subPart + encodeURIComponent(value[key])}&`;
|
|
}
|
|
}
|
|
} else {
|
|
urlparams += `${part + encodeURIComponent(value)}&`;
|
|
}
|
|
}
|
|
}
|
|
urlparams = urlparams.slice(0, -1);
|
|
}
|
|
return baseUrl + urlparams;
|
|
}
|
|
|
|
function getPostParams(params: Record<string, any> | null) {
|
|
const dataParams: Record<string, any> = {}; // 用于存放请求体数据
|
|
// get请求映射params参数
|
|
if (params) {
|
|
for (const propName of Object.keys(params)) {
|
|
const value = params[propName];
|
|
if (value !== null && typeof value !== 'undefined') {
|
|
if (typeof value === 'object') {
|
|
// eslint-disable-next-line max-depth
|
|
for (const key of Object.keys(value)) {
|
|
// eslint-disable-next-line max-depth
|
|
if (value[key] !== null && typeof value[key] !== 'undefined') {
|
|
const nestedKey = `${propName}[${key}]`;
|
|
dataParams[nestedKey] = value[key];
|
|
}
|
|
}
|
|
} else {
|
|
dataParams[propName] = value;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return dataParams;
|
|
}
|
|
|
|
function handleRequest(config: AxiosRequestConfig, mine: keyof MimeMap, filename: string) {
|
|
createMessage('warning', '正在导出中,请稍后...');
|
|
|
|
axios(config)
|
|
.then(res => {
|
|
resolveBlob(res, mine, filename);
|
|
})
|
|
.catch(err => {
|
|
createMessage('error', err.message);
|
|
endLoading();
|
|
});
|
|
}
|
|
|
|
function downLoadOss(ossId: string | number = '', filename: string = '') {
|
|
handleRequest(
|
|
{
|
|
method: 'get',
|
|
url: `${baseUrl}/system/oss/download/${ossId}`,
|
|
responseType: 'blob',
|
|
headers: { Authorization: getAuthorization() }
|
|
},
|
|
'oss',
|
|
filename
|
|
);
|
|
}
|
|
|
|
function downLoadZip(url: string, filename: string = '') {
|
|
handleRequest(
|
|
{
|
|
method: 'get',
|
|
url: baseUrl + url,
|
|
responseType: 'blob',
|
|
headers: { Authorization: getAuthorization() }
|
|
},
|
|
'zip',
|
|
filename
|
|
);
|
|
}
|
|
|
|
function downLoadZipPost(url: string, params: Record<string, any> | null = null, filename: string = '') {
|
|
handleRequest(
|
|
{
|
|
method: 'post',
|
|
url: baseUrl + url,
|
|
data: getPostParams(params),
|
|
responseType: 'blob',
|
|
headers: {
|
|
Authorization: getAuthorization(),
|
|
'Content-Type': 'application/json;charset=utf-8' // 设置请求体类型
|
|
}
|
|
},
|
|
'zip',
|
|
filename
|
|
);
|
|
}
|
|
|
|
function downLoadExcel(url: string, params: Record<string, any> | null = null, filename: string = '') {
|
|
handleRequest(
|
|
{
|
|
method: 'get',
|
|
url: paramsGetToUrl(url, params),
|
|
responseType: 'blob',
|
|
headers: {
|
|
Authorization: getAuthorization()
|
|
}
|
|
},
|
|
'xlsx',
|
|
filename
|
|
);
|
|
}
|
|
|
|
function downLoadExcelPost(url: string, params: Record<string, any> | null = null, filename: string = '') {
|
|
handleRequest(
|
|
{
|
|
method: 'post',
|
|
url: baseUrl + url,
|
|
data: getPostParams(params),
|
|
responseType: 'blob',
|
|
headers: {
|
|
Authorization: getAuthorization(),
|
|
'Content-Type': 'application/json;charset=utf-8' // 设置请求体类型
|
|
}
|
|
},
|
|
'xlsx',
|
|
filename
|
|
);
|
|
}
|
|
|
|
function resolveBlob(res: AxiosResponse, mime: keyof MimeMap, filename: string) {
|
|
const mimeType = mimeMap[mime];
|
|
if (res.headers['content-type'].includes('application/json')) {
|
|
const fileReader = new FileReader();
|
|
fileReader.readAsText(new Blob([res.data], { type: 'application/octet-stream' }), 'utf-8');
|
|
fileReader.onload = () => {
|
|
try {
|
|
const result = JSON.parse(fileReader.result as string);
|
|
if (result.code === 500) {
|
|
removeMessage();
|
|
messageReactive = window.$message?.error(`导出失败:${result.msg}`, { duration: 0 });
|
|
}
|
|
} catch {
|
|
removeMessage();
|
|
messageReactive = window.$message?.error(`系统错误,请联系管理员`, { duration: 0 });
|
|
}
|
|
};
|
|
endLoading();
|
|
setTimeout(() => {
|
|
removeMessage();
|
|
}, 3000);
|
|
return;
|
|
}
|
|
|
|
const aLink = document.createElement('a');
|
|
const blob = new Blob([res.data], { type: mimeType });
|
|
// //从response的headers中获取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 设置的文件名;
|
|
const patt = /filename=([^;]+\.[^.;]+);*/;
|
|
const contentDisposition = decodeURI(res.headers['content-disposition']);
|
|
const result = patt.exec(contentDisposition);
|
|
// var fileName = result[1]
|
|
// fileName = fileName.replace(/\"/g, '')
|
|
let fileName: string | undefined = '';
|
|
if (filename) {
|
|
fileName = filename;
|
|
} else {
|
|
fileName = result?.[1];
|
|
fileName = fileName?.replace(/"/g, '');
|
|
}
|
|
aLink.style.display = 'none';
|
|
aLink.href = URL.createObjectURL(blob);
|
|
aLink.setAttribute('download', decodeURI(typeof fileName === 'string' ? fileName : '')); // 设置下载文件名称
|
|
document.body.appendChild(aLink);
|
|
aLink.click();
|
|
URL.revokeObjectURL(aLink.href); // 清除引用
|
|
document.body.removeChild(aLink);
|
|
|
|
createMessage('success', '导出成功');
|
|
endLoading();
|
|
setTimeout(() => {
|
|
removeMessage();
|
|
}, 3000);
|
|
}
|
|
|
|
// 创建消息框
|
|
function createMessage(type: keyof MessageApiInjection, message: string) {
|
|
startLoading();
|
|
removeMessage();
|
|
messageReactive = window.$message?.[type](message, { duration: 0 }) as MessageReactive;
|
|
}
|
|
|
|
// 移出消息框
|
|
function removeMessage() {
|
|
if (messageReactive) {
|
|
messageReactive.destroy();
|
|
messageReactive = null;
|
|
}
|
|
}
|
|
|
|
onBeforeUnmount(() => {
|
|
removeMessage();
|
|
});
|
|
|
|
return {
|
|
loading,
|
|
downLoadOss,
|
|
downLoadZip,
|
|
downLoadZipPost,
|
|
downLoadExcel,
|
|
downLoadExcelPost
|
|
};
|
|
}
|