@linch-tech/print-sdk
v0.1.1
Published
Linch Print Studio SDK - 打印解决方案 SDK,支持 Web 和 Node.js
Downloads
225
Readme
@linch-tech/print-sdk
Linch Print Studio 的 JavaScript/TypeScript SDK,支持 Web 应用和 Node.js 服务调用。
安装
npm install @linch-tech/print-sdk
# or
pnpm add @linch-tech/print-sdk
# or
yarn add @linch-tech/print-sdk快速开始
Web 应用
import { LinchPrint } from '@linch-tech/print-sdk';
// 单次打印
await LinchPrint.template('order-tpl')
.data({
orderNo: 'ORD-2024-001',
customer: { name: '张三', phone: '13800138000' },
items: [
{ name: '商品A', qty: 2, price: 99.00 },
{ name: '商品B', qty: 1, price: 199.00 }
]
})
.print({ printer: 'HP LaserJet', copies: 2 });Node.js 服务
import { LinchPrint } from '@linch-tech/print-sdk/node';
// 服务端打印
await LinchPrint.template('order-tpl')
.data({ orderNo: 'ORD-001', customer: { name: '张三' } })
.print({ printer: 'Office Printer' });API 参考
初始化
import { createLinchPrint } from '@linch-tech/print-sdk';
// 自定义配置
const printer = createLinchPrint({
baseUrl: 'http://localhost:4500', // API 地址
timeout: 30000, // 请求超时(毫秒)
});
// 或使用默认配置
import { LinchPrint } from '@linch-tech/print-sdk';LinchPrint
主入口对象,提供以下方法:
LinchLinchPrint.template(id)
选择模板,返回 TemplateClient 实例。
const tpl = LinchLinchPrint.template('order-tpl');LinchLinchPrint.printers()
获取可用打印机列表。
const printers = await LinchLinchPrint.printers();
// ['HP LaserJet Pro', 'Canon PIXMA', 'Microsoft Print to PDF']LinchPrint.templates()
获取所有模板列表。
const templates = await LinchPrint.templates();
// [{ id: 'order-tpl', name: '订单打印模板', updatedAt: 1703001234 }]LinchPrint.getJob(jobId)
查询打印任务状态。
const job = await LinchPrint.getJob('job_1703001234567');
// { id: '...', status: 'completed', printer: 'HP LaserJet', ... }TemplateClient
通过 LinchPrint.template(id) 获取。
template.data(payload)
绑定单条数据,返回 PrintTask 实例。
const task = LinchPrint.template('order-tpl').data({
orderNo: 'ORD-001',
customer: { name: '张三' }
});template.batch(payloads)
绑定多条数据(批量打印),返回 PrintTask 实例。
const task = LinchPrint.template('order-tpl').batch([
{ orderNo: 'ORD-001', customer: { name: '张三' } },
{ orderNo: 'ORD-002', customer: { name: '李四' } },
{ orderNo: 'ORD-003', customer: { name: '王五' } },
]);template.schema()
获取模板的数据 Schema 定义。
const schema = await LinchPrint.template('order-tpl').schema();
// {
// version: '1.0',
// fields: [
// { name: 'orderNo', type: 'string', required: true },
// { name: 'customer.name', type: 'string' },
// ...
// ]
// }template.validate(data)
验证数据是否符合模板 Schema。
const result = LinchPrint.template('order-tpl').validate({
orderNo: 'ORD-001',
customer: { name: '张三' }
});
if (!result.valid) {
console.error('数据验证失败:', result.errors);
}PrintTask
通过 template.data() 或 template.batch() 获取。
task.preview()
生成预览 HTML。
const html = await LinchPrint.template('order-tpl')
.data({ orderNo: 'ORD-001' })
.preview();
// 在页面中显示预览
document.getElementById('preview').innerHTML = html;task.print(options?)
执行打印。
const result = await LinchPrint.template('order-tpl')
.data({ orderNo: 'ORD-001' })
.print({
printer: 'HP LaserJet', // 打印机名称
copies: 2, // 份数
});
console.log('打印任务ID:', result.jobId);task.printBatch(options?)
批量打印(需要先调用 batch() 绑定多条数据)。
const results = await LinchPrint.template('order-tpl')
.batch(orders)
.printBatch({
printer: 'HP LaserJet',
copies: 1,
continueOnError: true, // 遇错继续
onProgress: (current, total) => {
console.log(`打印进度: ${current}/${total}`);
}
});
// 检查结果
results.forEach((r, i) => {
if (r.status === 'failed') {
console.error(`订单 ${i} 打印失败:`, r.error);
}
});类型定义
PrintOptions
interface PrintOptions {
printer?: string; // 打印机名称,不指定则使用默认打印机
copies?: number; // 打印份数,默认 1
}BatchPrintOptions
interface BatchPrintOptions extends PrintOptions {
continueOnError?: boolean; // 遇错是否继续,默认 false
onProgress?: (current: number, total: number) => void; // 进度回调
}PrintResult
interface PrintResult {
jobId: string;
status: 'pending' | 'printing' | 'completed' | 'failed';
error?: string;
}TemplateSchema
interface TemplateSchema {
version: '1.0';
fields: FieldDefinition[];
}
interface FieldDefinition {
name: string; // 字段名(支持 customer.name)
type: FieldType; // 类型
label?: string; // 显示名称
required?: boolean; // 是否必填
default?: any; // 默认值
description?: string; // 描述
items?: FieldDefinition; // 数组元素定义
properties?: FieldDefinition[]; // 对象属性定义
}
type FieldType = 'string' | 'number' | 'boolean' | 'date' | 'image' | 'array' | 'object';ValidationResult
interface ValidationResult {
valid: boolean;
errors: ValidationError[];
}
interface ValidationError {
field: string;
message: string;
}使用场景示例
1. 电商订单打印
import { LinchPrint } from '@linch-tech/print-sdk';
// 订单详情页 - 打印单个订单
async function printOrder(order) {
try {
const result = await LinchPrint.template('order-receipt')
.data({
orderNo: order.id,
orderDate: order.createdAt,
customer: {
name: order.customerName,
phone: order.customerPhone,
address: order.shippingAddress
},
items: order.items.map(item => ({
name: item.productName,
sku: item.sku,
qty: item.quantity,
price: item.unitPrice,
total: item.quantity * item.unitPrice
})),
totalAmount: order.totalAmount,
paymentMethod: order.paymentMethod
})
.print({ copies: 2 });
console.log('打印成功:', result.jobId);
} catch (error) {
console.error('打印失败:', error.message);
}
}2. 批量打印发货单
// 批量发货页面
async function batchPrintShippingLabels(orders) {
const dataList = orders.map(order => ({
orderNo: order.id,
recipient: order.customerName,
phone: order.customerPhone,
address: order.shippingAddress,
items: order.items.map(i => i.productName).join(', '),
weight: order.totalWeight,
courier: order.courierName,
trackingNo: order.trackingNumber
}));
const results = await LinchPrint.template('shipping-label')
.batch(dataList)
.printBatch({
printer: 'Label Printer',
continueOnError: true,
onProgress: (current, total) => {
updateProgressBar(current / total * 100);
}
});
// 统计结果
const success = results.filter(r => r.status === 'completed').length;
const failed = results.filter(r => r.status === 'failed').length;
alert(`打印完成: 成功 ${success} 个, 失败 ${failed} 个`);
}3. React 组件集成
import { useState } from 'react';
import { LinchPrint } from '@linch-tech/print-sdk';
function OrderPrintButton({ order }) {
const [loading, setLoading] = useState(false);
const [printers, setPrinters] = useState([]);
const [selectedPrinter, setSelectedPrinter] = useState('');
// 加载打印机列表
useEffect(() => {
LinchPrint.printers().then(setPrinters);
}, []);
const handlePrint = async () => {
setLoading(true);
try {
await LinchPrint.template('order-tpl')
.data(order)
.print({ printer: selectedPrinter });
toast.success('打印成功');
} catch (e) {
toast.error('打印失败: ' + e.message);
} finally {
setLoading(false);
}
};
return (
<div>
<select value={selectedPrinter} onChange={e => setSelectedPrinter(e.target.value)}>
{printers.map(p => <option key={p} value={p}>{p}</option>)}
</select>
<button onClick={handlePrint} disabled={loading}>
{loading ? '打印中...' : '打印订单'}
</button>
</div>
);
}4. Vue 组件集成
<template>
<div>
<select v-model="selectedPrinter">
<option v-for="p in printers" :key="p" :value="p">{{ p }}</option>
</select>
<button @click="handlePrint" :disabled="loading">
{{ loading ? '打印中...' : '打印订单' }}
</button>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
import { LinchPrint } from '@linch-tech/print-sdk';
const props = defineProps(['order']);
const printers = ref([]);
const selectedPrinter = ref('');
const loading = ref(false);
onMounted(async () => {
printers.value = await LinchPrint.printers();
if (printers.value.length) {
selectedPrinter.value = printers.value[0];
}
});
const handlePrint = async () => {
loading.value = true;
try {
await LinchPrint.template('order-tpl')
.data(props.order)
.print({ printer: selectedPrinter.value });
alert('打印成功');
} catch (e) {
alert('打印失败: ' + e.message);
} finally {
loading.value = false;
}
};
</script>5. Node.js Express 服务
import express from 'express';
import { LinchPrint } from '@linch-tech/print-sdk/node';
const app = express();
app.use(express.json());
// 打印订单接口
app.post('/api/orders/:id/print', async (req, res) => {
try {
const order = await db.orders.findById(req.params.id);
if (!order) {
return res.status(404).json({ error: 'Order not found' });
}
const result = await LinchPrint.template('order-receipt')
.data({
orderNo: order.id,
customer: order.customer,
items: order.items,
totalAmount: order.totalAmount
})
.print({
printer: req.body.printer,
copies: req.body.copies || 1
});
res.json({ success: true, jobId: result.jobId });
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// 批量打印接口
app.post('/api/orders/batch-print', async (req, res) => {
try {
const { orderIds, printer } = req.body;
const orders = await db.orders.findByIds(orderIds);
const results = await LinchPrint.template('order-receipt')
.batch(orders.map(o => ({
orderNo: o.id,
customer: o.customer,
items: o.items,
totalAmount: o.totalAmount
})))
.printBatch({
printer,
continueOnError: true
});
res.json({
success: true,
total: results.length,
completed: results.filter(r => r.status === 'completed').length,
failed: results.filter(r => r.status === 'failed').length
});
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000);6. 预览打印内容
// 生成预览 HTML
const previewHtml = await LinchPrint.template('invoice')
.data(invoiceData)
.preview();
// 在新窗口中显示预览
const previewWindow = window.open('', '_blank');
previewWindow.document.write(previewHtml);
previewWindow.document.close();
// 如需导出 PDF,可选择 "Microsoft Print to PDF" 打印机
await LinchPrint.template('invoice')
.data(invoiceData)
.print({ printer: 'Microsoft Print to PDF' });注意事项
Linch Print 必须运行:SDK 通过 HTTP API 与本地运行的 Linch Print 应用通信,确保应用已启动。
跨域访问:Linch Print 默认允许跨域请求,Web 应用可以直接调用。
模板 ID:使用 Linch Print 设计器创建模板后,在模板列表中查看模板 ID。
数据字段:确保传入的数据字段与模板中定义的变量名一致(支持嵌套路径如
customer.name)。错误处理:所有异步方法可能抛出异常,请使用 try-catch 处理。
License
MIT
