feat: agregar funcionalidad para imprimir imágenes en base64 y mejorar la impresión de tickets
This commit is contained in:
parent
21b28b5bff
commit
4dfeeeea20
@ -341,6 +341,46 @@ class PrintService {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Imprimir imagen base64
|
||||||
|
* @param {string} base64Image - Imagen en base64 (png, jpg)
|
||||||
|
* @param {string} printerName - Nombre de la impresora (opcional)
|
||||||
|
* @returns {Promise}
|
||||||
|
*/
|
||||||
|
async printImage(base64Image, printerName = null) {
|
||||||
|
try {
|
||||||
|
await this.connect();
|
||||||
|
|
||||||
|
const printer = printerName || this.getSavedPrinter() || await this.getDefaultPrinter();
|
||||||
|
|
||||||
|
const config = this.qz.configs.create(printer, {
|
||||||
|
scaleContent: true
|
||||||
|
});
|
||||||
|
|
||||||
|
// Asegurar data URI
|
||||||
|
let imgData = base64Image;
|
||||||
|
if (!imgData.startsWith('data:image')) {
|
||||||
|
imgData = `data:image/png;base64,${base64Image}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
type: 'pixel',
|
||||||
|
format: 'image',
|
||||||
|
flavor: 'base64',
|
||||||
|
data: imgData
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
await this.qz.print(config, data);
|
||||||
|
console.log('Imagen impresa exitosamente');
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error imprimiendo imagen:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exportar instancia singleton
|
// Exportar instancia singleton
|
||||||
|
|||||||
@ -3,6 +3,30 @@ import QRCode from 'qrcode';
|
|||||||
import { formatMoney, PAYMENT_METHODS } from '@/utils/formatters';
|
import { formatMoney, PAYMENT_METHODS } from '@/utils/formatters';
|
||||||
import printService from '@Services/printService';
|
import printService from '@Services/printService';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cargar PDF.js dinámicamente desde CDN
|
||||||
|
*/
|
||||||
|
async function loadPdfJs() {
|
||||||
|
if (window.pdfjsLib) return window.pdfjsLib;
|
||||||
|
|
||||||
|
console.log('Cargando PDF.js desde CDN...');
|
||||||
|
|
||||||
|
// Cargar script principal
|
||||||
|
await new Promise((resolve, reject) => {
|
||||||
|
const script = document.createElement('script');
|
||||||
|
script.src = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js';
|
||||||
|
script.integrity = 'sha512-q+GRHzvH4z5fXN5WjM8oKGTf4PxcX1QzGjZfrFqVBqAdgEecT0kFvvn7uZ2+GL3LMDM9M79cfsREi+T17J9wMA==';
|
||||||
|
script.crossOrigin = 'anonymous';
|
||||||
|
script.onload = resolve;
|
||||||
|
script.onerror = reject;
|
||||||
|
document.head.appendChild(script);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configurar worker
|
||||||
|
window.pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
|
||||||
|
return window.pdfjsLib;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Servicio para generar tickets de venta en formato PDF
|
* Servicio para generar tickets de venta en formato PDF
|
||||||
*/
|
*/
|
||||||
@ -367,25 +391,70 @@ const ticketService = {
|
|||||||
// Imprimir automáticamente si se solicita
|
// Imprimir automáticamente si se solicita
|
||||||
if (autoPrint) {
|
if (autoPrint) {
|
||||||
try {
|
try {
|
||||||
|
// Intentar convertir PDF a Imagen y usar QZ Tray (Mejor compatibilidad con térmicas)
|
||||||
|
try {
|
||||||
|
// Obtener Blob del PDF
|
||||||
|
const pdfBlob = doc.output('blob');
|
||||||
|
const pdfUrl = URL.createObjectURL(pdfBlob);
|
||||||
|
|
||||||
|
// Cargar librería PDF.js
|
||||||
|
const pdfjs = await loadPdfJs();
|
||||||
|
|
||||||
|
// Cargar documento
|
||||||
|
const pdf = await pdfjs.getDocument(pdfUrl).promise;
|
||||||
|
const page = await pdf.getPage(1); // Página 1
|
||||||
|
|
||||||
|
// Configurar escala (2.0 da buena nitidez para tickets)
|
||||||
|
const scale = 2.0;
|
||||||
|
const viewport = page.getViewport({ scale });
|
||||||
|
|
||||||
|
// Crear canvas temporal
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
canvas.height = viewport.height;
|
||||||
|
canvas.width = viewport.width;
|
||||||
|
|
||||||
|
// Renderizar PDF en Canvas
|
||||||
|
await page.render({
|
||||||
|
canvasContext: context,
|
||||||
|
viewport: viewport
|
||||||
|
}).promise;
|
||||||
|
|
||||||
|
// Convertir Canvas a Imagen Base64
|
||||||
|
const imgData = canvas.toDataURL('image/png');
|
||||||
|
|
||||||
|
// Enviar imagen a QZ Tray
|
||||||
|
await printService.printImage(imgData, printerName);
|
||||||
|
|
||||||
|
console.log('Ticket impreso como imagen con QZ Tray');
|
||||||
|
|
||||||
|
// Limpieza
|
||||||
|
URL.revokeObjectURL(pdfUrl);
|
||||||
|
canvas.remove();
|
||||||
|
|
||||||
|
} catch (imgError) {
|
||||||
|
console.warn('Falló impresión como imagen, intentando método nativo PDF:', imgError);
|
||||||
|
|
||||||
|
// Fallback: Intentar mandar el PDF directo (puede fallar en térmicas) o usar diálogo
|
||||||
// Convertir PDF a base64 data URI
|
// Convertir PDF a base64 data URI
|
||||||
const pdfBase64 = doc.output('datauristring');
|
const pdfBase64 = doc.output('datauristring');
|
||||||
|
|
||||||
// Intentar imprimir con QZ Tray
|
// Intentar QZ Tray Direct PDF
|
||||||
try {
|
try {
|
||||||
await printService.printPDF(pdfBase64, printerName);
|
await printService.printPDF(pdfBase64, printerName);
|
||||||
console.log('Ticket enviado a la impresora con QZ Tray');
|
|
||||||
} catch (qzError) {
|
} catch (qzError) {
|
||||||
console.warn('QZ Tray falló, usando diálogo de impresión:', qzError.message);
|
console.warn('QZ Tray PDF falló, abriendo diálogo:', qzError);
|
||||||
|
|
||||||
// Fallback: usar window.print()
|
|
||||||
await printService.printPDFWithDialog(pdfBase64);
|
await printService.printPDFWithDialog(pdfBase64);
|
||||||
window.Notify.info('Se abrió el diálogo de impresión');
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error imprimiendo ticket:', error);
|
console.error('Error general imprimiendo ticket:', error);
|
||||||
|
|
||||||
// Mostrar error al usuario
|
// Fallback final
|
||||||
window.Notify.warning('No se pudo imprimir automáticamente. Usa el PDF descargado.');
|
const pdfBase64 = doc.output('datauristring');
|
||||||
|
await printService.printPDFWithDialog(pdfBase64);
|
||||||
|
|
||||||
|
window.Notify.warning('Hubo un problema con la impresión automática. Se abrió el diálogo del sistema.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user