前端集成Lodop实现复杂业务单据打印技能实践
一、技能选型与预备工作1.1 打印技能方案对比
方案优点缺点实用场景浏览器打印无需插件、跨平台格式控制差、无法精准分页简单报表打印Lodop精准控制、功能强大需要安装插件复杂业务单据打印PDF打印格式统一、跨平台依靠阅读器、动态内容受限标准化文档输出原生驱动打印直接控制打印机开辟复杂度高特种装备对接 1.2 情况搭建步骤
<!-- 引入Lodop基础依赖 -->
<script src="http://localhost:8000/CLodopfuncs.js"></script>
<script src="http://localhost:8000/LodopFuncs.js"></script>
<!-- 兼容性检测 -->
<script>
function checkLodop() {
try {
const LODOP = getCLodop();
if (!LODOP) {
console.error("未检测到CLodop服务,请先安装打印插件");
window.open('http://www.lodop.net/download.html');
return false;
}
return true;
} catch (e) {
console.error("Lodop初始化异常:", e);
return false;
}}
</script>
二、核心打印功能实现
2.1 连续打印实现(批量订单)
function printContinuousOrders(orders) {const LODOP = getCLodop(); LODOP.PRINT_INIT("批量订单打印");LODOP.SET_PRINT_PAGESIZE(1, '210mm', '297mm', 'A4'); orders.forEach((order, index) => { LODOP.ADD_PRINT_HTM( "10mm", "10mm", "190mm", "277mm", generateOrderHtml(order)
);
if (index < orders.length - 1) { LODOP.NewPage();
}
});
LODOP.PREVIEW();
}
// 动态生成订单HTML模板
function generateOrderHtml(order) {return
`<div class="order-box">
<h2>订单编号:${order.no}</h2> <table border="1"> <tr> <th>商品名称</th> <th>规格</th> <th>数量</th> <th>单价</th> </tr>
${order.items.map(item => ` <tr>
<td>${item.name}</td> <td>${item.spec}</td> <td>${item.quantity}</td> <td>${item.price.toFixed(2)}</td> </tr>`).join('')}
</table>
<div class="total">总金额:¥${order.total.toFixed(2)}</div> </div>`;
}
2.2 智能分页打印(主动分页处理)
function smartPagePrint(htmlContent) {const LODOP = getCLodop();
const PAGE_HEIGHT = 277;
// A4可打印高度(mm)
LODOP.PRINT_INIT("智能分页打印");LODOP.SET_PRINT_PAGESIZE(1, '210mm', '297mm', 'A4');
let currentY = 10;
let pageIndex = 1; LODOP.ADD_PRINT_HTM(`${currentY}mm`, "10mm", "190mm", "277mm",htmlContent); // 自动分页检测
while(true) {
const contentHeight = LODOP.GET_PRINT_HEIGHT(pageIndex); if (contentHeight <= PAGE_HEIGHT)
break; LODOP.SET_PRINT_MODE("CONTENT_SPLIT", pageIndex, 1);
pageIndex++;
}
LODOP.SET_PRINT_MODE("FULL_PAGE", true);LODOP.PREVIEW();
}
2.3 标签打印实现(100x150mm标签)
function printLabels(labels) {
const LODOP = getCLodop();
const LABEL_WIDTH = 100;
const LABEL_HEIGHT = 150;
LODOP.PRINT_INIT("标签打印");LODOP.SET_PRINT_PAGESIZE(3, `${LABEL_WIDTH}mm`, `${LABEL_HEIGHT}mm`, '自定义标签');
// 设置标签模板
LODOP.ADD_PRINT_RECT("1mm", "1mm", "98mm", "148mm", 0, 1); labels.forEach((label, index) => { const row = Math.floor(index / 3); const col = index % 3; LODOP.ADD_PRINT_TEXT( "10mm", `${10 + col*(LABEL_WIDTH+5)}mm`, "90mm", "20mm",label.title); LODOP.ADD_PRINT_BARCODE("30mm", `${10 + col*(LABEL_WIDTH+5)}mm`, "90mm","40mm","128Auto", label.barcode);
if ((index + 1) % 6 === 0) { LODOP.NewPage();
}
}); LODOP.SET_PRINT_MODE("POS_BASEON_PAPER", true);
LODOP.PREVIEW();
}
三、高级功能实现
3.1 打印任务队列管理
class PrintQueue {
constructor() {
this.queue = [];
this.isPrinting = false;
}
addTask(taskFn) { this.queue.push(taskFn);
if (!this.isPrinting) this.processNext();
}
processNext() {
if (this.queue.length === 0) {
this.isPrinting = false;
return;
}
this.isPrinting = true;
const task = this.queue.shift(); try {
task(() => {
setTimeout(() => this.processNext(), 500);
});
} catch (e) {
console.error('打印任务失败:', e); this.processNext();
}
}}
// 使用示例
const queue = new PrintQueue();
queue.addTask((done) => {printContinuousOrders(orderList);LODOP.On_Return = (taskID, value) => { if(value) done();
};
});
3.2 打印模板动态天生
function createDynamicTemplate(data, templateConfig) {
const { fields, layout, styles } = templateConfig;
return ` <style> .template-container { width: ${layout.width}mm;height: ${layout.height}mm; font-family: ${styles.fontFamily}; padding: ${layout.padding}mm; } ${styles.customCSS} </style> <div class="template-container"> ${fields.map(field => ` <div class="field ${field.className}" style="position: absolute; left: ${field.x}mm; top: ${field.y}mm; width: ${field.width}mm; height: ${field.height}mm;"> ${data} </div> `).join('')} </div>`;}
// 配置示例
const config = {
layout: {
width: 210,
height: 297,
padding: 5
},
fields: [
{
key: 'orderNo',
x: 10,
y: 15,
width: 50,
height: 10,
className: 'order-number'
},
// 更多字段配置...
],
styles: {
fontFamily: 'SimSun',
customCSS: ` .order-number { font-size: 14pt; font-weight: bold; } `
}};
四、常见题目解决方案
4.1 打印偏移校准
function calibratePrinter() {
const LODOP = getCLodop();
// 生成校准模板
LODOP.PRINT_INIT("打印机校准");LODOP.ADD_PRINT_LINE("0mm", "0mm", "0mm", "210mm", 0, 1);LODOP.ADD_PRINT_LINE("0mm", "0mm", "297mm", "0mm", 0, 1);LODOP.ADD_PRINT_TEXT("145mm", "95mm", "20mm", "10mm", "中线校准标记");
// 保存偏移量
LODOP.SET_PRINT_MODE("OFFSET_PERCENT", (dx, dy) => { localStorage.setItem('PRINT_OFFSET_X', dx); localStorage.setItem('PRINT_OFFSET_Y', dy);}); LODOP.PREVIEW();}
// 应用校准参数
function applyCalibration() {
const dx = localStorage.getItem('PRINT_OFFSET_X') || 0;
const dy = localStorage.getItem('PRINT_OFFSET_Y') || 0; LODOP.SET_PRINT_MODE("POS_BASEON_PAPER", true);LODOP.SET_PRINT_MODE("OFFSET_PERCENT", dx, dy);}
4.2 打印异常处理
function safePrint(printFn) {
try {
if (!checkLodop())
return;
printFn();
LODOP.On_Return = (taskID, success) => {
if (!success) {
console.error(`打印任务失败,错误码:
${LODOP.GetStatus()}`); showErrorMessage(LODOP.GetStatusDes());
}
};
} catch (e) {
console.error("打印过程发生异常:", e);
showErrorMessage("打印系统异常,请联系管理员");}}
function showErrorMessage(msg) {
const errorBox = document.createElement('div');errorBox.className = 'print-error';errorBox.innerHTML = `<div class="error-header">打印错误</div> <div class="error-content">${msg}</div> <button onclick="this.parentElement.remove()">关闭</button>`;document.body.appendChild(errorBox);
}
五、性能优化实践
5.1 打印缓存计谋
const templateCache = new Map();
function getCachedTemplate(templateKey, generator) {
if (templateCache.has(templateKey)) {
return
templateCache.get(templateKey);
}
const html = generator();
const parser = new DOMParser();
const doc = parser.parseFromString(html, 'text/html'); templateCache.set(templateKey, doc);return doc;}
// 使用示例
function printOrder(order) {
const cachedDoc = getCachedTemplate('order', () => generateOrderHtml(defaultOrder)); const clone = cachedDoc.cloneNode(true);// 填充动态数据...
const html = clone.documentElement.outerHTML; LODOP.ADD_PRINT_HTM("10mm", "10mm", "190mm", "277mm", html);}
5.2 批量数据分块打印
async function chunkedPrint(data, chunkSize = 50) {
for (let i = 0; i < data.length; i += chunkSize) {
const chunk = data.slice(i, i + chunkSize);
await new Promise(resolve => {
printContinuousOrders(chunk);
LODOP.On_Return = (taskID, success) => {
if (success) resolve();
};
});
// 防止内存泄漏
LODOP.CLEAR_PRINT_STYLE();
if (i + chunkSize < data.length) {
LODOP.NewPageA();
}
}}
六、总结与扩展
本文详细讲解了基于Lodop的复杂打印场景实现方案,涵盖以下关键技能点:
[*]多类型打印控制:通过精确的坐标盘算实现标签打印、智能分页等复杂需求
[*]打印任务管理:引入队列机制确保打印任务有序实行
[*]动态模板系统:实现设置化模板天生,提升系统机动性
[*]稳固性增强:完满的异常处理机制和校准方案扩展方向建议:- 结合WebSocket实现远程打印监控- 集成电子署名实现单据防伪- 开辟可视化的模板设计器- 对接称重装备实现主动打标通过以上技能方案,企业可以构建稳固可靠的打印服务系统,满足各类业务场景的打印需求,同时为后续的物联网集成打下结实基础
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]