← dompdf.js Studio

销售报表PDF导出完整指南

销售报表是销售管理和经营决策的重要依据,日报、周报、月报几乎是每个销售团队的标配。传统导出方式要么依赖后端模板渲染,要么用浏览器打印,前者迭代慢、中文字体问题多,后者版式不受控、不同电脑导出的效果完全不同。dompdf.js将销售报表的生成完全搬到浏览器前端:销售数据通过接口获取后,前端组装成HTML表格,加上汇总统计和图表图片,一次addPage渲染成矢量PDF。本文将详细介绍销售报表PDF的导出方案,包括数据组织、表格与图表结合、多页月报导出以及常见问题,帮助销售系统快速上线导出能力。文中还会涉及指标口径统一、图表与表格如何配合、批量导出技巧,以及让合计数字保持可信的校验方法。无论你是在给CRM、ERP还是轻量销售工具加导出功能,这里的模板模式都能快速适配;因为一切都在浏览器里完成,销售团队拿到的是即时、一致的报表,再也不用等后端排期。

销售报表的业务场景与痛点

销售团队需要日报了解当天业绩,需要月报分析月度趋势,管理层则需要按区域、按产品、按销售人员的多维汇总报表。报表通常包含销售额、订单数、客单价、回款率等核心指标,以及明细列表和同比环比数据。

后端导出销售报表的常见问题包括:报表模板与业务代码耦合,指标口径一变就要改代码发版;数据量大时导出接口超时;服务器缺少中文字体导致报表乱码。这些问题让销售团队经常要等开发排期,报表时效性大打折扣。

浏览器打印方案虽然灵活,但不同电脑的浏览器设置、纸张大小、缩放比例各不相同,导出的PDF页边距和字体忽大忽小,无法形成统一规范;而且打印对话框的额外操作也降低了效率,不适合批量导出场景。

另一个常见痛点是报表口径不统一:有的系统把含税金额当销售额,有的用不含税金额,统计出来的数字对不上。前端方案可以把口径规则集中定义在模板逻辑里,所有报表共用同一套口径函数,从源头上消除各报表之间数字对不上的问题。

前端生成销售报表的优势

前端方案中,报表模板就是HTML,指标口径调整只需修改前端模板,刷新页面即可生效,无需发布服务端代码;销售数据的过滤、排序、汇总都可以在前端完成,报表形态灵活多变。

dompdf.js支持flex/grid布局,可以轻松实现卡片式的指标汇总区;支持图片嵌入,可以把图表库(如ECharts)渲染的统计图转为base64图片嵌入报表,实现表格加图表的专业组合排版。

批量导出是前端方案的天然优势:循环遍历多个销售人员或区域,逐次addPage后一次save,几十份报表瞬间生成;配合自动分页和页眉页脚,多页月报也能保持版式统一,打印即所得。

此外,前端生成让销售报表的定制变得非常轻量。销售总监想要一个新维度(比如按行业、按渠道拆分),前端开发当天就能在模板里加上一组分组统计,配合自动分页生成新报表;这种灵活性在后端方案里意味着一次完整的开发发版周期。

销售报表模板设计

销售报表建议分为四个区域:顶部是报表标题和统计周期;中部是指标汇总卡片,用flex布局横向排列销售额、订单数、客单价等核心数字;下方是销售明细表格;底部是同比环比分析和备注,层次分明。

明细表格的列建议包括销售人员、客户名称、产品、订单金额、成交时间、订单状态等,金额列右对齐并带千分位分隔符,状态列可以用不同颜色区分已成交、跟进中和已流失,提升可读性。

图表部分可以把ECharts或Chart.js生成的canvas转换为PNG的base64字符串,设置合适的宽度后嵌入HTML,dompdf.js会按比例嵌入图片,让报表既有明细数据又有趋势可视化,专业度大幅提升。

模板中还可以加入同比环比说明区,用简短文字解释数字背后的原因,比如本月增长主要来自企业版大单。文字说明让报表不只是数字堆砌,管理层阅读时能更快抓住重点;这些说明可以做成配置项,由销售运营维护,无需开发介入。

代码示例:导出销售月报PDF

下面演示销售月报的生成代码,包括指标汇总卡片、明细表格和图表图片嵌入,完整展示销售报表的典型结构,可以直接套用到日报和周报模板上。

图表转换的关键代码:使用ECharts渲染图表后调用getDataURL({ type: 'png', pixelRatio: 2 })获取高清base64,2倍像素比保证嵌入PDF后依然清晰;转换完成后及时dispose图表实例释放内存。

示例中的KPI卡片使用flex布局横向排列,每个卡片固定flex:1,宽度自动均分,无论显示三个还是五个指标都能自适应;如果指标较多,可以拆成两行排列,只需调整flex-wrap即可,布局代码几乎不用改。

图表嵌入的完整流程是:先创建ECharts实例渲染到隐藏的canvas容器,调用getDataURL({ type: 'png', pixelRatio: 2 })拿到高清base64,再写入模板的img标签。注意在转换完成后调用chart.dispose()释放实例,避免内存占用;如果报表包含多张图表,逐张转换逐张释放,保持内存平稳。

