npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@lemon-nb/label-print

v0.1.16

Published

PDA 标签打印通用组件:数据 + 格式 → 指令生成与发送,支持 BLE/自定义传输

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/> 或换行分隔的多段文本,每行独立解析模板函数
  • 模板函数fixedroundceilformatDatesumtoCNYtoEnglishUpper 等(见 src/renderers/cpcl.js
  • 字段别名解析:模板中中文标签(如「商品名称」「生产日期」)自动映射到 itemNameproductionDate 等数据字段;支持 明细.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 installyarn 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 单元格内的占位符同样需要映射;明细数据通过 printItemsdetails 数组传入。

多行 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 420goods数组时表示多条订货任务(勿对数组做 {...goods} 展开)

实现见 src/renderers/wmsAppLegacy.js

连续纸模式(启锐等打印机)

getCPCLNewReport 可通过 options.paperContinuous: true 或模板 page.paperContinuous: true 启用连续纸模式:

  • 指令头追加 JOURNAL
  • 页尾不再输出 FORMPARTIAL-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 模板,配合 jasperReportnewReport: 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=123456

package.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 TokenSSH 密钥,勿将密码写入仓库。


目录结构

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)
  • 表格单元格字段解析修复resolveTableCellTextsubstituteSimplePlaceholders${明细.xxx} 替换为 $F{key} 后,若表达式不再含 ${ 但含 $F{,则通过 getFieldFn 解析实际值,修复表格内容打印成 $F{itemName} 字面量的问题(EAR-257627)

0.1.14

  • 新版模板二维码定位修复getCPCLNewReport 非 legacy 路径输出 QR 时使用 data.left + item.xdata.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.versionpage.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{商品名称}${生产日期} 等中文标签可自动映射到 itemNameproductionDate 等实际数据 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