Files
SaaS-lib/lib/util/xlsx-util.ts
xuziqiang d0155dbe3c push
2024-05-15 17:29:42 +08:00

175 lines
4.6 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { utils, write } from 'xlsx';
import { dateUtil } from '/nerv-lib/util/date-util';
import { NsMessage } from '/nerv-lib/component/message';
import axios from 'axios';
import { createVNode, h, render as vueRender } from 'vue';
import { NsXlsxImport } from '/nerv-lib/component/xlsx';
import { NsModal } from '/nerv-lib/component/modal';
interface MapItem {
title: string;
dataIndex: string;
format?: Function;
}
type objProps = {
[name: string]: any;
};
type argType = {
data: Array<object>;
xlsxMap: Array<MapItem>;
xlsxName: string;
limit?: number;
};
const DATE_FORMAT = 'YYYY-MM-DD ';
const MODAL_INFO = {
title: '警告',
okText: '确认',
cancelText: '取消',
};
const errorTable = [
{
title: '行数',
dataIndex: 'row',
},
{
title: '错误内容',
dataIndex: 'reason',
},
];
const sheet2blob = (sheet: any, sheetName = 'sheet1') => {
sheetName = sheetName || 'sheet1';
const workbook = {
SheetNames: [sheetName],
Sheets: {},
};
workbook['Sheets'][sheetName] = sheet;
// 生成excel的配置项
const wbout = write(workbook, {
bookType: 'xlsx', // 要生成的文件类型
bookSST: false, // 是否生成Shared String Table官方解释是如果开启生成速度会下降但在低版本IOS设备上有更好的兼容性
type: 'binary',
});
const blob = new Blob([s2ab(wbout)], { type: 'application/octet-stream' });
// 字符串转ArrayBuffer
function s2ab(s: any) {
const buf = new ArrayBuffer(s.length);
const view = new Uint8Array(buf);
for (let i = 0; i != s.length; ++i) view[i] = s.charCodeAt(i) & 0xff;
return buf;
}
return blob;
};
function openDownloadDialog(url: string | Blob | MediaSource, saveName: string) {
if (typeof url == 'object' && url instanceof Blob) {
url = URL.createObjectURL(url); // 创建blob地址
}
const aLink = document.createElement('a');
aLink.href = url;
aLink.download = saveName || '';
document.body.appendChild(aLink);
aLink.click();
document.body.removeChild(aLink);
}
function download(table: unknown[][], name: string, config: any) {
let isHandle;
if (config && config['isHandle']) {
isHandle = config['isHandle'];
}
let sheet;
//isHandle 表示自己处理表格样式和数据,不需要再做处理
isHandle ? (sheet = table) : (sheet = utils.aoa_to_sheet(table));
openDownloadDialog(sheet2blob(sheet), `${name}.xlsx`);
}
function DataHandler(data: Array<object>, keyMap: Array<MapItem>) {
const tableHeader: string[] = []; // 表头
const tableHeaderKeyMap: objProps = {}; // 表头索引map
keyMap?.map((item: MapItem) => {
tableHeader.push(item['title']);
tableHeaderKeyMap[item['title']] = item['dataIndex'];
});
const table = [tableHeader];
data.forEach((item: object) => {
const rowData: any[] = [];
tableHeader.forEach((th: string, index: number) => {
let temp = item[tableHeaderKeyMap[th]];
const format = keyMap[index].format;
if (format) temp = format(temp, item);
rowData.push(temp);
});
table.push(rowData);
});
return table;
}
export const importFile = (
{ api, params }: any,
reload: Function,
event: any,
successBack?: Function,
errorBack?: Function,
) => {
const formData = new FormData();
params &&
Object.keys(params).map((item) => {
formData.append(item, params[item]);
});
formData.append('file', event);
axios
.post(api, formData)
.then((res) => {
if (res) {
NsMessage.success('导入成功', 1, () => {
reload && reload();
successBack && successBack(res);
});
}
})
.catch((err) => {
if (errorBack) {
errorBack(err);
} else {
NsMessage.error(err.response?.data?.msg || '导入失败');
const error = err.response?.data?.data;
if (error)
xlsxExport({
data: error,
xlsxMap: errorTable,
xlsxName: '导入数据不规范说明YYYY-MM-DD',
});
}
});
};
const checkLimit = (data: Array<object>, limit?: number) => {
if (limit && data.length > limit) {
NsModal.confirm({
...MODAL_INFO,
content: `本次数据下载超过${limit}条,请重新选择数据!`,
});
return false;
}
return true;
};
export const xlsxExport = ({ data, xlsxMap, xlsxName, limit }: argType) => {
if (!checkLimit(data, limit)) return;
const name = dateUtil(new Date()).format(xlsxName);
download(DataHandler(data, xlsxMap), `${name}`, '');
};
export const xlsxImport = (data: any) => {
const div = document.createElement('div');
const vm = h(NsXlsxImport, { ...data }, '');
vueRender(vm, div);
};