是否可以对MUI Material Table的默认PDF导出功能进行样式自定义?
MUI Material Table 自定义样式PDF导出实现方案
实现思路
Material Table 内置的默认PDF导出仅支持表格内容的基础导出,无法满足多模块自定义内容的需求,因此我们需要替换默认导出逻辑,结合jsPDF+jspdf-autotable库实现完全自定义的PDF内容排版。
前置依赖安装
npm install jspdf jspdf-autotable # 若需要渲染页面元素为图片可额外安装html2canvas npm install html2canvas
核心实现步骤
- 禁用默认导出,新增自定义导出按钮
在Material Table的actions配置中添加自定义导出按钮,关闭默认的export功能:
import MaterialTable from '@material-table/core'; import { ExportToPdf } from '@mui/icons-material'; <MaterialTable // 其他基础配置 options={{ exportButton: false, // 关闭默认导出 }} actions={[ { icon: () => <ExportToPdf />, tooltip: '自定义导出PDF', onClick: (event, rowData) => handleExportPdf(rowData), // 行级导出,全量导出可放到toolbar isFreeAction: true, // 设为true则按钮放在顶部工具栏 } ]} />
- 编写自定义导出逻辑
以下是包含logo、多信息模块、表格的导出逻辑示例:
import jsPDF from 'jspdf'; import autoTable from 'jspdf-autotable'; // 提前把logo转成base64,避免跨域无法加载 const LOGO_BASE64 = '你的logo base64字符串'; const handleExportPdf = (data) => { const doc = new jsPDF('p', 'mm', 'a4'); // p=纵向,单位mm,A4尺寸 const pageWidth = doc.internal.pageSize.getWidth(); // 1. 渲染顶部logo doc.addImage(LOGO_BASE64, 'PNG', 14, 10, 30, 30); // 渲染右上角ID信息 doc.setFontSize(12); doc.text(`订单ID:${data.orderId}`, pageWidth - 14, 15, { align: 'right' }); doc.text(`导出时间:${new Date().toLocaleString()}`, pageWidth -14, 22, { align: 'right' }); // 2. 渲染学生信息模块 doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text('学生信息', 14, 50); doc.setFont('helvetica', 'normal'); doc.setFontSize(12); doc.text(`姓名:${data.student.name}`, 14, 58); doc.text(`年级:${data.student.grade}`, 14, 66); doc.text(`学号:${data.student.studentNo}`, 80, 58); doc.text(`联系电话:${data.student.phone}`, 80, 66); // 3. 渲染用户信息模块 doc.setFontSize(14); doc.setFont('helvetica', 'bold'); doc.text('用户信息', 14, 80); doc.setFont('helvetica', 'normal'); doc.setFontSize(12); doc.text(`账号:${data.user.account}`, 14, 88); doc.text(`注册时间:${data.user.registerTime}`, 14, 96); doc.text(`所属机构:${data.user.org}`, 80, 88); // 4. 渲染订单表格 autoTable(doc, { startY: 110, // 表格开始的Y轴位置 head: [['订单商品', '单价', '数量', '实付金额', '购买时间']], body: data.orderList.map(item => [item.goodsName, item.price, item.count, item.payAmount, item.buyTime]), headStyles: { fillColor: '#1976d2', // 和MUI主题色保持一致 textColor: '#fff', }, styles: { fontSize: 10, cellPadding: 3, }, margin: { left: 14, right: 14 }, didDrawPage: (data) => { // 页脚内容,分页时自动添加 doc.setFontSize(10); doc.text(`第 ${doc.internal.getNumberOfPages()} 页`, pageWidth / 2, doc.internal.pageSize.getHeight() - 10, { align: 'center' }); } }) // 保存PDF doc.save(`订单_${data.orderId}.pdf`); }
常见问题处理
- 中文乱码:需要给jsPDF引入支持中文的字体库,把ttf字体转成base64后通过
doc.addFont()方法加载即可。 - 分页适配:
jspdf-autotable会自动处理表格内容的分页,可通过didDrawPage钩子统一添加页眉页脚。 - 复杂样式渲染:如果有更复杂的排版需求,可以先用html写好模板,通过
html2canvas转成图片后插入到PDF中。
内容的提问来源于stack exchange,提问作者React Enjoyer
相关产品推荐
相关产品推荐

