Taro Bluetooth Print
轻量级、高性能的 Taro 蓝牙打印库
支持图片、二维码、断点续传与弱网适配
✨ 特性
- 🚀 高性能 - 直接字节缓冲区操作,服务缓存优化
- 📱 跨平台 - 基于 Taro 蓝牙 API,支持微信小程序、H5、React Native 等
- 🎨 简洁 API - 链式调用,易于使用
- 🖼️ 图片打印 - 内置 Floyd-Steinberg 抖动算法,高质量图片转换
- 📲 二维码支持 - 原生 ESC/POS 二维码指令
- 📊 条码支持 - 支持 Code128、Code39、EAN-13、EAN-8、UPC-A 格式
- 🔄 断点续传 - 支持打印任务暂停/恢复/取消
- 📶 弱网适配 - 智能分片与重试机制,自适应传输参数
- 📊 进度追踪 - 实时打印进度事件
- 💾 离线缓存 - 断网时自动缓存,重连后自动同步
- 📋 打印队列 - 优先级排序,失败自动重试
- 📝 模板引擎 - 内置收据和标签模板
- 🔍 打印预览 - ESC/POS 命令渲染为图像预览
- 🌐 Web Bluetooth - 支持 H5 环境的 Web Bluetooth API
- 💓 连接稳定 - 心跳检测和自动重连机制
- 🛠️ TypeScript - 完整的类型定义和 JSDoc 文档
- 🧪 高测试覆盖 - 76%+ 代码覆盖率
📦 安装
npm install taro-bluetooth-print
yarn add taro-bluetooth-print
pnpm add taro-bluetooth-print
🚀 快速开始
基础示例
import { BluetoothPrinter } from 'taro-bluetooth-print';
const printer = new BluetoothPrinter();
async function printReceipt(deviceId: string) {
try {
await printer.connect(deviceId);
await printer
.text('=== 欢迎光临 ===', 'GBK')
.feed()
.text('商品A x1 ¥10.00')
.text('商品B x2 ¥20.00')
.feed()
.text('------------------------')
.text('合计: ¥30.00')
.feed(2)
.qr('https://example.com', { size: 8 })
.feed(2)
.cut()
.print();
console.log('打印成功!');
} catch (error) {
console.error('打印失败:', error);
} finally {
await printer.disconnect();
}
}
监听打印进度
import { BluetoothPrinter, LogLevel, Logger } from 'taro-bluetooth-print';
Logger.setLevel(LogLevel.DEBUG);
const printer = new BluetoothPrinter();
printer.on('progress', ({ sent, total }) => {
const percent = ((sent / total) * 100).toFixed(1);
console.log(`打印进度: ${percent}%`);
});
printer.on('error', error => {
console.error('打印错误:', error.code, error.message);
});
printer.on('print-complete', () => {
console.log('打印完成!');
});
await printer.connect(deviceId);
await printer.text('Hello').feed().print();
断点续传示例
const printer = new BluetoothPrinter();
await printer.connect(deviceId);
printer.text('第1页内容...').feed(10).text('第2页内容...').feed(10).text('第3页内容...');
const printPromise = printer.print();
setTimeout(() => {
printer.pause();
console.log('已暂停,剩余:', printer.remaining(), '字节');
}, 5000);
setTimeout(async () => {
await printer.resume();
console.log('已恢复打印');
}, 10000);
await printPromise;
图片打印
import Taro from '@tarojs/taro';
const canvas = Taro.createCanvasContext('myCanvas');
Taro.canvasGetImageData({
canvasId: 'myCanvas',
x: 0,
y: 0,
width: 200,
height: 100,
success: res => {
const imageData = new Uint8Array(res.data);
printer.image(imageData, res.width, res.height).feed(2).print();
},
});
弱网适配
printer.setOptions({
chunkSize: 20,
delay: 30,
retries: 5,
});
await printer.text('测试内容').print();
文本格式化 (v2.2+)
await printer
.align('center')
.setSize(2, 2)
.setBold(true)
.text('大标题')
.resetStyle()
.feed()
.align('left')
.text('正常文本')
.print();
条码打印 (v2.2+)
await printer.text('商品条码:').barcode('6901234567890', 'EAN13', { height: 80 }).feed(2).print();
设备管理 (v2.2+)
import { DeviceManager } from 'taro-bluetooth-print';
const deviceManager = new DeviceManager();
deviceManager.on('device-found', device => {
console.log('发现设备:', device.name, device.deviceId);
});
await deviceManager.startScan({ timeout: 10000 });
const devices = deviceManager.getDiscoveredDevices();
打印队列 (v2.2+)
import { PrintQueue } from 'taro-bluetooth-print';
const queue = new PrintQueue({ maxSize: 100 });
queue.add(printData, { priority: 'HIGH' });
queue.on('job-completed', job => {
console.log('任务完成:', job.id);
});
离线缓存 (v2.2+)
import { OfflineCache } from 'taro-bluetooth-print';
const cache = new OfflineCache();
await cache.save({ id: 'job-1', data: printData });
await cache.sync();
📚 文档
完整文档请访问:https://agions.github.io/taro-bluetooth-print/
🎯 核心 API
BluetoothPrinter
connect(deviceId) | 连接蓝牙设备 | Promise<this> |
disconnect() | 断开连接 | Promise<void> |
text(content, encoding?) | 添加文本 | this |
feed(lines?) | 换行 | this |
image(data, width, height) | 打印图片 | this |
qr(content, options?) | 打印二维码 | this |
barcode(content, format, options?) | 打印条码 (v2.2+) | this |
align(alignment) | 设置对齐 (v2.2+) | this |
setSize(width, height) | 设置字体大小 (v2.2+) | this |
setBold(enabled) | 设置粗体 (v2.2+) | this |
setUnderline(enabled) | 设置下划线 (v2.2+) | this |
resetStyle() | 重置样式 (v2.2+) | this |
cut() | 切纸 | this |
setOptions(options) | 设置适配器参数 | this |
print() | 发送打印 | Promise<void> |
pause() | 暂停打印 | void |
resume() | 恢复打印 | Promise<void> |
cancel() | 取消打印 | void |
remaining() | 获取剩余字节数 | number |
qr(content, options?) | 打印二维码 | this |
cut() | 切纸 | this |
setOptions(options) | 设置适配器参数 | this |
print() | 发送打印 | Promise<void> |
pause() | 暂停打印 | void |
resume() | 恢复打印 | Promise<void> |
cancel() | 取消打印 | void |
remaining() | 获取剩余字节数 | number |
事件
state-change | PrinterState | 连接状态变化 |
progress | { sent, total } | 打印进度 |
error | BluetoothPrintError | 错误事件 |
connected | string (deviceId) | 已连接 |
disconnected | string (deviceId) | 已断开 |
print-complete | void | 打印完成 |
🔧 配置选项
interface IAdapterOptions {
chunkSize?: number;
delay?: number;
retries?: number;
}
interface IQrOptions {
model?: 1 | 2;
size?: number;
errorCorrection?: 'L' | 'M' | 'Q' | 'H';
}
🌐 平台支持
| 微信小程序 | ✅ | 完全支持 |
| H5 | ✅ | 需要浏览器支持 Web Bluetooth |
| React Native | ✅ | 通过 Taro RN |
| 支付宝小程序 | ✅ | 完全支持 |
| 百度小程序 | ✅ | 完全支持 |
| 字节跳动小程序 | ✅ | 完全支持(抖音、头条等) |
🏗️ 架构设计
┌─────────────────────────────────────┐
│ BluetoothPrinter (Core) │
│ - 连接管理 │
│ - 打印队列 │
│ - 事件系统 │
│ - 断点续传 │
└────────┬────────────────┬───────────┘
│ │
┌────▼─────┐ ┌────▼──────┐
│ Adapter │ │ Driver │
│ 层 │ │ 层 │
└──────────┘ └───────────┘
│ │
┌────▼─────┐ ┌────▼──────┐
│Taro │ │ESC/POS │
│Adapter │ │Driver │
└──────────┘ └───────────┘
- Core 层: 核心业务逻辑
- Adapter 层: 平台适配(Taro、Web Bluetooth 等)
- Driver 层: 打印机协议(ESC/POS、TSPL 等)
🤝 贡献
欢迎贡献!请查看 贡献指南。
开发设置
git clone https://github.com/agions/taro-bluetooth-print.git
cd taro-bluetooth-print
npm install
npm test
npm run build
npm run docs:dev
📄 许可证
MIT © Agions
🙏 致谢
感谢所有贡献者的支持!
Made with ❤️ by Agions