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
|
||||
|
||||
@ -3,6 +3,30 @@ import QRCode from 'qrcode';
|
||||
import { formatMoney, PAYMENT_METHODS } from '@/utils/formatters';
|
||||
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
|
||||
*/
|
||||
@ -367,25 +391,70 @@ const ticketService = {
|
||||
// Imprimir automáticamente si se solicita
|
||||
if (autoPrint) {
|
||||
try {
|
||||
// Convertir PDF a base64 data URI
|
||||
const pdfBase64 = doc.output('datauristring');
|
||||
|
||||
// Intentar imprimir con QZ Tray
|
||||
// Intentar convertir PDF a Imagen y usar QZ Tray (Mejor compatibilidad con térmicas)
|
||||
try {
|
||||
await printService.printPDF(pdfBase64, printerName);
|
||||
console.log('Ticket enviado a la impresora con QZ Tray');
|
||||
} catch (qzError) {
|
||||
console.warn('QZ Tray falló, usando diálogo de impresión:', qzError.message);
|
||||
// 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();
|
||||
|
||||
// Fallback: usar window.print()
|
||||
await printService.printPDFWithDialog(pdfBase64);
|
||||
window.Notify.info('Se abrió el diálogo de impresión');
|
||||
} 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
|
||||
const pdfBase64 = doc.output('datauristring');
|
||||
|
||||
// Intentar QZ Tray Direct PDF
|
||||
try {
|
||||
await printService.printPDF(pdfBase64, printerName);
|
||||
} catch (qzError) {
|
||||
console.warn('QZ Tray PDF falló, abriendo diálogo:', qzError);
|
||||
await printService.printPDFWithDialog(pdfBase64);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error imprimiendo ticket:', error);
|
||||
|
||||
// Mostrar error al usuario
|
||||
window.Notify.warning('No se pudo imprimir automáticamente. Usa el PDF descargado.');
|
||||
console.error('Error general imprimiendo ticket:', error);
|
||||
|
||||
// Fallback final
|
||||
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