【web应用】若依框架中,使用Echarts导出报表为PDF文件

文章目录


前言

若依框架前端中,要使用一些文本、数据、图表制作报表,然后导出,那么这个功能如何实现呢?

一、Echarts准备工作

1、查看是否安装了Echarts

查看是否安装了Echarts,方法是,终端运行:

c 复制代码
npm list echarts

以下代表已安装成功:

如果没安装则执行安装依赖包:

c 复制代码
npm install echarts --save

2、Echarts导入script 中

c 复制代码
import * as echarts from 'echarts'

3、使用Echarts创建图表

c 复制代码
const numbers = ref(['加载中', '加载中'])

onMounted(() => {
  setTimeout(() => {
    numbers.value = ['10', '30'] 
    
    const present = parseInt(numbers.value[0]);
    const total = parseInt(numbers.value[1]);
    const absent = total - present;

    // 初始化图表
    const chartDom = document.getElementById('attendanceChart');
    const myChart = echarts.init(chartDom);

    // 图表配置
    const option = {
      // 提示框配置
      tooltip: {
        trigger: 'item',  // 触发类型为数据项触发
        formatter: '{a} <br/>{b}: {c} ({d}%)'  // 提示框格式化字符串
        // {a} 系列名称, {b} 数据名称, {c} 数值, {d} 百分比
      },

      // 图例配置
      legend: {
        top: '0%',    // 图例距离容器顶部的距离
        left: 'center', // 图例水平居中
        textStyle: {   // 图例文字样式
          color: '#A6CAF4', // 文字颜色
          fontSize: 14     // 文字大小
        }
      },

      // 系列列表(一个图表可以包含多个系列)
      series: [
        {
          name: '你好',  // 系列名称
          type: 'pie',      // 图表类型为饼图
          radius: '100%',    // 饼图半径(单个值表示饼图,数组表示环图)
          top: '20%', // 饼图距离容器顶部的距离

          // 数据数组
          data: [
            {
              value: present,  
              name: '我好',    // 数据项名称
              itemStyle: {     // 数据项样式
                color: '#91CC75' // 出勤部分颜色(绿色)
              }
            },
            {
              value: absent,   // 数据值
              name: '未出勤',  // 数据项名称
              itemStyle: {     // 数据项样式
                color: '#409EF0' 
              }
            }
          ],

          // 平时不显示外侧标签和引导线
          label: {
            show: false
          },
          labelLine: {
            show: false
          },


          // 鼠标悬停时显示标签(类似图例效果)
          emphasis: {
            label: {
              show: true,
              position: 'inside', // 悬停时标签显示在内侧
              formatter: '{b}: {d}%', // 显示名称和百分比
              color: '#ffff', // 文字颜色
              fontSize: 14
            },
            itemStyle: {
              shadowBlur: 10,
              shadowOffsetX: 0,
              shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
          }

        }
      ]
    };

    // 使用配置项显示图表
    myChart.setOption(option);

    // 组件卸载时清理
    onBeforeUnmount(() => {
      // 如果图表实例存在,则销毁
      if (myChart) {
        myChart.dispose();  // 销毁图表实例,释放资源
      }

    });

  }, 300) // 延迟模拟数据加载
})

二、报表制作打印html2canvas和jsPDF准备工作

1、安装html2canvas和jsPDF依赖包

c 复制代码
npm install  html2canvas jspdf

2、html2canvas和jsPDF引用到script中

c 复制代码
import html2canvas from 'html2canvas';
import { jsPDF } from 'jspdf'; // jspdf需解构导入

3、制作并打印报表

1、按钮

c 复制代码
<div>
<!-- 添加导出按钮 -->
      <button @click="exportTextAndChartAsPDF" class="export-btn">导出报表</button>
</div>

2、按钮调用

c 复制代码
const personnelData = [
  { name: '张三', date: '2023-10-01', status: '出勤' },
  { name: '李四', date: '2023-10-01', status: '缺勤' },
  { name: '王五', date: '2023-10-02', status: '迟到' },
];

const exportTextAndChartAsPDF = async () => {
  const pdf = new jsPDF('p', 'mm', 'a4'); // 纵向 A4 纸
  const lineHeight = 10; // 行高
  let startY = 40; // 初始 Y 坐标

  // 1. 添加标题
  pdf.setFontSize(16).setTextColor(0, 0, 0);
  pdf.text('人数报表', 105, 15, { align: 'center' });

  // 2. 添加表格标题行
  pdf.setFontSize(12);
  pdf.text('姓名', 20, 30);
  pdf.text('日期', 80, 30);
  pdf.text('状态', 140, 30);

  // 3. 添加数据行
  personnelData.forEach((item, index) => {
    const currentY = startY + index * lineHeight;
    pdf.text(item.name, 20, currentY);
    pdf.text(item.date, 80, currentY);
    pdf.text(item.status, 140, currentY);
  });

  // 4. 截取饼图并添加到 PDF
  const chartContainer = document.getElementById('attendanceChart')?.parentNode; // 获取饼图容器(确保存在)
  if (chartContainer) {
    // 截图饼图区域
    const canvas = await html2canvas(chartContainer, {
      scale: 2, // 提高分辨率
      logging: false,
      useCORS: true, // 允许跨域图片
      backgroundColor: '#FFFFFF', // 背景设为白色
    });

    // 计算饼图在 PDF 中的位置(放在表格下方)
    const imgProps = { width: 80, height: 80 }; // 自定义饼图大小(mm)
    const imgX = 60; // X 坐标(居中偏左)
    const imgY = startY + personnelData.length * lineHeight + 20; // Y 坐标(表格下方留 20mm 间距)

    // 添加饼图到 PDF
    pdf.addImage(
        canvas.toDataURL('image/png'),
        'PNG',
        imgX,
        imgY,
        imgProps.width,
        imgProps.height
    );
  }

  // 5. 保存 PDF
  pdf.save('报表导出.pdf');
};

3、按钮样式

c 复制代码
/* 添加导出按钮样式 */
.export-btn {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 10;
  padding: 5px 10px;
  background-color: #409EFF;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

.export-btn:hover {
  background-color: #66b1ff;
}

三、导出结果

相关推荐
miss15 分钟前
AI 改完不敢上线?OpenSpec 规约驱动开发实战
前端·代码规范·前端工程化
AiMan1 小时前
腾讯ima还是不可以导出左侧所有对话,只能单条导出,方法不对吗
前端
去伪存真1 小时前
并发量一高就装死?Agent 全链路“防猝死”手册
前端·agent
Moment1 小时前
AI 编程时代,聊聊我的 Mac mini 双屏桌面
前端·后端
AiMan1 小时前
先确认能不能一次把Microsofat Copilot所有内容打包一个文件导出
前端
总要学点什么1 小时前
第97篇:三维数据加载-城市建筑白模自定义着色器——让一条光带沿高度扫上去,快慢却由帧率说了算
前端·gis·webgl·cesium·着色器·空间分析·白模
上海懒图科技2 小时前
工厂厂区电子地图定位导航:厂区人车精准定位,安全合规双保障
前端·arcgis·vue
西安小哥2 小时前
端侧跑大模型,真正的门槛不在参数量:一次 596 秒到 10 秒的压缩路径复盘
前端·人工智能
陈随易2 小时前
Cloudflare 出钱,Vite 团队挑人,44 个维护者分 30 万美元
前端·后端·程序员
恋猫de小郭3 小时前
Flutter THLC 的 WebView 滚动终于从 70 FPS 提升到 120 FPS
android·前端·flutter