@lemon-nb/label-print
v0.1.16
Published
PDA 标签打印通用组件:数据 + 格式 → 指令生成与发送,支持 BLE/自定义传输
Maintainers
Readme
@lemon-nb/label-print
PDA 标签打印通用组件:根据数据源和格式配置生成 CPCL/TSPL 指令,并通过可插拔的传输适配器(默认 BLE)发送到打印机。
适用于 React Native PDA、Web、Node 等多端复用,与业务层(Redux、UI 库等)解耦。
- npm 包名:
@lemon-nb/label-print - GitLab 仓库:https://gitlab.nhsoft.cn/nhsoft.chenzh/bluetooth-print
- 当前版本:
0.1.16
功能特性
- CPCL / TSPL 指令生成,支持旧版 Jasper 模板与新版格式设计(
newReport) - 新版模板支持 field / barcode / qrcode / table 等元素
- table 元素:明细循环渲染、列宽自适应、单元格换行
- 多行 field:
<br/>或换行分隔的多段文本,每行独立解析模板函数 - 模板函数:
fixed、round、ceil、formatDate、sum、toCNY、toEnglishUpper等(见src/renderers/cpcl.js) - 字段别名解析:模板中中文标签(如「商品名称」「生产日期」)自动映射到
itemName、productionDate等数据字段;支持明细.xxx前缀与嵌套路径 - 表格单元格模板函数:明细列支持
${fixed(${明细.数量},2)}等函数表达式;占位符会先按formatMap替换再解析函数 - wmsAppLegacy 表格:订货单/采购单旧版表格单元格支持模板函数(如
${fixed(...)}) - 内置默认模板:箱码、容器签、收货标签等
- BLE 传输适配器,支持连接后刷新 service/characteristic UUID
- 可自定义 HTTP / 本地服务等传输适配器
安装
从 npm 安装(推荐)
npm install @lemon-nb/label-print
# 或
yarn add @lemon-nb/label-print在 package.json 中:
"@lemon-nb/label-print": "^0.1.4"从 GitLab 安装
yarn add git+ssh://[email protected]:nhsoft.chenzh/bluetooth-print.git#develop或 HTTPS(需 GitLab 访问权限):
"@lemon-nb/label-print": "git+https://gitlab.nhsoft.cn/nhsoft.chenzh/bluetooth-print.git#develop"本地联调(monorepo / file 依赖)
在业务项目 package.json 中:
"@lemon-nb/label-print": "file:./packages/pda-label-print"修改包源码后执行 yarn install 或 yarn sync-label-print(若项目内配置了同步脚本),再重启 Metro。
快速开始
1. 仅生成打印指令(不连接打印机)
import { buildLabelCommand } from "@lemon-nb/label-print";
const cmd = buildLabelCommand({
template: {
type: "cpcl",
newReport: true,
jasperReport: printStyle.jasperReport,
},
data: {
itemName: "商品A",
lotNum: "20250101",
userName: "张三",
printTime: "2025-03-06 12:00:00",
details: [{ itemName: "商品A", useQty: 2, useUnit: "件" }],
},
formatMap: myFormatMap,
copies: 1,
});2. React Native BLE 打印
应用启动时注入 BluetoothManager(可选):
import { setDefaultBleManager } from "@lemon-nb/label-print";
setDefaultBleManager(global.BluetoothManager);调用打印:
import { printLabels, createBleAdapter } from "@lemon-nb/label-print";
await printLabels({
connection: bleDevice, // { peripheralId, serviceUUID, characteristicUUID }
template: {
type: "cpcl",
newReport: !!printStyle.newReport,
jasperReport: printStyle.jasperReport,
},
data: printList,
formatMap,
copies: 1,
transport: createBleAdapter(global.BluetoothManager),
callbacks: {
onConnecting: () => {},
onPrinting: () => {},
onSuccess: () => {},
onError: (msg) => {},
onBluetoothOff: () => {},
},
});3. 直接使用 CPCL 渲染器
import { getCPCLNewReport, getDefaultCPCL } from "@lemon-nb/label-print";
// 新版格式设计
const cpcl = getCPCLNewReport(
jasperReport,
{ ...printParams, userName, printTime },
formatMap,
1,
);
// amazon-wms-app 订货单等 legacy 场景(可选第 5 个参数 options)
const orderCpcl = getCPCLNewReport(
jasperReport,
printOrderList, // 数组:多条采购任务
formatMap,
1,
{
wmsAppLegacy: true,
isWuGeng: () => false,
printUser: "张三",
printTime: "2026-05-26 12:00:00",
},
);
// 无自定义模板时的默认箱码
const defaultCpcl = getDefaultCPCL(printParams);4. 自定义传输适配器
const httpAdapter = {
async isConnected() {
return true;
},
async write(connection, rawCommand) {
await fetch(connection.printServiceUrl, {
method: "POST",
body: rawCommand,
});
},
};
await printLabels({
connection: { printServiceUrl: "https://your-print-service/send" },
template: { type: "cpcl", jasperReport, newReport: true },
data: printList,
transport: httpAdapter,
callbacks: { onSuccess: () => {}, onError: () => {} },
});新版格式设计说明
formatMap
调用方需根据格式设计中的 ${字段名} 与后端 readNew 字段树,构建 Map:
// key: 模板占位符,如 '${商品名称}'
// value: 数据路径,如 '$F{itemName}'
formatMap.set("${商品名称}", "$F{itemName}");table 单元格内的占位符同样需要映射;明细数据通过 printItems 或 details 数组传入。
多行 field(<br/> 换行)
field 的 text 可包含多行,用 <br/> 或换行分隔,每行可独立使用模板函数:
${fixed(${基本数量},2)}<br/>
${round(${基本数量},0)}<br/>
${formatDate("${打印时间}", "YYYY-MM-DD")}table 元素
模板 elements 中含 type: 'table' 时,自动计算表格高度并渲染 thead/tbody/tfoot;tbody 明细行按 details / printItems 循环输出。
wmsAppLegacy(amazon-wms-app 兼容模式)
getCPCLNewReport 第 5 个参数 options 传入 { wmsAppLegacy: true } 时启用旧版 wms-app 特有能力,默认路径不受影响:
- 订货单表格:
wmsPurchaseTaskClientList循环、虚线边框、「商品订货单」居中、表头只打一次 - 吾耕二维码:
options.isWuGeng()为 true 时按旧规则计算 QR 尺寸 - 旧版 field 解析:普通 field 走 eval 回退;含
<br/>/ 模板函数仍走新版多行解析 - 表格纸宽固定
PW 420;goods为数组时表示多条订货任务(勿对数组做{...goods}展开)
实现见 src/renderers/wmsAppLegacy.js。
连续纸模式(启锐等打印机)
getCPCLNewReport 可通过 options.paperContinuous: true 或模板 page.paperContinuous: true 启用连续纸模式:
- 指令头追加
JOURNAL - 页尾不再输出
FORM、PARTIAL-CUT,仅保留PRINT
适用于启锐等使用连续纸、不支持间隙切纸的蓝牙打印机。
API
| 导出 | 说明 |
| ------------------------------------------------------------- | ------------------------ |
| buildLabelCommand(options) | 仅生成指令字符串,不发送 |
| printLabels(options) | 生成并发送到打印机 |
| setDefaultBleManager(bluetoothManager) | 设置默认 BLE 管理器 |
| createBleAdapter(bluetoothManager) | 创建 BLE 传输适配器 |
| getCPCL / getCPCLNewReport | CPCL 指令生成 |
| getDefaultCPCL / getContainerDefaultCPCL | 内置默认 CPCL 模板 |
| getTSPL / getReceiveDefaultCPCL / getReceiveDefaultTSPL | TSPL 相关 |
template.type
| type | 说明 |
| ----------------------------------------------- | ---------------------------------------------------------------- |
| cpcl | CPCL 模板,配合 jasperReport;newReport: true 为新版格式设计 |
| tspl | TSPL 模板,可选 tsplParams: { flip: true } |
| raw | 直接使用 cpclOrTspl 字符串 |
| default_box | 内置箱码默认格式 |
| default_container | 内置容器签默认格式 |
| default_receive_cpcl / default_receive_tspl | 收货任务默认标签 |
printLabels / buildLabelCommand 参数
| 参数 | 类型 | 说明 |
| ------------ | -------------------- | -------------------------------------------------------------------------- |
| template | Object | 模板配置,见上表 |
| data | Object \| Object[] | 单条或多条打印数据 |
| formatMap | Map | 新版模板字段映射(可选) |
| copies | number | 每张标签份数,默认 1 |
| connection | Object | BLE 连接信息(printLabels 必填) |
| transport | Object | 传输适配器;不传则使用 setDefaultBleManager 设置的 BLE |
| callbacks | Object | onConnecting / onPrinting / onSuccess / onError / onBluetoothOff |
发布指南
发布到 npm(公有)
包 maintainer 账号需有 @lemon-nb scope 发布权限(当前 maintainer:chenzhihao123)。
cd bluetooth-print
# 1. 登录 npm(token 过期会导致 E404)
npm login
# 2. 确认当前账号
npm whoami
# 3. 更新 version(package.json),然后发布
npm publish --access public
# 若开启 2FA,需附加 OTP
npm publish --access public --otp=123456package.json 已配置:
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/"
}常见错误:404 Not Found - PUT @lemon-nb/label-print 通常是 npm 未登录或 token 失效,执行 npm login 后重试。
发布成功后,业务项目升级依赖:
yarn add @lemon-nb/label-print@^0.1.4推送到 GitLab
git add .
git commit -m "feat: xxx"
git push origin develop仓库地址:[email protected]:nhsoft.chenzh/bluetooth-print.git
Git 操作请使用 Personal Access Token 或 SSH 密钥,勿将密码写入仓库。
目录结构
bluetooth-print/
├── package.json
├── README.md
└── src/
├── index.js # 主入口:printLabels / buildLabelCommand
├── types.js
├── renderers/
│ ├── cpcl.js # CPCL 渲染、模板函数
│ ├── table.js # table 元素与多行 field 解析
│ ├── wmsAppLegacy.js # amazon-wms-app legacy 表格/订货单
│ ├── tspl.js
│ └── defaultTemplates.js
└── transport/
└── bleAdapter.js # BLE 传输适配器版本记录
0.1.16
- 条码/二维码坐标安全处理:新增
safeCpclCoord,对 CPCL 条码与二维码坐标取整并兜底非负,避免负坐标或浮点坐标导致打印异常 - 新版模板页高计算优化:
getCPCLNewReport非 legacy 路径统一以Math.max(contentHeight, designPageHeight)计算最终页高,设计稿页高不再额外减 12,无表格标签也保证不低于设计稿高度 - 表格序号占位符增强:支持
${数据源序号}及明细.xxx.数据源序号等写法;resolveTableCellText在简单占位符替换时跳过序号类占位符,避免被formatMap误替换 - 动态表格底部安全距离:
calculateNewReportPrintHeight底部边距至少预留 80 dots,适配连续纸及不同机型尾部不可打印区差异
0.1.15
- 连续纸模式(启锐打印机):
getCPCLNewReport支持options.paperContinuous或模板page.paperContinuous;连续纸时输出JOURNAL指令,页尾跳过FORM/PARTIAL-CUT,仅保留PRINT(EAR-258277) - 表格单元格字段解析修复:
resolveTableCellText在substituteSimplePlaceholders将${明细.xxx}替换为$F{key}后,若表达式不再含${但含$F{,则通过getFieldFn解析实际值,修复表格内容打印成$F{itemName}字面量的问题(EAR-257627)
0.1.14
- 新版模板二维码定位修复:
getCPCLNewReport非 legacy 路径输出 QR 时使用data.left + item.x、data.top + item.y,与 field / barcode 一致,修复二维码偏移 - 二维码尺寸自适应:按模板元素宽高与内容长度估算 CPCL
U单元大小,最小打印边长约 100 点,避免固定U 7导致过小或过大 - 装箱码打印参数:
createPrintParams增加skuNum别名(同skuQty),兼容模板占位符${skuNum}
0.1.13
- 96 DPI 识别优化:新增
isLikelyDesignerPixelCmTemplate,根据模板unit: cm与尺寸/边距数值形态推断是否为新版设计器 96 DPI 画布坐标,不再依赖page.version - 兼容旧厘米模板:真实厘米值(如 6cm、0.1cm)不会被误判为 96 DPI 像素坐标
0.1.12
- 新版格式设计 96 DPI 坐标转换:
getCPCLNewReport根据page.version、page.paperSize自动识别设计器画布 DPI(72 / 96),按 203 打印机 DPI 换算元素位置与尺寸,修复新版设计器标签偏移、缩放不正确 - 纸宽指令优化:非 legacy 模板在
data.width > 0时输出PW,不再仅限含 table 元素时才设置纸宽 - 取消新版模板 576 点纸宽上限:移除
72 * 8居中裁剪,按设计稿实际宽度打印 - wmsAppLegacy 不受影响:订货单等 legacy 场景仍使用 72 DPI 坐标与
PW 420固定纸宽
0.1.11
- 打印字体优化:支持字体加粗
0.1.10
- CPCL 字段别名解析:新增
FIELD_ALIAS_MAP,模板字段$F{商品名称}、${生产日期}等中文标签可自动映射到itemName、productionDate等实际数据 key - 嵌套路径取值:
resolvePrintDataValue支持a.b.c点路径,以及明细.xxx前缀回退到xxx - 函数参数占位符:
parseTemplateFunctions在解析${function(...)}前,先替换参数内的简单${字段}占位符 getField增强:除$F{xxx}外,也支持简单${xxx}字段引用;统一走别名解析与数字保留 2 位小数
0.1.9
- 表格起始 Y 定位优化:
getTableFallbackStartY在无设计稿 Y 坐标时,按elements数组中 table 的下标,取 table 之前元素的最大底部作为起始位置,避免表格与上方 field/条码重叠 getTableStartY兜底参数:fallbackStartY默认值由0改为null,仅在有明确回退值时才使用,避免0被误判为有效起始 Y
0.1.8
- 表格占位符别名:
substituteSimplePlaceholders支持明细.xxx、明细.客户明细.xxx等前缀自动匹配formatMap(兼容设计器字段名与数据字段名不一致) - 表格单元格函数解析:
resolveTableCellText先替换简单占位符再识别模板函数,修复${fixed(${明细.数量},2)}等表达式无法取值的问题 - wmsAppLegacy 表格函数:
replaceLegacyWmsAppTableFields增加getFieldFn参数,旧版订货单表格支持模板函数;getCPCLNewReport在 legacy 模式下传入resolveField
0.1.7
- 新增模板函数
ceil(向上取整)、toEnglishUpper(英文金额大写) - 修复嵌套模板函数解析:参数内
${字段}使用非贪婪匹配,避免误截断 - 表格单元格支持模板函数表达式
0.1.6
- 装箱码商品列表支持打印字体大小,支持列宽定义
0.1.4
- 修复新版模板元素缺少
size/position时 CPCL 渲染崩溃 - 修复装箱码标签表格与页脚 field 重叠:优化
getTableFallbackStartY页脚识别逻辑 - 新增
calculateNewReportPrintHeight:按明细行数动态计算打印高度,同时保留设计稿底部留白
0.1.3
- 支持老格式设计$P{}字段解析
0.1.2
- 新增
wmsAppLegacy兼容模式(getCPCLNewReport第 5 参数options.wmsAppLegacy) - 订货单表格渲染、吾耕 QR、旧版 field eval 回退(见
wmsAppLegacy.js) - 与
pda-label-print本地包同步:cpcl.js/table.js/bleAdapter.js等
0.1.1
- 新增 table 格式元素渲染
- 支持
<br/>多行 field 与嵌套模板函数解析 - BLE connect 后刷新 service/characteristic UUID
formatDate无效日期兜底
0.1.0
- 初始版本:CPCL/TSPL 生成、BLE 打印、默认模板
License
MIT
