You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

174 lines
4.6 KiB

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);
};