打印组件接入文档
将传思网"打印模板"能力嵌入到您的网站,让您的用户在线设计模板、下发到本地客户端并触发打印。共三步:完成身份核验(申请 API Key 并换取 Token)→ 安装本地 ClientPrinter 客户端 → 引入 wacp.js SDK 调用「设计 / 下载 / 打印」。
1身份核验(申请 API Key + 换取 Token)
使用 wacp.js 的设计器与下载能力前,需要一个有效的 API Key 并换取 Poster 服务 Token(打印模板与海报共用同一类型 Token)。详细步骤请参阅:
Poster 换取 Token(有效期 1 小时)→ 把 Token 传给 SDK。注意:OCR / ASR / TTS 的 Token 不可用于打印模板接入,必须使用
serviceType=Poster。
wacp.openDesigner 打开设计器时;② 调用 wacp.downloadTemplate 把模板下发到本地时。后续
wacp.print 完全走本机链路,无需 Token、断网亦可继续打印。
2安装本地打印客户端 ClientPrinter
打印动作发生在用户的本机(依赖系统打印机驱动),因此需要在每台需要打印的电脑上安装 ClientPrinter。它兼容 Windows 7 / 10 / 11(32 位 / 64 位)。
安装后的客户端为 SDK 提供两项能力:
- 注册
acp://自定义协议,浏览器可自动唤起客户端,无需用户手动启动; - 持久化已下载的模板,断网仍可继续打印;客户端不持久化任何 Token。
• 点击上方按钮下载安装包后,双击运行并按提示完成系统打印机驱动安装;
• 安装后需允许其开机自启,否则用户每次需手动启动;
• 浏览器首次唤起
acp:// 时会弹出"是否允许打开 ClientPrinter",请勾选"始终允许"以避免反复确认;• 未检测到客户端运行时,SDK 会自动弹出下载提示。
3引入 SDK 并完成三段式调用
3.1 引入 wacp.js
在您的网站页面引入 wacp.js:
<script src="https://your-webapi.com/printtemplate/wacp.js"></script> <script> var wacp = new Wacp(); </script>
3.2 打开模板设计器(openDesigner)
调用 wacp.openDesigner(token, options, onReady) 在新窗口打开设计器,用户保存模板时通过 onReady 回调拿到 templateId 并持久化到您的业务系统。
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
| token | 是 | string | Poster 服务 Token。 |
| options.templateId | 否 | string | 已有模板 ID。不传 则创建空白模板;传入 则加载已有模板用于继续编辑。 |
| options.dataSourceFields | 否 | object | 设计器内可绑定的数据源字段映射,{ 英文键: '中文显示名' },例如 { userName: '姓名', orderId: '工号' }。 |
| options.dpi | 否 | number | 新建模板时画布的初始 DPI,常用 203(热敏标签/小票)/ 300(激光)/ 600(照片)。仅未传 templateId 时生效;不传时设计器默认 203,用户仍可在工具栏修改。详见下方「DPI 参数怎么填」。 |
| options.width / options.height | 否 | number | 新建模板时画布初始尺寸(单位:像素)。仅未传 templateId 时生效,未传时设计器自带默认。 |
| onReady | 否 | function | 设计器保存或退出时回调 { templateId, error, type },templateId 即为可持久化到三方业务系统的模板 ID。 |
// 打开设计器(独立窗口)
wacp.openDesigner(
'a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6',
{
templateId: '', // 留空 = 新建
dpi: 203, // 新建画布初始 DPI(203 / 300 / 600)
dataSourceFields: {
userName: '姓名',
orderId: '工号'
}
},
function (ev) {
if (ev.error) {
console.error('[wacp] 设计器返回错误:', ev.error);
return;
}
// ev.templateId 为最终保存的模板 ID
// 业务方持久化此 ID,用于后续 download / print
localStorage.setItem('myTemplateId', ev.templateId);
console.log('模板已保存,templateId:', ev.templateId);
}
);
widthMm(毫米宽)/ heightMm(毫米高)/ dpi(建议 203 / 300),保存时会强校验,否则拒绝入库。
3.3 把模板下载到本地(downloadTemplate)
用户首次打印(或模板更新后)需把云端最新模板下发到本地 ClientPrinter。SDK 会自动尝试唤起本地客户端:
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
| token | 是 | string | Poster 服务 Token。 |
| templateId | 是 | string | 云端模板 ID(由 openDesigner 保存时返回)。 |
| name | 否 | string | 本地显示名称,仅用于客户端「查看本机模板」下拉列表展示;允许重复,本地仍以 templateId 唒一。未传时默认使用 templateId 作为名称。 |
// 不传名称:本地以 templateId 作为显示名
wacp.downloadTemplate(token, templateId)
.then(function (info) {
// info = { templateId, name }
console.log('模板已下发到本地:', info.templateId, info.name);
})
.catch(function (err) {
// 常见错误:本地 ClientPrinter 未运行(acp:// 唤起失败)/ token 过期 / 模板不存在
alert('下发失败:' + err.message);
});
// 传入中文名称:客户端下拉列表中会显示“工号牌-2026版”
wacp.downloadTemplate(token, templateId, '工号牌-2026版');
// 也可以传对象形式
wacp.downloadTemplate(token, templateId, { name: '工号牌-2026版' });
wacp.print 全程本地,不再需要 token。
name,不拼接 ID。如果多个模板使用同名称,用户从视觉上无法区分,但选中后系统仍会按唯一的 templateId 加载;建议业务侧在名称中附加可识别后缀(如「工号牌-A版」/「工号牌-B版」)。
3.4 触发本地打印(print)
打印动作完全在用户本机执行,无需联网。一次调用支持多条数据 + 多份份数。
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
| templateId | 是 | string | 必须为已经 downloadTemplate 过的模板 ID;本地未找到时报错。 |
| payload.rows | 是 | object[] | 非空数组,每个对象一条打印记录。键名必须与设计器中绑定的 dataSourceFields 一致。 |
| payload.copies | 否 | number | 每条记录的打印份数,默认 1。 |
wacp.print(templateId, {
rows: [
{ userName: '张三', orderId: 'A001' },
{ userName: '李四', orderId: 'A002' }
],
copies: 1
})
.then(function (res) {
console.log('已下达打印任务:', res);
})
.catch(function (err) {
console.error('打印失败:', err.message);
});
3.5 删除云端模板(deleteTemplate)
当不再需要某个模板时,可从服务器永久删除。删除后该模板不可恢复,但本地已下载的副本不受影响(仍可继续打印)。
| 参数 | 必填 | 类型 | 说明 |
|---|---|---|---|
| token | 是 | string | Poster 服务 Token。 |
| templateId | 是 | string | 要删除的模板 ID(由 openDesigner 保存时返回)。 |
wacp.deleteTemplate(token, templateId)
.then(function (res) {
console.log('模板已删除:', res.message);
})
.catch(function (err) {
// 常见错误:token 过期 / 模板不存在 / 无权删除(非本账号创建的模板)
alert('删除失败:' + err.message);
});
downloadTemplate 重新拉取。
3.6 事件订阅
| 事件 | 触发时机 |
|---|---|
| connected | SDK 与本地 ClientPrinter 建链成功。 |
| disconnected | 本地连接断开(用户关闭客户端、网络异常等)。 |
| printed | 本地完成一次打印,payload 含 taskCount 等统计字段。 |
| error | 调用链路中的任何错误(连接超时、token 过期、模板不存在)。 |
| idCardRead / idCardConnected / idCardDisconnected / idCardError / idCardReaderSwitched / idCardReaderEnabled | 身份证读卡器推送事件,详见下文「3.8 身份证读卡器」。 |
wacp.on('connected', function () { console.log('客户端已连接'); });
wacp.on('printed', function (e) { console.log('打印完成', e); });
wacp.on('error', function (e) { console.error('SDK 错误', e); });
扩展能力(本地存取 / 读卡器 / 系统)
除「设计 / 下发 / 打印」主链路外,wacp.js 还封装了 ClientPrinter 在本机提供的应用能力,可调用本机键值存取、身份证读卡器、系统动作等,本节能力全部走本机链路,不需 token。
3.7 本机键值对存取 (setItems / getItems / removeItems)
将 UI 常用参数(如部门名、上次选择、设备号)写入本机 Settings 表,断电不丢;同一台机器上不同页面/会话都能读到。存储 value 统一以字符串语义调度。
// 写入(同名键会被覆盖)
wacp.setItems({
deptName: '行政部',
userName: '张三',
lastTplId: 'tpl_20260520_xxx'
});
// 读取:返回只包含存在的 key
wacp.getItems(['deptName', 'userName']).then(function (m) {
console.log(m.deptName, m.userName); // 行政部 张三
});
// 删除
wacp.removeItems(['deptName']);
localStorage 的区别:setItems 写入的是本机 ClientPrinter,与浏览器、域名均无关;同一台电脑上的任何三方网站都能读取。
3.8 身份证读卡器
ClientPrinter 内置两种读卡器驱动:HS100N(USB 免驱)与 SerialPort(串口 IDM40 类)。SDK 提供状态查询 / 切换 / 开关控制以及 推送式读卡事件。
| 方法 | 说明 |
|---|---|
| switchIDCardReader(type) | 切换型号,type 为 'HS100N' 或 'SerialPort'。返回 { readerType }。 |
| getIDCardReaderType() | 查询当前型号。返回 { readerType }。 |
| setIDCardReaderEnabled(enabled) | 开启 / 关闭读卡。返回 { enabled, readerType }。 |
| getIDCardReaderEnabled() | 查询读卡开关状态。返回 { enabled, readerType }。 |
推送事件(服务端主动广播):
| 事件名 | 触发时机 / payload |
|---|---|
| idCardRead | 读到身份证。ev.data 为包含姓名、性别、身份证号、地址、照片 base64 等字段的对象。 |
| idCardConnected | 读卡器设备已连接(USB 插入 / 串口打开)。 |
| idCardDisconnected | 读卡器设备已拔出,插回后会自动重新广播 connected。 |
| idCardError | 读卡过程异常(SDK 异常、设备占用等)。 |
| idCardReaderSwitched | 调用 switchIDCardReader 后会同时返回 Promise,也会广播该事件。 |
| idCardReaderEnabled | 读卡开关变更(包括在 ClientPrinter 本机 UI 手动切换)。 |
// 订阅读卡事件(在调用 setIDCardReaderEnabled(true) 之前订阅以免丢事件)
wacp.on('idCardRead', function (ev) {
// ev.data 示例:
// {
// Name: '张三', Sex: '男', Nation: '汉', Birth: '19900101',
// Address: '北京市海淀区中关村大街1号',
// IDCardNo: '110108199001011234',
// Department: '北京市公安局海淀分局',
// ValidStart: '20200101', ValidEnd: '20400101',
// PhotoBase64: 'data:image/bmp;base64,...' // 按驱动不同可能为 JPG
// }
console.log('读到身份证', ev.data);
});
wacp.on('idCardError', function (ev) { console.error('读卡错误', ev.data); });
wacp.on('idCardDisconnected', function () { /* 提示用户重插 */ });
// 选择型号 + 开启读卡
wacp.switchIDCardReader('HS100N')
.then(function () { return wacp.setIDCardReaderEnabled(true); })
.then(function (r) { console.log('读卡已开启', r); });
•
HS100N 需插入 USB 读卡器,ClientPrinter 会自动检测;•
SerialPort(IDM40 类串口读卡器)需要使用手动点亮其驱动,ClientPrinter 会自动探测串口;• 设备拔插后会自动推送
idCardConnected / idCardDisconnected,业务侧只需代码订阅事件即可。
3.9 系统能力
| 方法 | 说明 |
|---|---|
| createDesktopShortcut(name, url) | 在用户桌面创建一个网页快捷方式,使用默认浏览器打开。按机器头一次使用时快速引导。 |
| getClientNum() | 获取本机 ClientPrinter 的唯一通道号 ClientNum,返回 { clientNum }。 |
| clearPrintTasks() | 清空本机打印任务队列,不影响已下发给驱动的任务。 |
| clearTemplates() | 清空本机所有已下载的模板(谨慎),后续需重新 downloadTemplate。 |
| connect() | 显式建立 WebSocket 连接。默认采用懒建连,等首次业务调用时自动建连。 |
// 1)创建桌面快捷方式
wacp.createDesktopShortcut('打印组件 Demo',
'https://tools.eainfor.com/printtemplate/demo-printer.html');
// 2)查询本机通道号
wacp.getClientNum().then(function (r) { console.log(r.clientNum); });
// 3)集中作业中零凌时清队
wacp.clearPrintTasks();
在线体验
我们提供了一个集成 Demo 启动页,覆盖「换 Token / 设计模板 / 下发到本地 / 触发打印」全链路,可在不写代码的情况下走通流程:
建议先在 Demo 启动页跑通一次完整链路(确认本机 ClientPrinter 已安装、能成功唤起 + 出纸),再按上面的示例代码集成到您自己的网站。
DPI 参数怎么填
设计器顶部工具栏的 DPI 输入框(默认 203)决定模板的 毫米 ↔ 像素 折算关系:
画布像素宽 = widthMm × dpi ÷ 25.4 画布像素高 = heightMm × dpi ÷ 25.4
所以 DPI 必须与目标打印机的实际 DPI 一致,否则本地客户端会按比例缩放,导致出纸尺寸偏大或偏小。
推荐取值
| 打印机类型 | 推荐 DPI |
|---|---|
| 热敏标签机(条码、胸卡) | 203 |
| 热敏小票机 | 203 |
| 普通激光 / 喷墨打印机 | 300 |
| 高精度照片打印 | 600 |
XX-203 即为 203 dpi,XX-300 即为 300 dpi。
如何在 Windows 查看打印机 DPI
打开 控制面板 → 设备和打印机,右键目标打印机 → 打印机属性,然后按下表查找:
| 选项卡 | 查看位置 |
|---|---|
| 常规 | 部分驱动会在"型号 / Model"行显示 203 dpi 等字样。 |
| 高级 | 点 打印默认值... → 图形 或 质量,会有"分辨率"下拉框,列出 203 dpi / 300 dpi 等可选值。 |
| 设备设置 | 标签机驱动通常在这里有"打印头分辨率 / Print Head Resolution"选项。 |
600 dpi / 1200 dpi,那是最大输出分辨率,不是物理 DPI。普通办公场景按 300 填即可,更高反而可能引起缩放问题。
实在查不到?用试错法
如果没有规格书也找不到驱动属性,按推荐值填一个,然后通过设计器右上角的 🖨️ 打印测试页 试打一张,再用尺子量纸面:
- 量出来比设计的 大 → 填的 DPI 小了,调高(如 203 → 300);
- 量出来比设计的 小 → 填的 DPI 大了,调低(如 300 → 203);
- 量出来一致 → DPI 就是对的。
常见问题
• 确认本机已安装并运行 ClientPrinter(任务栏托盘有对应图标);未安装请点击 下载 ClientPrinter;
• 确认浏览器允许
acp:// 协议唤起(Chrome 首次需勾选"始终允许");• 默认监听端口为
8080,若被占用可在 ClientPrinter 配置中修改,并同步传入 new Wacp({ wsUrl: 'ws://127.0.0.1:新端口/' })。
• 设计器右侧「打印参数」面板必须填写
widthMm / heightMm / dpi(均为正数);• dpi 推荐:热敏标签 203 / 热敏小票 203 / 普通激光打印机 300。
• 检查
rows[i] 的键名是否与设计器中绑定的 dataSourceFields 一致(区分大小写);• 若设计器使用
{{key}} 占位符,请确保 key 已加入 dataSourceFields 并在 rows 中提供值。
•
print.dpi 必须与目标打印机实际 DPI 匹配,否则会被等比缩放;• 横向打印机请将
print.rotate90 设为 true,仅做长宽交换,无需重新设计内容。
• 换取 Token 时
serviceType 必须为 Poster;• OCR / ASR / TTS 的 Token 不可用于打印模板接入,需要单独换取。