更新记录
1.0.0(2026-04-17)
BLE蓝牙打印机UTS插件(uni-app x),基于ESC/POS协议,兼容58mm便携式热敏打印机
平台兼容性
uni-app x(4.0)
| Chrome | Safari | Android | iOS | 鸿蒙 | 微信小程序 |
|---|---|---|---|---|---|
| - | - | 8.0 | - | - | √ |
BtPrinter - BLE 蓝牙打印机插件使用说明
适用于 uni-app x (Android),基于 ESC/POS 协议,兼容 58mm 便携式热敏打印机 支持 58HB6 等主流蓝牙打印机型号
目录
1. 快速开始
1.1 安装
将 uni_modules/BtPrinter 目录放入项目的 uni_modules/ 下即可,无需额外配置。
1.2 导入
import BtPrinter from '@/uni_modules/BtPrinter/utssdk/index.uts'
1.3 最小使用示例
// 1. 初始化(会尝试自动重连上次设备)
BtPrinter.initPrinter()
// 2. 获取已配对设备列表
const devices = BtPrinter.getPairedDevices()
console.log('配对设备:', devices)
// 3. 连接打印机(传入 MAC 地址)
BtPrinter.connectPrinter('AA:BB:CC:DD:EE:FF')
// 4. 打印文本
BtPrinter.printTextLn('Hello, Printer!')
// 5. 切纸
BtPrinter.cutPaper()
2. 模块结构
BtPrinter/
├── package.json # uni_modules 配置
└── utssdk/
├── index.uts # 统一导出 + 类型定义
├── interface.uts # TypeScript 类型(导出接口)
└── app-android/
├── index.uts # 核心实现(蓝牙连接 + ESC/POS)
├── config.json # 插件配置
└── libs/
└── androidprintsdk.jar # 打印机厂商 SDK(已废弃,实际用纯 ESC/POS 实现)
核心设计
| 设计 | 说明 |
|---|---|
| 连接状态管理 | BtPrinterState 静态单例,跨页面保持连接不断开 |
| MAC 持久化 | SharedPreferences 存储上次连接的 MAC,重启后可自动重连 |
| 图片打印 | 纯 ESC/POS 光栅位图手动实现(GS v 0),JAR SDK 实际未使用 |
| 编码 | 文本使用 GBK 编码,二维码使用字符码值直接发送 |
3. API 清单
3.1 设备连接
| API | 参数 | 返回值 | 说明 |
|---|---|---|---|
initPrinter() |
— | void |
初始化,自动尝试重连上次设备 |
getPairedDevices() |
— | BleDevice[] |
获取已配对的蓝牙设备列表 |
connectPrinter(mac: string) |
MAC 地址 | boolean |
连接指定 MAC 的打印机 |
disconnectPrinter() |
— | void |
断开连接,清除 MAC 记录 |
isConnected() |
— | boolean |
检查连接状态(实时验证 socket) |
isBluetoothEnabled() |
— | boolean |
检查蓝牙是否开启 |
requestEnableBluetooth() |
— | void |
弹窗请求开启蓝牙 |
getConnectedMac() |
— | string \| null |
获取当前连接设备的 MAC |
3.2 基础打印
| API | 参数 | 说明 |
|---|---|---|
printerInit() |
— | 初始化打印机(ESC @) |
printText(text) |
文本 | 打印文本(GBK 编码) |
printTextLn(text) |
文本 | 打印文本 + 换行 |
printLine(text) |
文本 | printTextLn 的别名 |
feedPaper(lines) |
行数 | 走纸 N 行 |
cutPaper() |
— | 切纸 |
printEmptyLine(count) |
行数(默认1) | 打印空行 |
printSeparator(char) |
分隔符字符(默认 -) |
打印 32 字符分隔线 |
3.3 格式化
| API | 参数 | 说明 |
|---|---|---|
setBold(bold) |
true/false |
加粗开关 |
setFontSize(size) |
0=正常, 1=倍宽, 2=倍高, 3=倍宽高 | 设置字号 |
setAlign(align) |
0=左, 1=中, 2=右 | 设置对齐 |
3.4 二维码与条形码
| API | 参数 | 说明 |
|---|---|---|
printQR(data, moduleSize?, errorCorrection?) |
内容, 模块大小(1-16), 纠错等级 | 打印二维码 |
printQRCode(data, moduleSize?) |
内容, 模块大小 | printQR 的别名 |
printBarcode(data, type?) |
内容, 条码类型(默认0x41) | 打印条形码 |
3.5 图片打印
| API | 参数 | 说明 |
|---|---|---|
printImage(imagePath, width?, alignment?) |
本地路径, 宽度px(默认384), 对齐 | 打印本地图片 |
printImageBase64(base64Data, width?, alignment?) |
Base64字符串, 宽度px, 对齐 | 打印 Base64 图片 |
3.6 完整小票打印
| API | 参数 | 说明 |
|---|---|---|
printReceipt(data) |
ReceiptData 对象 |
打印商品小票 |
printParkingReceipt(data) |
ParkingReceiptData 对象 |
打印停车缴费单 |
4. 初始化与连接
4.1 完整连接流程
import BtPrinter from '@/uni_modules/BtPrinter/utssdk/index.uts'
export function connectToPrinter() {
// Step 1: 检查蓝牙状态
if (!BtPrinter.isBluetoothEnabled()) {
BtPrinter.requestEnableBluetooth()
// 用户同意后再执行后续步骤
return
}
// Step 2: 初始化(推荐每次页面加载时调用)
BtPrinter.initPrinter()
// Step 3: 检查是否已连接(initPrinter 会自动重连)
if (BtPrinter.isConnected()) {
console.log('已连接:', BtPrinter.getConnectedMac())
return
}
// Step 4: 获取配对设备列表让用户选择
const devices = BtPrinter.getPairedDevices()
console.log('配对设备:', devices)
// devices 示例: [{ deviceId: 'AA:BB:CC:DD:EE:FF', name: '58HB6-BT', RSSI: -50 }]
// Step 5: 连接用户选择的设备
const success = BtPrinter.connectPrinter('AA:BB:CC:DD:EE:FF')
if (success) {
console.log('连接成功')
} else {
console.log('连接失败,请确认打印机已开启')
}
}
4.2 断开连接
BtPrinter.disconnectPrinter()
// 断开后 SharedPreferences 中的 MAC 记录也会清除
4.3 连接状态说明
initPrinter()每次调用会检查并尝试重连上次 MAC 设备- 连接成功后 MAC 自动保存到
SharedPreferences - 下次打开 APP 时调用
initPrinter()会自动重连,无需用户手动选择 - 页面切换不会断开连接(状态保存在静态内存中)
5. 基础打印
// 初始化
BtPrinter.printerInit()
// 打印多行
BtPrinter.printTextLn('第1行')
BtPrinter.printTextLn('第2行')
BtPrinter.printTextLn('第3行')
// 走纸3行
BtPrinter.feedPaper(3)
// 切纸
BtPrinter.cutPaper()
6. 格式化打印
BtPrinter.printerInit()
// 居中大标题
BtPrinter.setAlign(1) // 居中
BtPrinter.setBold(true) // 加粗
BtPrinter.setFontSize(3) // 双倍宽高
BtPrinter.printTextLn('欢迎光临')
BtPrinter.setBold(false)
BtPrinter.setFontSize(0) // 恢复正常
BtPrinter.printEmptyLine(1)
// 左对齐普通文本
BtPrinter.setAlign(0)
BtPrinter.printTextLn('商品名称 数量 价格')
BtPrinter.printSeparator('-')
// 右对齐金额
BtPrinter.setAlign(2)
BtPrinter.printTextLn('总计: ¥128.00')
BtPrinter.cutPaper()
7. 二维码与条形码
二维码
// 打印二维码(居中)
BtPrinter.setAlign(1)
BtPrinter.printQR('https://example.com/pay?id=123456', 8, 49)
// 参数1: 二维码内容
// 参数2: 模块大小 1-16(推荐: 小=3, 中=6, 大=8, 超大=12)
// 参数3: 纠错等级 48=L, 49=M, 50=Q, 51=H(默认M)
条形码
BtPrinter.printBarcode('1234567890', 0x41)
// 0x41 = CODE_39,其他类型参考 ESC/POS 标准
8. 图片打印
从本地文件打印
// 打印 Logo(本地路径,居中,宽度 256px)
BtPrinter.printImage('/sdcard/logo.png', 256, 1)
从 Base64 打印
// 打印 Base64 编码的图片
const base64Str = 'iVBORw0KGgoAAAANSUhEUgAAAAE...'
BtPrinter.printImageBase64(base64Str, 384, 1)
// Base64 中的 data:image/xxx;base64, 前缀会自动去除
图片规格:58mm 打印机每行最大 384 像素,建议图片宽度设为 384px 或更小以获得最佳效果。
9. 完整小票打印
const receipt: ReceiptData = {
title: '购物小票',
items: [
{ name: '矿泉水', qty: '2', price: '¥4.00' },
{ name: '方便面', qty: '1', price: '¥5.50' },
{ name: '火腿肠', qty: '3', price: '¥12.00' },
],
total: '¥21.50',
qrData: 'https://example.com/order/12345'
}
// 一行代码打印完整小票
BtPrinter.printReceipt(receipt)
效果预览:
════════════════════════
购物小票
════════════════════════
矿泉水
x2 ¥4.00
方便面
x1 ¥5.50
火腿肠
x3 ¥12.00
--------------------------------
合计: ¥21.50
扫码查看详情
[二维码]
🔖
10. 停车缴费单打印
const parking: ParkingReceiptData = {
platformName: '铼停智慧停车',
receiptTitle: '缴费单',
plateNumber: '渝B66688',
parkingRoad: '长乐路1 - 21311',
entryTime: '2026-03-18 16:20:55',
owedAmount: '10.48',
owedCount: '1',
qrData: 'https://pay.example.com?plate=渝B66688',
rate: '每分钟 0.01 元',
servicePhone: '0755-6977333',
qrSize: 10,
}
// 一行代码打印停车单
BtPrinter.printParkingReceipt(parking)
ParkingReceiptData 完整字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
platformName |
string | ✅ | 平台名称,如 "铼停智慧停车" |
receiptTitle |
string | ✅ | 单据标题,如 "缴费单" |
plateNumber |
string | ✅ | 车牌号,如 "渝B66688" |
parkingRoad |
string | ✅ | 停车路段 |
entryTime |
string | ✅ | 驶入时间(格式灵活) |
owedAmount |
string | ✅ | 历史欠费金额,如 "10.48" |
owedCount |
string | ✅ | 未缴笔数,如 "1" |
qrData |
string | ✅ | 支付二维码 URL/内容 |
printTime |
string | ❌ | 打印时间,默认当前时间 |
rate |
string | ❌ | 费率说明,如 "每分钟 0.01 元" |
servicePhone |
string | ❌ | 客服电话,如 "0755-6977333" |
qrSize |
number | ❌ | 二维码大小 1-16,默认 10 |
logoPath |
string | ❌ | Logo 本地路径 |
11. 权限说明
插件已通过 config.json 声明以下 Android 权限:
| 权限 | 用途 |
|---|---|
BLUETOOTH |
蓝牙基本通信 |
BLUETOOTH_ADMIN |
蓝牙设备扫描/管理 |
BLUETOOTH_CONNECT (Android 12+) |
连接已配对蓝牙设备 |
BLUETOOTH_SCAN (Android 12+) |
扫描周围蓝牙设备 |
BLUETOOTH_PRIVILEGED |
系统级蓝牙操作(厂商适配) |
ACCESS_FINE_LOCATION |
位置权限(扫描蓝牙需要,Android 6.0+) |
READ_EXTERNAL_STORAGE |
读取本地图片文件 |
Android 12+ 权限处理
Android 12(API 31)起蓝牙权限变更,initPrinter() 中已内置 requestBluetoothPermissions() 处理。
如需手动请求:
// 在 manifest 中声明后,Android 会在需要时自动弹窗请求
BtPrinter.requestEnableBluetooth()
12. ESC/POS 命令速查
| 命令 | 十六进制 | 说明 |
|---|---|---|
printerInit |
1B 40 |
初始化打印机 |
| 换行 | 0A |
打印 + 换行 |
| 加粗开 | 1B 45 01 |
ESC E 1 |
| 加粗关 | 1B 45 00 |
ESC E 0 |
| 居中 | 1B 61 01 |
ESC a 1 |
| 左对齐 | 1B 61 00 |
ESC a 0 |
| 右对齐 | 1B 61 02 |
ESC a 2 |
| 切纸 | 1D 56 01 |
GS V 1 |
| 走纸 N 行 | 0A × N |
LF |
13. 常见问题
Q1: 连接成功但打印不出内容?
- 确认打印机有纸、有电
- 确认文本编码为 GBK(非 UTF-8)
- 调用
printerInit()初始化打印机后再打印
Q2: 打印乱码?
文本默认使用 GBK 编码。若打印机不支持 GBK,可修改源码 index.uts 中的 Charset.forName("GBK") 为其他编码(如 UTF-8)。
Q3: 页面切换后连接丢失?
不会丢失。连接状态保存在 BtPrinterState 静态内存中,跨页面保持。如需在 APP 重启后恢复连接,调用 initPrinter() 即可。
Q4: 自动重连失败?
- 检查 SharedPreferences 中是否存有 MAC:
BtPrinter.loadLastMac() - 确认蓝牙开关已开启:
BtPrinter.isBluetoothEnabled() - 确认打印机已开机并在范围内
- 尝试重新配对:先在系统蓝牙设置中删除配对记录,重新配对后再试
Q5: 图片打印模糊?
- 图片宽度建议设为 384px(58mm 满宽)
- 图片内容对比度要高(深色背景、浅色文字效果差)
- 使用
printImageBase64打印高分辨率截图效果更好
Q6: 二维码无法扫描?
- 减小
moduleSize值(推荐 6-10) - 确认纠错等级不太低(推荐 M=49)
- 二维码内容不要太长
文档生成时间: 2026-04-17 适用版本: BtPrinter v1.0.0

收藏人数:
购买源码授权版(
试用
赞赏(0)
下载 0
赞赏 0
下载 11573281
赞赏 1905
赞赏
京公网安备:11010802035340号