From 48ea04138b6f179d6221c209a75350d0c67de77d Mon Sep 17 00:00:00 2001 From: caoqianming Date: Sun, 2 Nov 2025 00:22:29 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20base=20=E6=89=80=E6=9C=89=E8=A1=A8?= =?UTF-8?q?=E6=A0=BC=E5=A2=9E=E5=8A=A0=E9=80=9A=E7=94=A8=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/scTable/index.vue | 41 +++++++++++++- src/utils/exportExcel.js | 97 +++++++++++++++++++++++++------- 2 files changed, 116 insertions(+), 22 deletions(-) diff --git a/src/components/scTable/index.vue b/src/components/scTable/index.vue index eba599fb..00a5816f 100644 --- a/src/components/scTable/index.vue +++ b/src/components/scTable/index.vue @@ -45,6 +45,14 @@ + + +
1导出本页数据
+
2导出本页数据
+
3导出全部数据
+
@@ -82,7 +90,7 @@ import config from "@/config/table"; import columnSetting from "./columnSetting"; import { genTree } from "@/utils/verificate"; - +import { domToExcel } from "@/utils/exportExcel"; export default { name: "scTable", components: { @@ -115,6 +123,8 @@ export default { hideDo: { type: Boolean, default: false }, hideRefresh: { 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 }, }, watch: { @@ -299,6 +309,35 @@ export default { this.getData(); 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) { this.userColumn = userColumn; diff --git a/src/utils/exportExcel.js b/src/utils/exportExcel.js index 23bcbae0..01bf6b5a 100644 --- a/src/utils/exportExcel.js +++ b/src/utils/exportExcel.js @@ -1,4 +1,11 @@ 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 = [ * { header: 'Id', key: 'id', wpx: 10 }, @@ -10,35 +17,83 @@ import * as XLSX from 'xlsx'; * @param data 数据 * @param name 文件名 */ -export const generateExcel = (columns = [], data = [], name = '') => { +export const dataToExcel = (columns = [], data = [], name = 'data') => { const headers = columns.map((item) => item.header); - const otherConfigs = columns.map(({ key, header, ...item }) => item); const dataList = data.map((item) => { let obj = {}; - columns.forEach((col) => { - obj[col.header] = item[col.key]; + columns.forEach(col => { + obj[col.header] = getNestedValue(item, col.key) ?? ''; }); return obj; }); const workbook = XLSX.utils.book_new(); - workbook.SheetNames.push(name); + // workbook.SheetNames.push(name); const worksheet = XLSX.utils.json_to_sheet(dataList, { header: headers, }); - worksheet['!cols'] = otherConfigs; - workbook.Sheets[name] = worksheet; - // 生成Blob数据 - const excelData = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' }); - const blobData = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); - // 创建Blob URL - const blobUrl = URL.createObjectURL(blobData); - // 创建一个隐藏的标签并设置href属性为Blob URL - const link = document.createElement('a'); - link.href = blobUrl; - link.target = '_blank'; - link.download = `${name}.xlsx`; - // 触发点击操作,开始下载文件 - link.click(); - // 释放Blob URL - URL.revokeObjectURL(blobUrl); + // 自动计算列宽 + worksheet['!cols'] = calculateColumnWidths(columns, dataList); + // const otherConfigs = columns.map(({ key, header, ...item }) => item); + // worksheet['!cols'] = otherConfigs; + XLSX.utils.book_append_sheet(workbook, worksheet); + XLSX.writeFile(workbook, `${name}.xlsx`); + // workbook.Sheets[name] = worksheet; + // // 生成Blob数据 + // const excelData = XLSX.write(workbook, { type: 'array', bookType: 'xlsx' }); + // const blobData = new Blob([excelData], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }); + // // 创建Blob URL + // const blobUrl = URL.createObjectURL(blobData); + // // 创建一个隐藏的标签并设置href属性为Blob URL + // const link = document.createElement('a'); + // link.href = 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) }; + }); }; \ No newline at end of file