文章目录
前言
若依框架前端中,要使用一些文本、数据、图表制作报表,然后导出,那么这个功能如何实现呢?
一、Echarts准备工作
1、查看是否安装了Echarts
查看是否安装了Echarts,方法是,终端运行:
npm list echarts
以下代表已安装成功:
如果没安装则执行安装依赖包:
npm install echarts --save
2、Echarts导入script 中
import * as echarts from 'echarts'
3、使用Echarts创建图表
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依赖包
npm install html2canvas jspdf
2、html2canvas和jsPDF引用到script中
import html2canvas from 'html2canvas';
import { jsPDF } from 'jspdf'; // jspdf需解构导入
3、制作并打印报表
1、按钮
<div>
<!-- 添加导出按钮 -->
<button @click="exportTextAndChartAsPDF" class="export-btn">导出报表</button>
</div>
2、按钮调用
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、按钮样式
/* 添加导出按钮样式 */
.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;
}