feat: base 所有表格增加通用导出方法
This commit is contained in:
parent
a0814191a7
commit
48ea04138b
|
|
@ -45,6 +45,14 @@
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-if="!hideRefresh" @click="reload" icon="el-icon-refresh-right" circle style="margin-left: 15px">
|
<el-button v-if="!hideRefresh" @click="reload" icon="el-icon-refresh-right" circle style="margin-left: 15px">
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<el-popover v-if="!hideExport" placement="top" trigger="click" :hide-after="0">
|
||||||
|
<template #reference>
|
||||||
|
<el-button icon="el-icon-download" circle style="margin-left: 15px"></el-button>
|
||||||
|
</template>
|
||||||
|
<div><el-button type="primary" size="small" @click="exportExcel(0)">1导出本页数据</el-button></div>
|
||||||
|
<div style="margin-top: 2px;" v-if="hExportExcel"><el-button type="primary" size="small" @click="exportExcel(1)">2导出本页数据</el-button></div>
|
||||||
|
<div style="margin-top: 2px;" v-if="hExportExcel"><el-button type="primary" size="small" @click="exportExcel(2)">3导出全部数据</el-button></div>
|
||||||
|
</el-popover>
|
||||||
<el-popover v-if="column" placement="top" title="列设置" :width="500" trigger="click" :hide-after="0"
|
<el-popover v-if="column" placement="top" title="列设置" :width="500" trigger="click" :hide-after="0"
|
||||||
@show="customColumnShow = true" @after-leave="customColumnShow = false">
|
@show="customColumnShow = true" @after-leave="customColumnShow = false">
|
||||||
|
|
||||||
|
|
@ -82,7 +90,7 @@
|
||||||
import config from "@/config/table";
|
import config from "@/config/table";
|
||||||
import columnSetting from "./columnSetting";
|
import columnSetting from "./columnSetting";
|
||||||
import { genTree } from "@/utils/verificate";
|
import { genTree } from "@/utils/verificate";
|
||||||
|
import { domToExcel } from "@/utils/exportExcel";
|
||||||
export default {
|
export default {
|
||||||
name: "scTable",
|
name: "scTable",
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -115,6 +123,8 @@ export default {
|
||||||
hideDo: { type: Boolean, default: false },
|
hideDo: { type: Boolean, default: false },
|
||||||
hideRefresh: { type: Boolean, default: false },
|
hideRefresh: { type: Boolean, default: false },
|
||||||
hideSetting: { type: Boolean, default: false },
|
hideSetting: { type: Boolean, default: false },
|
||||||
|
hideExport: { type: Boolean, default: false },
|
||||||
|
hExportExcel: { type: Function, default: null },
|
||||||
paginationLayout: { type: String, default: config.paginationLayout },
|
paginationLayout: { type: String, default: config.paginationLayout },
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -299,6 +309,35 @@ export default {
|
||||||
this.getData();
|
this.getData();
|
||||||
this.$emit("resetQuery");
|
this.$emit("resetQuery");
|
||||||
},
|
},
|
||||||
|
//导出
|
||||||
|
exportExcel(type=0) {
|
||||||
|
if (type === 0) {
|
||||||
|
try {
|
||||||
|
domToExcel(this.$refs.scTable.$el, "表格数据");
|
||||||
|
} catch (error) {
|
||||||
|
console.error('导出失败:', error);
|
||||||
|
this.$message.error("导出失败");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type === 1) {
|
||||||
|
this.hExportExcel(this.tableData);
|
||||||
|
}else if (type === 2) {
|
||||||
|
var c = Object.assign({}, this.query, this.tableParams, {[this.orderStr]: this.order}, {page: 0})
|
||||||
|
let ElLoading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: '数据请求中,请稍后...',
|
||||||
|
background: 'rgba(0, 0, 0, 0)',
|
||||||
|
})
|
||||||
|
this.apiObj.req(c).then(res=>{
|
||||||
|
ElLoading.close();
|
||||||
|
this.hExportExcel(res);
|
||||||
|
}).catch(err=>{
|
||||||
|
ElLoading.close();
|
||||||
|
console.log(err)
|
||||||
|
this.$message.error("导出失败");
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
//自定义变化事件
|
//自定义变化事件
|
||||||
columnSettingChange(userColumn) {
|
columnSettingChange(userColumn) {
|
||||||
this.userColumn = userColumn;
|
this.userColumn = userColumn;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,11 @@
|
||||||
import * as XLSX from 'xlsx';
|
import * as XLSX from 'xlsx';
|
||||||
|
|
||||||
|
export const domToExcel = (dom, name="data") => {
|
||||||
|
const worksheet = XLSX.utils.table_to_sheet(dom);
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet);
|
||||||
|
XLSX.writeFile(workbook, `${name}.xlsx`);
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* eg: .columns = [
|
* eg: .columns = [
|
||||||
* { header: 'Id', key: 'id', wpx: 10 },
|
* { header: 'Id', key: 'id', wpx: 10 },
|
||||||
|
|
@ -10,35 +17,83 @@ import * as XLSX from 'xlsx';
|
||||||
* @param data 数据
|
* @param data 数据
|
||||||
* @param name 文件名
|
* @param name 文件名
|
||||||
*/
|
*/
|
||||||
export const generateExcel = (columns = [], data = [], name = '') => {
|
export const dataToExcel = (columns = [], data = [], name = 'data') => {
|
||||||
const headers = columns.map((item) => item.header);
|
const headers = columns.map((item) => item.header);
|
||||||
const otherConfigs = columns.map(({ key, header, ...item }) => item);
|
|
||||||
const dataList = data.map((item) => {
|
const dataList = data.map((item) => {
|
||||||
let obj = {};
|
let obj = {};
|
||||||
columns.forEach((col) => {
|
columns.forEach(col => {
|
||||||
obj[col.header] = item[col.key];
|
obj[col.header] = getNestedValue(item, col.key) ?? '';
|
||||||
});
|
});
|
||||||
return obj;
|
return obj;
|
||||||
});
|
});
|
||||||
const workbook = XLSX.utils.book_new();
|
const workbook = XLSX.utils.book_new();
|
||||||
workbook.SheetNames.push(name);
|
// workbook.SheetNames.push(name);
|
||||||
const worksheet = XLSX.utils.json_to_sheet(dataList, {
|
const worksheet = XLSX.utils.json_to_sheet(dataList, {
|
||||||
header: headers,
|
header: headers,
|
||||||
});
|
});
|
||||||
worksheet['!cols'] = otherConfigs;
|
// 自动计算列宽
|
||||||
workbook.Sheets[name] = worksheet;
|
worksheet['!cols'] = calculateColumnWidths(columns, dataList);
|
||||||
// 生成Blob数据
|
// const otherConfigs = columns.map(({ key, header, ...item }) => item);
|
||||||
const excelData = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' });
|
// worksheet['!cols'] = otherConfigs;
|
||||||
const blobData = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
XLSX.utils.book_append_sheet(workbook, worksheet);
|
||||||
// 创建Blob URL
|
XLSX.writeFile(workbook, `${name}.xlsx`);
|
||||||
const blobUrl = URL.createObjectURL(blobData);
|
// workbook.Sheets[name] = worksheet;
|
||||||
// 创建一个隐藏的<a>标签并设置href属性为Blob URL
|
// // 生成Blob数据
|
||||||
const link = document.createElement('a');
|
// const excelData = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' });
|
||||||
link.href = blobUrl;
|
// const blobData = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' });
|
||||||
link.target = '_blank';
|
// // 创建Blob URL
|
||||||
link.download = `${name}.xlsx`;
|
// const blobUrl = URL.createObjectURL(blobData);
|
||||||
// 触发点击操作,开始下载文件
|
// // 创建一个隐藏的<a>标签并设置href属性为Blob URL
|
||||||
link.click();
|
// const link = document.createElement('a');
|
||||||
// 释放Blob URL
|
// link.href = blobUrl;
|
||||||
URL.revokeObjectURL(blobUrl);
|
// link.target = '_blank';
|
||||||
|
// link.download = `${name}.xlsx`;
|
||||||
|
// // 触发点击操作,开始下载文件
|
||||||
|
// link.click();
|
||||||
|
// // 释放Blob URL
|
||||||
|
// URL.revokeObjectURL(blobUrl);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getNestedValue = (obj, path, defaultValue = '') => {
|
||||||
|
if (!obj || !path) return defaultValue;
|
||||||
|
|
||||||
|
const keys = path.split('.');
|
||||||
|
let result = obj;
|
||||||
|
|
||||||
|
for (const key of keys) {
|
||||||
|
if (result === null || result === undefined) {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
result = result[key];
|
||||||
|
}
|
||||||
|
|
||||||
|
return result !== undefined ? result : defaultValue;
|
||||||
|
};
|
||||||
|
const calculateColumnWidths = (columns, dataList) => {
|
||||||
|
// 确保 dataList 有数据
|
||||||
|
if (!dataList || dataList.length === 0) {
|
||||||
|
return columns.map(col => ({ wch: 15 })); // 返回默认宽度
|
||||||
|
}
|
||||||
|
|
||||||
|
return columns.map(col => {
|
||||||
|
// 固定宽度优先
|
||||||
|
if (col.wpx) return { wpx: col.wpx };
|
||||||
|
if (col.wch) return { wch: col.wch };
|
||||||
|
if (col.width) return { wch: col.width };
|
||||||
|
|
||||||
|
const header = col.header || '';
|
||||||
|
let maxWidth = header.length;
|
||||||
|
|
||||||
|
// 遍历数据计算最大宽度
|
||||||
|
for (let i = 0; i < Math.min(dataList.length, 100); i++) {
|
||||||
|
const item = dataList[i];
|
||||||
|
// 确保使用正确的键名
|
||||||
|
const value = item[header] !== undefined ? String(item[header]) : '';
|
||||||
|
if (value.length > maxWidth) {
|
||||||
|
maxWidth = value.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { wch: Math.min(Math.max(maxWidth + 2, 8), 50) };
|
||||||
|
});
|
||||||
};
|
};
|
||||||
Loading…
Reference in New Issue