Table of Contents
Installation and Usage
- Print Control - SpiritWeb
- Label Design - Designer
- Label Printing - SpiritLabel
- Registration Code Authorization
- Membership Authorization
- embeded Javascript
Development Manual
- JS API
- Dynamic Link Library
- REST API
- Third-party Website Integration
- Android Native SDK
- H5 APP
FAQ
"打印精灵"扩展小程序Extension开发指南
打印精灵的Web插件, 桌面版, Center版均支持扩展小程序, 开发建议使用桌面版.
目录结构
extension-name/
├── extension.json # 扩展配置文件(必需)
├── entry.html # 入口 HTML 文件
├── app.js # 前端应用代码
├── styles.css # 样式文件
├── icon.png # 扩展图标(根目录)
└── server/ # 服务端脚本
├── script_1.js
└── script_2.js
extension.json 配置
1{
2 "id": "extension-id",
3 "name": "扩展名称",
4 "desc": "扩展描述",
5 "icon": "icon.png",
6 "entry": "entry.html",
7 "version": "x.x.x",
8 "config": {
9 "key1": "value1", //缺省配置项目
10 "key2": "value2"
11 }
12}
前端 API
前端API包括: 配置API, 核心功能API, 服务端脚本调用API三类, 前端程序通过这三类API可以实现复杂的业务程序.
配置 API
1// 读取配置
2const cfg = await (await fetch(`/app-ext/getcfg?app=${extensionId}`)).json()
3
4// 保存配置
5await fetch(`/app-ext/setcfg?app=${extensionId}`, {
6 method: 'POST',
7 headers: { 'Content-Type': 'application/json' },
8 body: JSON.stringify({ key: value })
9})
核心功能API
| API | 方法 | 说明 |
|---|---|---|
/api/v2/get-printer-list |
GET | 获取打印机列表 |
/api/v2/print |
POST | 打印标签 |
/api/v2/close |
POST | 关闭打印机(生成文件) |
/utils/thumb |
GET | 标签预览 |
1// 获取打印机列表
2const { printers } = await (await fetch(`/api/v2/get-printer-list`)).json()
3// printers: [{ name, type, act }, ...]
4
5// 打印标签
6await fetch("/api/v2/print", {
7 method: "POST",
8 headers: { "Content-Type": "application/json" },
9 body: JSON.stringify({
10 cmd: "PrintLabel",
11 data: { tpid: label_id, vars: record },
12 opts: { printer: printerName }
13 })
14})
15
16// 关闭打印机并生成文件
17await fetch("/api/v2/close", {
18 method: "POST",
19 headers: { "Content-Type": "application/json" },
20 body: JSON.stringify({ printer: "Microsoft Print to PDF" })
21})
22
23// 标签预览
24const vars = encodeURIComponent(JSON.stringify(record))
25const previewUrl = `/utils/thumb?id=${templateId}&vars=${vars}`
服务端脚本调用
对于无法通过核心API实现的功能, 可以通过服务端脚本实现, 在前端调用服务端脚本的API如下
1// GET 请求
2const result = await fetch(`/app-ext-run/${extensionId}/script.js?key=value`)
3
4// POST 请求
5const result = await fetch(`/app-ext-run/${extensionId}/script.js`, {
6 method: 'POST',
7 headers: { 'Content-Type': 'application/json' },
8 body: JSON.stringify({ data })
9})
服务端 API
打印精灵扩展框架支持用JS开发服务端脚步程序, 并提供了一系列服务端API用于功能开发
上下文对象 ctx
| 属性/方法 | 说明 |
|---|---|
ctx.request.query |
URL 查询参数 |
ctx.request.body |
POST 请求体 |
ctx.cfg |
扩展配置 |
ctx.json(data) |
返回 JSON 响应 |
ctx.type(mime) |
设置响应类型 |
ctx.data(buffer) |
返回二进制数据 |
ctx.file(path) |
返回文件 |
DB操作
1// 打开 DB 表
2const tbl = DB.Open(excelPath[, "SheetName"])
3
4// 查询 - 获取第一条
5const result = tbl.Query().Where("列名", "=", value).First()
6
7// 查询 - 获取所有匹配
8const list = tbl.Query().Where("列名", "=", value).Find()
9
10// 关闭表
11db.close(excelPath, "SheetName")
打印/预览函数
1// 生成预览图
2rc = preview(labelId, vars, { printer: "preview", dpmm: "8" })
3ctx.type("png")
4ctx.data(rc.data)
5
6// 打印标签
7rc = print(labelId, vars, { printer: printerName })
完整示例
entry.html
1<!DOCTYPE html>
2<html>
3<head>
4 <link rel="stylesheet" href="styles.css">
5</head>
6<body>
7 <div id="root"></div>
8 <script src="/js/preact-bundle.js"></script>
9 <script type="module" src="app.js"></script>
10</body>
11</html>
app.js
1const { Preact, html } = window;
2const { useState, useEffect, render } = Preact;
3
4function Setup(props) {
5 const [excel, setExcel] = useState();
6 const [labelId, setLabelId] = useState();
7 const [printer, setPrinter] = useState("");
8 const [printers, setPrinters] = useState([]);
9
10 useEffect(() => {
11 // 加载打印机列表
12 fetch(`/api/v2/get-printer-list`)
13 .then(r => r.json())
14 .then(rc => setPrinters(rc.printers || []));
15
16 // 加载已保存的配置
17 fetch(`/app-ext/getcfg?app=myextension`)
18 .then(r => r.json())
19 .then(cfg => {
20 setExcel(cfg.excel);
21 setLabelId(cfg.label_id);
22 setPrinter(cfg.printer || "");
23 });
24 }, []);
25
26 const saveSetup = async () => {
27 await fetch(`/app-ext/setcfg?app=myextension`, {
28 method: 'POST',
29 headers: { 'Content-Type': 'application/json' },
30 body: JSON.stringify({ excel, label_id: labelId, printer })
31 });
32 props.onSetup();
33 };
34
35 return html`
36 <section>
37 <label>数据文件</label>
38 <input value=${excel} onChange=${e => setExcel(e.target.value)} />
39
40 <label>标签ID</label>
41 <input value=${labelId} onChange=${e => setLabelId(e.target.value)} />
42
43 <label>打印机</label>
44 <select value=${printer} onChange=${e => setPrinter(e.target.value)}>
45 ${printers.map(p => html`<option value=${p.name}>${p.name}</option>`)}
46 </select>
47
48 <button onClick=${saveSetup}>保存</button>
49 </section>
50 `;
51}
52
53function Main(props) {
54 const [msg, setMsg] = useState("");
55
56 const printLabel = async (id) => {
57 const res = await fetch(`/app-ext-run/myextension/print.js`, {
58 method: 'POST',
59 headers: { 'Content-Type': 'application/json' },
60 body: JSON.stringify({ id })
61 });
62 const rc = await res.json();
63 setMsg(rc.rc === "OK" ? "打印成功" : rc.msg);
64 };
65
66 return html`
67 <div>
68 <button onClick=${() => printLabel("ABC123")}>打印</button>
69 <p>${msg}</p>
70 </div>
71 `;
72}
73
74function App() {
75 const [inSetup, setInSetup] = useState(true);
76 return html`
77 <main>
78 <h1>我的扩展</h1>
79 ${inSetup
80 ? html`<${Setup} onSetup=${() => setInSetup(false)} />`
81 : html`<${Main} />`
82 }
83 </main>
84 `;
85}
86
87render(html`<${App} />`, document.getElementById('root'));
server/print.js
1var body = ctx.request.body;
2try {
3 let { excel, label_id, printer } = ctx.cfg;
4
5 let tbl = db.open(excel, "Sheet1");
6 let vars = tbl.Query().Where("设备编码", "=", body.id).First();
7
8 print(label_id, vars, { printer: printer });
9 ctx.json({ rc: "OK" });
10} catch (e) {
11 ctx.json({ rc: "ERR", msg: "" + e });
12}
server/preview.js
1var id = ctx.request.query.id;
2try {
3 let { excel, label_id } = ctx.cfg;
4
5 let tbl = db.open(excel, "Sheet1");
6 let vars = tbl.Query().Where("设备编码", "=", id).First();
7
8 rc = preview(label_id, vars, { printer: "preview", dpmm: "8" });
9 ctx.type("png");
10 ctx.data(rc.data);
11} catch (e) {
12 ctx.file("err.png");
13}
server/close.js
1try {
2 let { excel } = ctx.cfg;
3 if (excel) {
4 db.close(excel, "Sheet1");
5 }
6 ctx.json({ rc: "OK" });
7} catch (e) {
8 ctx.json({ rc: "ERR", msg: "" + e });
9}
API 汇总
| API | 方法 | 说明 |
|---|---|---|
/app-ext/getcfg?app={id} |
GET | 获取扩展配置 |
/app-ext/setcfg?app={id} |
POST | 保存扩展配置 |
/app-ext-run/{id}/{script}.js |
GET/POST | 调用服务端脚本 |
/api/v2/get-printer-list |
GET | 获取打印机列表 |
/api/v2/print |
POST | 打印标签 |
/api/v2/close |
POST | 关闭打印机 |
/utils/thumb?id={tplId}&vars={json} |
GET | 标签预览图 |
最佳实践
- 路径规范: 服务端脚本路径为
/app-ext-run/{extensionId}/{script}.js - 配置管理: 使用
ctx.cfg获取配置,配置通过/app-ext/setcfg保存 - 错误处理: 服务端统一返回
{ rc: "OK"/"ERR", msg: "..." } - 资源释放: 操作完成后调用
db.close()释放 Excel 文件 - Preact 框架: 前端使用 Preact,通过
/js/preact-bundle.js引入