fix(pos): print tickets via iframe with measured height and configurable paper width
Some checks failed
CI / lint-and-test (3.11) (push) Has been cancelled
CI / lint-and-test (3.13) (push) Has been cancelled

This commit is contained in:
2026-07-02 23:11:55 +00:00
parent 31b533f9f9
commit 1ff4d80277
4 changed files with 76 additions and 13 deletions

View File

@@ -1597,11 +1597,64 @@ const POS = (() => {
}
function printTicket() {
// Make print area visible for @media print
const area = document.getElementById('ticketPrintArea');
if (area) area.style.display = 'block';
window.print();
setTimeout(() => { if (area) area.style.display = 'none'; }, 500);
const src = document.getElementById('ticketContent');
if (!src) return;
// Paper width: 58 mm -> 48 mm printable; 80 mm -> 72 mm printable.
const paperWidth = parseInt(rc('paper_width', '80'), 10) || 80;
const printWidth = paperWidth === 58 ? 48 : 72;
let iframe = document.getElementById('ticketPrintFrame');
if (!iframe) {
iframe = document.createElement('iframe');
iframe.id = 'ticketPrintFrame';
iframe.style.position = 'fixed';
iframe.style.left = '-9999px';
iframe.style.top = '0';
iframe.style.width = printWidth + 'mm';
iframe.style.border = '0';
document.body.appendChild(iframe);
}
const doc = iframe.contentDocument || iframe.contentWindow.document;
doc.open();
doc.write(`<!doctype html>
<html>
<head>
<meta charset="utf-8">
<style>
@page { margin: 0; size: ${printWidth}mm auto; }
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; height: auto; overflow: visible; background: #fff; color: #000; font-family: 'Courier New', Consolas, monospace; font-size: 9pt; }
body { width: ${printWidth}mm; }
.ticket { width: ${printWidth}mm; padding: 3mm; border: none !important; box-shadow: none !important; }
.item-line-wide { display: grid !important; grid-template-columns: auto 1fr auto auto !important; gap: 2mm; font-size: 8pt; margin-bottom: 1mm; }
.item-line-wide .name { white-space: normal !important; word-break: break-word; overflow: visible; }
.ticket-row, .folio-line, .total-line { display: flex !important; justify-content: space-between; }
.total-line.grand { font-size: 11pt; font-weight: bold; border-top: 0.5mm solid #000; padding-top: 1mm; margin-top: 1mm; }
.store-name { font-size: 12pt; font-weight: bold; text-align: center; margin-bottom: 2px; }
.store-tagline, .store-info { font-size: 8pt; text-align: center; color: #333; margin-bottom: 4px; line-height: 1.3; }
.divider { border: none; border-top: 1px dashed #999; margin: 4px 0; }
.divider-double { border: none; border-top: 2px solid #333; margin: 4px 0; }
.footer-section { text-align: center; margin-top: 6px; font-size: 8pt; color: #555; }
img { max-width: 100%; height: auto; }
</style>
</head>
<body>${src.innerHTML}</body>
</html>`);
doc.close();
// Measure real content height and set exact page size (avoids phantom 3276 mm).
const bodyEl = doc.body;
const heightPx = Math.max(bodyEl.scrollHeight, bodyEl.offsetHeight);
const heightMm = Math.ceil((heightPx * 25.4 / 96) + 5);
const exactPage = doc.createElement('style');
exactPage.textContent = `@page { margin: 0; size: ${printWidth}mm ${heightMm}mm; }`;
doc.head.appendChild(exactPage);
iframe.contentWindow.focus();
setTimeout(() => { iframe.contentWindow.print(); }, 150);
}
// ─── Thermal Printing ─────────────────
@@ -1623,7 +1676,8 @@ const POS = (() => {
return;
}
if (!lastSaleId) { showToast('No hay venta para imprimir'); return; }
const ok = await NexusPrinter.printSale(lastSaleId);
const paperWidth = parseInt(rc('paper_width', '80'), 10) || 80;
const ok = await NexusPrinter.printSale(lastSaleId, paperWidth);
if (ok) {
showToast('Ticket enviado a impresora termica');
} else {