1. 需求背景
前段时间公司项目需要在商户电脑上调用商户自己的热敏打印机打印商户的客户的购物小票(如下图),但FE的纯js显然不能实现该功能,因此采用nw来实现。
当时的项目已有一个web页面,因此在nw里将已有的html页面嵌入了iframe,与nw内实现的打印功能通过postMessage通信。但本篇重点介绍如何打印小票,这些通信以及nw的其他使用就不再占用篇幅了。
2. 功能点
- 获取用户打印机列表,让用户选择当前使用的打印机
- 按照格式打印所需内容
3. 最终代码使用
调用封装后的功能:
const printer = require('./printer.js')
function getPrinterList() {
const list = printer.getPrinterList()
const res = []
list.forEach(item => res.push(item.name))
return res
}
// 获取当前打印机列表
const printerList = getPrinterList()
// 暂定使用打印机为第一个
const printerName = printerList[0]
// mock订单数据
const mockData = { id: 001, delivery_way: '外送', deliver_time: '立即送达', sku_detail: [{ quantity: 10, sku_name: '火米饼套餐', price: 20 }], description: '多放火贝 火火火火', invoiced: '', package_fee: 1, deliver_fee: 10, total_price: 31, receiver_address: '火星1区101路1号', receiver_name: '火星人', receiver_phone: 00001, create_time: '0001-01-01', tagg_shop_name: '火星1号商店'}
// 封装打印订单函数,传参为打印机名称和订单数据
function printOrderRecive(name = '', data = {}) {
const Buffer = require('./escpos.js')
let buffer = new Buffer()
buffer = buffer.setLineHeight(70)
.setTextSize(2).setLineHeight(50).setText(data.id, 'center')
.setTextSize(1).setLineHeight(100).setText(`${data.delivery_way} ${data.deliver_time}`, 'center')
.setLineHeight(70).setDecLine()
.setBoldOn()
.setLineHeight(70)
data.sku_detail && data.sku_detail.forEach(item => {
buffer = buffer.setThreeCol(item.quantity, item.sku_name, `¥${item.price}`) })
buffer = buffer.setLine()
.setLineHeight(100).setText(`备注:${data.description}`).setBoldOff()
.setLineHeight(50).setDecLine()
.setLineHeight(70)
.setTwoCol('开具发票', data.invoiced)
.setTwoCol('包装费', `¥${data.package_fee}`)
.setTwoCol('配送费', `¥${data.deliver_fee}`)
.setLineHeight(50)
.setDecLine()
.setBoldOn().setText(`合计:¥${data.total_price} `, 'right').setBoldOff()
.setDecLine()
.setLineHeight(70)
.setText(`送货地址:${data.receiver_address}`)
.setText(`客户:${data.receiver_name} ${data.receiver_phone}`)
.setDecLine()
.setText(`下单时间: ${data.create_time}`, 'center')
.setLine(2)
.setBoldOn().setText(`${data.tagg_shop_name} \n \n`, 'center').setBoldOff()
.setLine(2)
.cut()
.getBuffer()
printer.print(name, buffer)
}
// 调用打印功能
printOrderRecive(printerName, mockData)
使用前准备:
克隆github代码到本地,使用 npm install
安装package.json中除了printer之外的其他安装包(因为priner包在被nw使用时,需要做特殊处理,且处理环境比较复杂,因此直接将处理好的printer包和项目一起上传到了github,虽然项目大了一些,但比较方便操作)
4. 打印功能的主要文件
|-- command.js --------- esc/pos常用指令集,十六进制数字,底层指令
|-- escpos.js ---------- 常用打印函数的封装,对外的函数,对command进行组合,并返回buffer
|-- printer.js --------- 打印机函数的封装,对外的函数,调用了node-printer模块
|-- example.js --------- 调用打印小票样例,即上面最终代码使用中的样例,对printer.js的调用
|-- index.html --------- 主文件,包括了iframe自适应、iframe与nw的通信、example.js的调用等
5. 项目地址
主要使用了node-printer模块并加以封装。