使用Print.js适配58mm热敏POS打印机打印收据及替代方案咨询
解决Print.js适配58mm热敏POS打印机及替代方案
一、修复Print.js的58mm适配及边距问题
你现在遇到的A4边距问题,是因为Print.js默认采用了A4纸张的打印配置,哪怕你给内容div设了58mm宽度,打印时浏览器还是会套用A4的边距规则。可以通过以下步骤调整:
1. 自定义Print.js配置参数
修改你的打印调用代码,添加自定义样式和打印配置,覆盖默认的A4设置:
$("#print-receipt").on("click", function() { printJS({ printable: "invoice-print-div", type: "html", // 自定义打印样式,强制去掉边距并固定宽度 style: ` @media print { body { margin: 0 !important; padding: 0 !important; width: 58mm !important; } #invoice-print-div { display: block !important; } #invoice-print-div > div { width: 58mm !important; margin: 0 !important; padding: 0 2mm; /* 留一点点内边距避免内容贴边 */ } } `, scanStyles: false, // 禁用默认的样式扫描,避免干扰自定义样式 // 指定需要保留的目标元素样式,确保你的内容样式生效 targetStyle: ["width", "margin", "padding", "text-align", "background-color", "border"] }); });
2. 优化HTML结构的基础样式
给打印区域的div补充更明确的样式,同时在页面头部添加打印媒体查询的全局样式:
<head> <style> .hidden { display: none; } @media print { /* 确保打印时页面整体适配58mm宽度 */ body { width: 58mm; margin: 0; padding: 0; } .hidden { display: block !important; } } </style> </head>
这样调整后,Print.js会按照58mm的宽度打印,并且去掉多余的A4边距。
二、JavaScript打印的替代方案
如果Print.js还是达不到你的预期,或者你想尝试更灵活的方式,这里有几个实用的替代方案:
1. 原生window.print() + 自定义打印样式
这是最轻量化的方案,完全不需要第三方库,通过控制打印区域和打印样式来实现:
$("#print-receipt").on("click", function() { // 临时隐藏页面上不需要打印的元素 const nonPrintElements = $("body > *:not(#invoice-print-div)"); nonPrintElements.addClass("print-hidden"); // 显示打印区域 $("#invoice-print-div").removeClass("hidden"); // 触发打印 window.print(); // 打印完成后恢复页面状态 nonPrintElements.removeClass("print-hidden"); $("#invoice-print-div").addClass("hidden"); });
对应的CSS补充:
.print-hidden { display: none !important; } @media print { body { width: 58mm; margin: 0; padding: 0; } #invoice-print-div > div { width: 58mm; padding: 0 2mm; } }
2. 使用ESC/POS专用打印库
热敏POS打印机大多支持ESC/POS指令,用专门的库可以直接发送原生指令,能精准控制字体、对齐、切纸等操作,比HTML打印更稳定。比如前端的escpos-js:
// 示例(需引入escpos-js库) const { Printer, Model, USB } = require('escpos'); // 通过USB连接打印机(需浏览器支持Web USB) USB.requestDevice().then(device => { const adapter = new USB(device); const printer = new Printer(new Model('TM-T88V'), adapter); printer .font('a') .align('ct') // 居中对齐 .text('alpha') .newLine() // 打印表格 .table([ ['Item', 'Qty', 'Price'], ['abc', '1', '120'], ['pqr', '2', '240'], ['xyz', '4', '360'] ]) .newLine(2) .cut() // 切纸 .close(); });
这种方式适合需要精细控制打印格式的场景,比如打印条码、logo或者自定义字体。
3. Web Bluetooth/Web USB直接通信
如果你的打印机支持蓝牙或USB连接,可以用浏览器的Web Bluetooth/Web USB API直接发送ESC/POS指令,不需要额外库。比如Web USB的示例:
async function printReceipt() { const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x04b8 }] }); // 替换为你的打印机厂商ID await device.open(); await device.selectConfiguration(1); await device.claimInterface(0); // 发送ESC/POS指令:初始化、居中、打印文本等 const commands = [ Buffer.from([0x1B, 0x40]), // 初始化打印机 Buffer.from('\x1B\x61\x01'), // 居中对齐 Buffer.from('alpha\n'), Buffer.from('Item Qty Price\n'), Buffer.from('abc 1 120\n'), Buffer.from('pqr 2 240\n'), Buffer.from('xyz 4 360\n'), Buffer.from([0x1D, 0x56, 0x01]) // 切纸 ]; for (const cmd of commands) { await device.transferOut(1, cmd); } await device.close(); } $("#print-receipt").on("click", printReceipt);
这个方案的优势是完全原生,不需要依赖任何第三方库,但需要打印机支持对应的通信方式,且浏览器版本较新。
内容的提问来源于stack exchange,提问作者Atharva Kale
相关产品推荐
相关产品推荐

