# yun2-printers
**Repository Path**: iYUN2/yun2-printers
## Basic Information
- **Project Name**: yun2-printers
- **Description**: 小票打印机`云打印`旨在抹平不同云打印厂商的`api`差异,用一套代码适应不同的厂家。开箱即用对接Wi-Fi、4G/5G的票据打印机,当你更换云打印设备到更换其它厂家的设备或者型号时,几乎不用更改代码。配合`uniCloud`使用,打印机信息和打印任务将存储在云数据库,支持同步打印、异步打印队列。
- **Primary Language**: JavaScript
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 3
- **Forks**: 1
- **Created**: 2022-08-17
- **Last Updated**: 2024-11-20
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
## LICENSE:Apache License
> #### [点击查看 Apache License ](https://gitee.com/mmsen/yun2-printers/blob/master/LICENSE)
联系方式:
QQ:183764371
VX:mulin1004
## 小票打印机云打印封装(支持佳博、飞鹅、优声云)
小票打印机`云打印`旨在抹平不同云打印厂商的`api`差异,用一套代码适应不同的厂家。开箱即用对接Wi-Fi、4G/5G的票据打印机,当你更换云打印设备到更换其它厂家的设备或者型号时,几乎不用更改代码。
配合`uniCloud`使用,打印机信息和打印任务将存储在云数据库,支持同步打印、异步打印队列。
使用统一数据类型可以自定义你的打印模版,并自动适应以下厂家的云票据打印设备。
支持厂商列表
- [x] 广州佳博
- [https://cp.poscom.cn/](https://cp.poscom.cn/)
- [https://dev.poscom.cn/](https://dev.poscom.cn/)
- [x] 广州飞鹅
- [https://admin.feieyun.com/login.php](https://admin.feieyun.com/login.php)
- [x] 成都优声云
- [https://www.ushengyun.com/open.html](https://www.ushengyun.com/open.html)
如果你有需要对接其它厂家设备的需求,请与我联系,QQ:183654371
## 插件下载地址 [https://ext.dcloud.net.cn/plugin?id=9184](https://ext.dcloud.net.cn/plugin?id=9184)
## 统一数据类型
- [基本用法](#基本用法)
- [分联打印index](#分联打印index)
- [条码](#条码barCode)
- [二维码](#二维码qrCode)
- [文本](#文本text)
- [多列文本](#文本text)
- [一行两列文本](#一行两列文本)
- [一行三列文本](#一行三列文本)
- [一行四列文本](#一行四列文本)
- [语音](#语音voice)
- [图片](#图片image)
- [字符作为分割线](#字符作为分割线div)
- [换行](#换行br)
- [切纸](#切纸cut)
- [LOGO](#LOGO)
- [异步打印队列](#异步打印队列)
- [添加到打印队列](#添加到打印队列)
- [处理打印队列](#处理打印队列)
## 基本用法
```js
const PrinterManager = require('yun2-printers')
//采用管理配置参数
const createConfig = require('uni-config-center')
const configData = createConfig({ pluginId: 'yun2-printers' }).config()
// 初始化
PrinterManager.init(configData)
//在uniCloud体系下,配置参数集中放置在`uni-config-center`内`yun2-printers`的config.json内
//config.json内容
{
"jiabo":{
"memberCode" : "",
"apiKey" : ""
},
"feie":{
"user" : "",
"key" : ""
},
"usheng":{
"appid":"",
"appsecret":""
},
"max_task":10,
"debug":false
}
//添加打印机,
//通常设备信息在打印机底部,没有key可以留空或不填写,paper为必填项
//第二个参数为数组时,可以同时添加多个打印机(仅飞鹅支持,佳博不支持)
const {id, ids} = await PrinterManager.addPrinter(PrinterManager.JIABO, {
deviceID:'',//打印机设备编号
key:'',//打印设备秘钥,部分厂家没有该项,不同的厂家叫法不同
name:'一楼大厅收银',
paper:0,//0代表58mm纸张宽度 1代表80mm纸张宽度
})
//获取打印机
//id为数据表`printers`的_id
const printer = await PrinterManager.getPrinter(id)
//如果不搭配`uniCloud`使用,也可以传入打印机信息创建打印机对象
const config = {
factory: PrinterManager.JIABO
deviceID:'',
key:'',
//覆盖PrinterManager.init()中 jiabo的参数设置
jiabo:{
memberCode:''
apiKey:''
}
}
const printer = await PrinterManager.getPrinter(config)
//执行打印任务, data 必须照格式生成
const data = [
{type:'barCode', mode:1, height:20, position:2,value:'1223213112'},
{type:'qrCode', align:'C', size:10, error:'H', value:'https://yun2.net'},
{type:'text', align:'L', bold:1, wsize:1 ,hsize:1, reverse:1, underline:0, value:'我是一行文字'},
{type:'text', value:['我是左边文字','我是右边文字']},
{type:'text', value:['左边文字','中间文字','右边文字']},
{type:'text', value:['第一列','第二列','第三列','第四列']},
{type:'image', align:'L', value:'http://图片网址'},
{type:'br'},
{type:'logo'},
{type:'br'},
{type:'br'},
{type:'cut'}
]
const res = await printer.print( data )
```
### 统一打印数据
统一数据格式类似一个打印中间件,开发人员将要打印的数据输出成`统一打印数据`格式,中间件负责根据打印机的厂家和纸张宽度翻译成该厂家打印机支持的自定义模版格式,以达到一套代码适应多个厂家的目的。
### 分联打印index
> # 注意:仅优声云打印设备支持
打印开头显示“第1联”,“第2联”
> #### `value`
> 条码类型
> |厂家|支持|
> |--|--|
> |佳博|否|
> |飞鹅|否|
> |优声|是 1-9 之间的任何一个数字|
value为实际的联数,支持[1,9]区间整数
```js
{
type:"index",
value:1
}
```
### 条码barCode
> #### `mode `
> 条码类型
> |厂家|支持|
> |--|--|
> |佳博|1-7|
> |飞鹅|20-21|
> |优声|40-42|
>- 1:UPC-A
>
> UPC-A码用于通用商品,是美国均匀码理事会制定的一种商品条码,主要在美国及加拿大使用,也是适用范围最广的一种UPC码。UPC-A码是定长码,支持的字符集为0-9数字,只能表示12位数字(1位系统符,5位制造商代码,5位产品代码,1位校验码)。UPC-A商品条码符号从左至右,依次是起始符、左侧数据符、中间分隔符、右侧数据符、校验符、终止符,如图。UPC-A码左、右侧空白区最小宽度均为9个模块宽,其它结构与EAN-13商品条码相同。
>- 2:JAN13(EAN13)
>
> EAN-13 是欧洲版本的通用商品代码 (UPC (A))。EAN-13 和 UPC (A) 之间的区别是 EAN-13 使用 13位数编码,第 13 位与一个 UPC (A) 符号左边六位数的样式相同。第 13 位数与第 12 位数共同表示国家/地区代码。可以向主条码中添加两位数或五位数(可选)。此数字是为出版物和期刊而设计的,作为附加条码显示在主条码右侧。ISSN(国际标准期刊编号)是JAN13的子集,它带有国家代码 977 和两位附加代码。两位的附加代码包含发行号。例如,一月 = 01,二月 = 02
>- 3:JAN8(EAN8)
>
> 使用八位数编码,包括两个国家代码数位、五个数据位和一个检查位。在条码向导中,您必须输入七位数,第八位数(或说检查位)将自动生成。可以向主条码中添加两位数或五位数(可选)。此数字是为出版物和期刊而设计的,作为附加条码显示在主条码右侧。
>- 4:CODE39
>
> Code 39,又称为"Code 3 of 9",是非零售市场中最常用的格式,用于盘存和跟踪。Code 39码编码规则简单,误码率低、所能表示字符多等特点。此条码广泛应用于制造业、军事和医疗保健行业中。这种格式离散而且长度可变,接受以下 44 个字符:`0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ-.*$/+%`及“空格”
>- 5:ITF
>
> ITF条码,又称交叉二五条码,主要用于运输包装,是印刷条件较差,不允许印刷EAN-13和UPC-A条码时应选用的一种条码。ITF条码是有别于EAN、UPC条码的另一种形式的条码。在商品运输包装上使用的主要是14位数字字符代表组成的ITF-14条码。
>- 6:CODABAR
>
> Codabar又称库德巴码,可表示数字和字母信息,通常在图书馆、医疗卫生和航空包裹等行业中使用。这种格式的长度是可变的,允许使用` 0123456789-$:/.+ABCD `这20 个字符进行编码:。Codabar 信息的起始和结束字符必须为 A、B、C 或 D。
>
>- 7:CODE128B
>
> Code 128 是一种长度可变、高密度、字母和数字混和使用的格式,广泛应用在企业内部管理、生产流程、物流控制系统方面
>
>- 20:数字字母混合条形码,最多支持14位数字大写字母混合
>
>- 21:最多支持22位纯数字条码
>
>- 40:CODE128A
>
>- 41:CODE128B
>
>- 42:CODE128C
>
> |厂家|支持|
> |--|--|
> |佳博|1-7|
> |飞鹅|20-21|
> |优声|40-42|
> #### `height`
>
> 点位计算,范围[1, 255]
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
> #### `position`
> HRI字符位置
>
> 0: 不打印,
>
> 1: 条码上方,
>
> 2: 条码下方,
>
> 3: 条码上、下方都打印
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
条码生成
```js
{
type:'barCode',
mode:1,
height:20,
position:2,
value:'123424234243'
}
```
### 二维码qrCode
> ##### 默认:居中,尺寸取值9,纠错等级L
> ##### 佳博:一个订单可以打印多个二维码
> ##### 飞鹅:一个订单可以只可以打印一个二维码
> #### `align`
> 对齐 大小写均可
>
> L: 左对齐
>
> C: 居中
>
> R: 右对齐
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
> #### `size `
> 尺寸,范围[1, 16]
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
> #### `error `
> 纠错等级
>
> l: 纠错等级l(字母L的小写,不是数字1)
>
> m: 纠错等级m
>
> q: 纠错等级Q
>
> h: 纠错等级H
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
```js
{
type:'qrCode',
align:'C',
size:10,
error:'H',
value:'https://yun2.net'
}
```
### 文本text
一个中文字符占两个英文字符的位置,中文简称“中”,英文简称“英”
> |厂家|文本字数|
> |--|--|
> |佳博|58mm:中16个或英32个
80mm:共中24个或英48个|
> |飞鹅|58mm:共16个或英32个
80mm:共中24个或英48个|
> |优声|58mm:共16个或英32个
80mm:共中24个或英48个|
> #### 默认:左对齐,不加粗,尺寸0,不反色,无下划线
> #### `align`
> 对齐 大小写均可
>
> L: 左对齐
>
> C: 居中
>
> R: 右对齐
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|是|
> |优声|是|
> #### `bold`
> 加粗
>
> 0: 不加粗
>
> 1: 加粗
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|是|
> |优声|是|
> #### `wsize`
> 字体宽度,倍数计算,范围[0, 8]
> |厂家|支持|
> |--|--|
> |佳博|0-8|
> |飞鹅|0-1|
> |优声|0-2|
> #### `hsize`
> 字体宽度,倍数计算,范围[0, 8]
> |厂家|支持|
> |--|--|
> |佳博|0-8|
> |飞鹅|0-1|
> |优声|0-2|
> #### `reverse`
> 0: 不反显(黑字白底)
>
> 1: 反显(黑底白字)
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
> #### `underline`
> 0: 无下划线
>
> 1: 有下划线
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
```js
{
type:'text',
align:'L',
bold:1,
wsize:1,
hsize:1,
reverse:1,
underline:0,
value:'我是一行文字'
}
```
### 多列文本
##### 一行两列文本
> |厂家|第一列字数|第二列字数|
> |--|--|--|
> |佳博|58mm:中10,英21
80mm:中15,英31|58mm:中5,英10
80mm:中8,英16|
> |飞鹅|58mm:中11,英22
80mm:中16,英32|58mm:中5,英10
80mm:中8,英16|
> |优声|58mm:中11,英22
80mm:中16,英32|58mm:中5,英10
80mm:中8,英16|
```js
{
type:'text',
value:['我是左边文字','我是右边文字']
}
```
##### 一行三列文本
> |厂家|第一列字数|第二列字数|第三列字数|
> |--|--|--|--|
> |佳博|58mm:中8,英17
80mm:中13,英27|58mm:中2,英5
80mm:中3,英7|58mm:中4,英8
80mm:中6,英12|
> |飞鹅|58mm:中9,英17
80mm:中14,英28|58mm:中3,英6
80mm:中4,英8|58mm:中4,英8
80mm:中6,英12|
> |优声|58mm:中9,英17
80mm:中14,英28|58mm:中3,英6
80mm:中4,英8|58mm:中4,英8
80mm:中6,英12|
```js
{
type:'text',
value:['左边文字','中间文字','右边文字']
}
```
##### 一行四列文本
58宽度第一列13个英文字符,第二列5个英文字符,第三列5个英文字符,第四列6个英文字符(1个中文为2个英文字符)
80宽度第一列23个英文字符,第二列7个英文字符,第三列7个英文字符,第四列8个英文字符(1个中文为2个英文字符)
> |厂家|第一列字数|第二列字数|第三列字数|第四列字数|
> |--|--|--|--|--|
> |佳博|58mm:中6,英13
80mm:中11,英23|58mm:中2,英5
80mm:中3,英7|58mm:中2,英5
80mm:中3,英7|58mm:中3,英6
80mm:中4,英8|
> |飞鹅|58mm:中7,英14
80mm:中12,英24|58mm:中3,英5
80mm:中4,英8|58mm:中3,英6
80mm:中4,英8|58mm:中3,英6
80mm:中4,英8|
> |优声|不支持|不支持|不支持|不支持|
```js
{
type:'text',
value:['第一列','第二列','第三列','第四列']
}
```
### 语音voice
仅语音版支持
> |厂家|支持|说明|
> |--|--|--|
> |佳博|否|部分机型支持厂家定制,开放平台不支持|
> |飞鹅|是|不添加{type:"voice"}默认播放来单语音
“value:REFUND”播报内容为:有用户申请退单了
“value:CANCEL”播报内容为:有用户申请取消订单了|
> |优声|是|value为语音的标志, 目前支持:
4:您有新的订单
5:您有新的美团外卖订单
6:您有新的饿了么外卖订单,请注意查收,
7:您有客户退单,请及时处理(实际效果以打印机播报为准)|
```js
{
type:'voice',
value:4
}
```
语音内容。仅支持语音版打印机,指令内容请咨询技术人员。
### 图片image
- 图片格式jpg,png,gif
- 图片最大宽高(576px X 2000px)
- 图片最大1024KB
不符合要求的图片将打印不成功
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
> #### 默认:左对齐,不加粗,尺寸0,不反色,无下划线
> #### `align`
> 对齐 大小写均可
>
> L: 左对齐(字母L的小写,不是数字1)
>
> C: 居中
>
> R: 右对齐
```js
{
type:'image',
align:'L',
value:'http://图片网址'
}
```
### 字符作为分割线div
如果需要分割线即一个英文符号重复显示一行
常用分割符号`@`,`#`,`=`,`-`
value只能为一个字符长度的英文字符,自动匹配58mm或80mm纸张宽度所需要的字符重复次数
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|是|
> |优声|是|
```js
{
type:'div',
value:'@'
}
```
### 换行br
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|是|
> |优声|否|
```js
{
type:'br'
}
```
### 切纸cut
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|是|
> |优声|否|
切纸行为控制,切刀打印机使用才有效果
```js
{
type:'cut'
}
```
### LOGO
> |厂家|支持|
> |--|--|
> |佳博|是|
> |飞鹅|否|
> |优声|否|
需要先给打印机设置LOGO`printer.setLogo('http://logo网址')`后才能使用。
仅需配置一次。
```js
{
type:'logo'
}
```
### 外置指令plugin
暂不实现
## 异步打印队列
通常为了减少业务模块的耦合性,建议采用异步打印队列来处理打印;
在支付场景下,多数系统同样采用异步处理订单的逻辑,以自有虚拟云主机或一台闲置在家的老式电脑为例,简称自己的服务器
- 主动模式:自己的服务器在进程内定时不间断发起请求到订单处理URL,每次批量处理订单的积分、通知、打印等等逻辑,弊端是需要不停的请求,在云开发模式下比较耗费网络资源
- 惰性模式:当有需要打印的任务时才通知自己的服务器发起请求到打印处理URL,批量处理后检查是否还有打印任务,将结果是否还有任务要打印返回给自己的服务器,自己的服务器判断返回结果,如果有打印任务则继续发起请求,如果没有打印任务则停止发起请求来节约网络资源。
主动模式和惰性模式各有利弊,可以用任何语言实现。
### 添加到打印队列
```js
const cloud = uniCloud.importObject('YourCloudFunction')
//创建打印任务
const task = {
//指定用哪一台打印机
printer_id : '',
//统一打印数据
content:[
{type:'barCode', mode:1, height:20, position:2,value:'1223213112'},
{type:'qrCode', align:'C', size:10, error:'H', value:'https://yun2.net'},
{type:'text', align:'L', bold:1, wsize:1 ,hsize:1, reverse:1, underline:0, value:'我是一行文字'},
{type:'text', value:['我是左边文字','我是右边文字']},
{type:'text', value:['左边文字','中间文字','右边文字']},
{type:'text', value:['第一列','第二列','第三列','第四列']},
{type:'image', align:'L', value:'http://图片网址'},
]
//打印次数,仅佳博支持
times:1
}
//添加一条打印任务
cloud.addTask(task)
//PrinterManager.addTask( [] ) 第一个参数是数组可以同时添加多条打印任务
//如在餐饮场景下,将一个订单的每个菜品分开打印
//可同时创建最多100个任务
const tasks = [
{
printer_id : '',
content:[]
},
{
printer_id : '',
content:[]
}
]
//如果tasks的长度大于100将会被中止创建打印任务
cloud.addTask(tasks)
```
### 处理打印队列
在演示项目云函数`YourCloudFunction`目录下的`package.json`内,默认以阿里云为例配置了URL化访问:`/http/printers`,内置处理打印云函数名:`asyncPrint`
```js
"cloudfunction-config": {
"memorySize": 256,
"timeout": 60,
"triggers": [],
"path": "/http/printers"
}
```
假设云函数自定义域名是`https://domain.com`
那么最终请求地址为:
`https://domain.com/http/printers/asyncPrint`
可以指定单次处理的最多任务数量,默认为10
需要搭配云函数/对象超时时间,避免单次处理超时造成任务积压
`https://domain.com/http/printers/asyncPrint?count=20`
不指定`count`,将使用`PrinterManager.init({max_count:10}`时设置的`max_count`
指定`count`不能超过设置的`max_count`
执行成功返回数据格式如下:
```js
{
"code":0,
"tasks":true,//true:还有未打印的任务,false:没有未打印的任务了
"result":"success"
}
```