在 UniApp 中针对 PDA 打印机(多数为 ESC/POS 协议),要做不同排版样式,主要有两条思路:
-
原生 ESC/POS 控制指令
-
先在客户端生成图片(Canvas/HTML → Bitmap),再下发给打印机
下面分别给出方案和示例代码。
1. 原生 ESC/POS 控制指令
ESC/POS 协议通过一系列控制码,实现对齐、加粗、放大、表格(通过字符填充)等功能。
在 UniApp 里你可直接拼接二进制数组,然后通过蓝牙/USB 写入打印机。
1.1 常用控制码
功能 | 指令(Hex) | 说明 |
---|---|---|
初始化 | 1B 40 | 重置打印机 |
左对齐 | 1B 61 00 | |
居中 | 1B 61 01 | |
右对齐 | 1B 61 02 | |
加粗开/关 | 1B 45 01 / 1B 45 00 | |
字体放大 | 1D 21 11 | 宽高各放大两倍 |
换行 | 0A |
1.2 打印“姓名/年龄”并居中、表格排版示例
// 引入蓝牙或 USB 连接模块,以下只示例数据拼装
function buildPrintData(name, age) {
const encoder = new TextEncoder();
let cmds = [];
// 初始化
cmds.push(...[0x1B, 0x40]);
// 标题居中放大加粗
cmds.push(...[0x1B, 0x61, 0x01]); // 居中
cmds.push(...[0x1B, 0x45, 0x01]); // 加粗
cmds.push(...[0x1D, 0x21, 0x11]); // 放大
cmds.push(...encoder.encode(`个人信息\n`));
// 恢复字体、左对齐
cmds.push(...[0x1B, 0x45, 0x00]);
cmds.push(...[0x1D, 0x21, 0x00]);
cmds.push(...[0x1B, 0x61, 0x00]); // 左对齐
// 模拟两列表格:Key(10字符宽) + Value
const pad = (str, len) => str + ' '.repeat(len - str.length);
const line1 = pad('姓名', 10) + ': ' + name + '\n';
const line2 = pad('年龄', 10) + ': ' + age + '\n';
cmds.push(...encoder.encode(line1 + line2));
// 换两行并切刀
cmds.push(...[0x0A, 0x0A]);
cmds.push(...[0x1D, 0x56, 0x00]);
return new Uint8Array(cmds);
}
// 调用示例
const printData = buildPrintData(this.name, this.age);
// 通过 uni Bluetooth/USB 模块将 printData 发给打印机
要点:
pad
函数做了简单的固定宽度对齐;控制码直接拼到字节数组里,最后发给打印机;
“表格”本质是用等宽字符+空格模拟。
2. Canvas/HTML → Bitmap 打印
有些 PDA 打印机也支持打印位图(图片)模式。思路是:
-
用 Canvas(或隐藏的
uni-webview
+ HTML/CSS)渲染出你想要的排版 -
转成 Base64 图片或二进制 Bitmap
-
用 ESC/POS 图片指令(
1D 76 30 m xL xH yL yH data…
)下发
2.1 Canvas 示例(伪代码)
<canvas id="label" :width="384" :height="200"></canvas>
// 在页面 mounted 后
const canvas = uni.createCanvasContext('label', this);
canvas.setTextAlign('center');
canvas.setFontSize(24);
canvas.fillText('个人信息', 192, 30);
canvas.setFontSize(18);
canvas.setTextAlign('left');
canvas.fillText('姓名:' + this.name, 10, 70);
canvas.fillText('年龄:' + this.age, 10, 100);
// 可以画线、画矩形模拟表格
canvas.setStrokeStyle('#000');
canvas.strokeRect(5, 55, 374, 50);
canvas.draw(false, () => {
// 生成 base64
uni.canvasToTempFilePath({
canvasId: 'label',
success(res) {
const base64 = res.tempFilePath; // 拿到临时路径
// 读取成二进制并拼接 ESC/POS 图片指令后发给打印机
// ...
}
}, this);
});
优点:
完全用视觉方式布局,自由度高
支持任意行距、线框、圆角、渐变……
缺点:
实现图片转二进制、分片传输逻辑更复杂
执行较慢,需注意分片大小与打印机缓存
3. 第三方库/插件
-
esc-pos-encoder:JS 版 ESC/POS 编码器,封装了常用指令。
-
react-native-esc-pos-printer:可借鉴其指令拼接思路。
它们能帮你用更友好的 API 来生成指令,比如:
import EscPosEncoder from 'esc-pos-encoder';
const encoder = new EscPosEncoder();
encoder.initialize()
.align('center')
.bold()
.size(2, 2)
.text('个人信息')
.newline()
.size(1, 1)
.align('left')
.text('姓名:' + this.name)
.newline()
.text('年龄:' + this.age)
.newline(2)
.cut();
const printData = encoder.encode(); // Uint8Array
小结
-
简单文字/表格:直接用 ESC/POS 控制码+等宽字符填充
-
复杂布局:Canvas/HTML → Bitmap → 打印
-
提升开发效率:引入
esc-pos-encoder
等库
任选其一,结合你项目对「布局自由度」和「实现难度」的取舍即可。