数据量略大的表格导出

86 阅读1分钟

// 封装下载组件

import * as XLSX from 'xlsx'

function downloadTable(sheetData: any, title: any) {

  const sheet = XLSX.utils.json_to_sheet(sheetData);

  // 支持多 sheet

  const wb = XLSX.utils.book_new();

  XLSX.utils.book_append_sheet(wb, sheet);

  // 支持多 sheet

  const workbookBlob = workbook2blob(wb);

  // 导出最后的总表

  openDownloadDialog(workbookBlob, `${title}.xlsx`);

}

function workbook2blob(workbook: any) {

  // 生成excel的配置项

  const wopts = {

    // 要生成的文件类型

    bookType: 'xlsx',

    // // 是否生成Shared String Table,官方解释是,如果开启生成速度会下降,但在低版本IOS设备上有更好的兼容性

    bookSST: false,

    type: 'binary'

  };

  const wbout = XLSX.write(workbook, wopts as any);

  // 将字符串转ArrayBuffer

  const 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;

  };

  const blob = new Blob([s2ab(wbout)], {

    type: 'application/octet-stream'

  });

  return blob;

}

function openDownloadDialog(blob: any, fileName: any) {

  if (typeof blob === 'object' && blob instanceof Blob) {

    blob = URL.createObjectURL(blob); // 创建blob地址

  }

  const aLink = document.createElement('a');

  aLink.href = blob;

  // HTML5新增的属性,指定保存文件名,可以不要后缀,注意,有时候 file:///模式下不会生效

  aLink.download = fileName || '';

  let event;

  if (window.MouseEvent) event = new MouseEvent('click');

  //   移动端

  else {

    event = document.createEvent('MouseEvents');

    event.initMouseEvent(

      'click',

      true,

      false,

      window,

      0,

      0,

      0,

      0,

      0,

      false,

      false,

      false,

      false,

      0,

      null

    );

  }

  aLink.dispatchEvent(event);

}

  


export default downloadTable;

import {  ElMessage } from 'element-plus';
import moment from 'moment';
import downloadTable from '@/utils/exportExcel';
const state = reactive({

  total: 0,

  exportLoading: false, //导出loading

  exportSize: 1000, //导出数据量

});


const fetchDataByPage = async (page: number) => {

  let params = {};

  const data: any = await getUserModule({

    ...params,

    current: page,

    size:state.exportSize,

  })

  if (data.code == 0) {

    return data.data.list;

  } else {

    return [];

  }

}

const fetchAllData = async () => {

  // 创建一个包含所有分页请求的 Promise 数组

  const pagePromises = [];

  for (let page = 1; page <= Math.ceil(state.total / state.exportSize); page++) {

    pagePromises.push(fetchDataByPage(page));

  }

  // 使用 Promise.allSettled 确保所有请求都完成

  const allPagesResults = await Promise.allSettled(pagePromises);

  // 处理结果

  const successfulData = [] as any;

  const failedPages = [] as any;

  allPagesResults.forEach((result, index) => {

    if (result.status === "fulfilled" && result.value) {

      successfulData.push(...result.value); // 合并成功的数据

    } else {

      failedPages.push(index + 1); // 记录失败的页码

    }

  });

  if (failedPages.length > 0) {

    ElMessage.error("以下页码请求失败:", failedPages.join(", "));

  }

  console.log("successfulData", successfulData);

  return successfulData;

}

const  handleExport = async ()=> {

  state.exportLoading = true;

  try {

    let data = await fetchAllData();

    if (data.length != 0) {

      const sheetData = data.map((item: any) => ({

        "手机号": item.phone,

        "客户号": item.customCode,

        "产品名称": item.productName,

        "产品ID": item.productId,

        "权限开始时间": item.moduleStart,

        "权限到期时间": item.moduleEnd,

        "有效期(天)": moment(item.moduleEnd).diff(moment(item.moduleStart), 'days'),

        "状态": moment(item.moduleEnd).diff(moment(new Date()), 'seconds') > 0 ? '生效中' : '已过期',

        "订单总笔数": item.totalOrder,

        "付费订单笔数": item.totalPayOrder,

        "免费订单笔数": item.totalFreeOrder,

        "更新时间": item.lastUpdatetime,

      }));

      downloadTable(

        sheetData,

        `用户权限明细_${moment(new Date()).format('YYYY-MM-DD')} `

      );

    } else if (data.length == 0) {

      ElMessage.warning('暂无数据可导出');

    }

    state.exportLoading = false;

  } catch (error) {

    state.exportLoading = false;

  }

}