另外,图表建议固定宽高比,比如宽度100%、高度260px,dompdf.js会按声明尺寸嵌入,保证PDF中图表不变形;折线图、柱状图、饼图的选择要匹配数据形态,趋势用折线、对比用柱状、构成用饼图,让图表真正辅助阅读。

import { DomPDF } from 'dompdf.js';

// 假设已通过接口获取数据
const summary = { revenue: '1,285,000', orders: 326, avgOrder: '3,941' };
const detailRows = [
  { seller: '张伟', customer: '华信科技', product: '企业版', amount: '120,000', status: '已成交' },
  { seller: '李娜', customer: '蓝海贸易', product: '专业版', amount: '86,000', status: '已成交' },
  { seller: '王强', customer: '云帆网络', product: '基础版', amount: '42,500', status: '跟进中' },
];

const detailHtml = detailRows.map(row => `
  <tr>
    <td style='border:1px solid #333;padding:6px'>${row.seller}</td>
    <td style='border:1px solid #333;padding:6px'>${row.customer}</td>
    <td style='border:1px solid #333;padding:6px'>${row.product}</td>
    <td style='border:1px solid #333;padding:6px;text-align:right'>¥${row.amount}</td>
    <td style='border:1px solid #333;padding:6px'>${row.status}</td>
  </tr>
`).join('');

const reportHtml = `
  <h1 style='text-align:center;font-size:16pt'>2026年7月销售月报</h1>
  <div style='display:flex;justify-content:space-between;margin:12px 0'>
    <div style='flex:1;border:1px solid #333;padding:10px;text-align:center'>
      <div style='font-size:10pt'>销售额</div>
      <div style='font-size:14pt;font-weight:bold'>¥${summary.revenue}</div>
    </div>
    <div style='flex:1;border:1px solid #333;padding:10px;text-align:center;margin:0 8px'>
      <div style='font-size:10pt'>订单数</div>
      <div style='font-size:14pt;font-weight:bold'>${summary.orders}</div>
    </div>
    <div style='flex:1;border:1px solid #333;padding:10px;text-align:center'>
      <div style='font-size:10pt'>客单价</div>
      <div style='font-size:14pt;font-weight:bold'>¥${summary.avgOrder}</div>
    </div>
  </div>
  <table style='width:100%;border-collapse:collapse'>
    <tr style='background:#f5f5f5'>
      <th style='border:1px solid #333;padding:6px'>销售</th>
      <th style='border:1px solid #333;padding:6px'>客户</th>
      <th style='border:1px solid #333;padding:6px'>产品</th>
      <th style='border:1px solid #333;padding:6px'>金额</th>
      <th style='border:1px solid #333;padding:6px'>状态</th>
    </tr>
    ${detailHtml}
  </table>
  <img src='${chartBase64}' style='width:100%;margin-top:12px' />
`;

const pdf = new DomPDF();
pdf.addPage(reportHtml, { format: 'A4', margin: '20mm' });
pdf.save('销售月报-2026年7月.pdf');

数据汇总与多页导出技巧

销售报表的汇总指标建议在JavaScript中完成计算,例如用reduce求销售额总和、计算客单价和环比增长,再以格式化字符串写入HTML;渲染层只负责展示,不负责计算,保证逻辑清晰可测试。

多页导出时注意控制每页内容量:一页建议不超过30行明细,行数过多可以按日期或产品分组拆页;使用addPage多次调用时,可以在每页HTML中带上独立的页标题,让每页自成一体。

页码和页眉页脚对多页报表很重要,dompdf.js支持页眉页脚/页码功能,可以在报表页脚显示第X页共Y页,页眉显示报表名称和生成时间,归档时能快速定位,避免多页报表丢失顺序。

多页报表还可以加入目录页或封面页,封面放报表标题、统计期间和生成人,目录列出各分页标题;用addPage先加封面再加内容页,最后save,整个报表的结构和可读性都会上一个台阶,适合定期呈报给管理层的正式月报。

常见问题与注意事项

常见问题一:图表图片模糊。原因是canvas导出分辨率不足,建议使用pixelRatio: 2或更高的倍率生成base64图片,并控制图片宽度不超过页面可用宽度,保证打印清晰。

常见问题二:flex布局在PDF中错位。dompdf.js支持flex/grid布局,但建议使用简单的justify-content: space-between横向排列卡片,避免嵌套过深的flex结构,减少渲染差异。

常见问题三:金额合计与明细不一致。汇总指标必须由同一份明细数据计算得出,建议在渲染前对明细求和并与接口返回的汇总值比对,不一致时提示异常,防止报表数据打架。

最后注意报表的时间范围口径:日报、周报、月报的起止时间要明确,跨月生成时避免重复统计;数据缓存也要处理,生成报表前建议刷新一次数据源,确保导出的是最新数据,并在页眉标注生成时间,让读者知道这份报表的数据时点。

⚡ 现场演示(点击生成 PDF)

下面的按钮用 dompdf.js 在浏览器端实时生成 PDF,无需后端:

Hello from dompdf.js!

这是由 dompdf.js 渲染的示例 PDF 内容。