first commit
This commit is contained in:
249
front/src/hooks/common/download.ts
Normal file
249
front/src/hooks/common/download.ts
Normal file
@@ -0,0 +1,249 @@
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user