import QRCode from 'qrcode'; export interface QRPrintItem { type: 'asset' | 'location'; code: string; title: string; // e.g. "[ HM IT ASSET ]" or "[ HM LOCATION ]" subtitle?: string; // e.g. "가을-PC(i5-12400F)" or "기술개발센터 서버실" dept?: string; // e.g. "전산" or "B-03 랙" user?: string; // e.g. "박노석" date?: string; // e.g. "2024-08-05" } /** * QR 라벨 인쇄 유틸리티 클래스 */ export class QRPrinter { private static styleId = 'qr-print-style'; private static containerId = 'label-print-container'; /** * 인쇄 전용 CSS 스타일 주입 */ private static injectStyles() { if (document.getElementById(this.styleId)) return; const style = document.createElement('style'); style.id = this.styleId; style.innerHTML = ` /* 화면에서는 인쇄 컨테이너 숨김 */ #${this.containerId} { display: none; } @media print { /* 화면 내 모든 요소 숨김 */ body > *:not(#${this.containerId}) { display: none !important; } /* 인쇄 전용 컨테이너 표시 */ #${this.containerId} { display: block !important; position: absolute; left: 0; top: 0; width: 50mm; height: 30mm; margin: 0; padding: 0; box-sizing: border-box; background: #fff; } /* 페이지 규격 설정 */ @page { size: 50mm 30mm; margin: 0; } /* 개별 라벨 스타일 */ .print-label-item { display: flex !important; flex-direction: row; width: 50mm; height: 30mm; box-sizing: border-box; padding: 2.5mm; page-break-after: always; font-family: 'Pretendard Variable', sans-serif; color: #000; background: #fff; overflow: hidden; } .print-label-item:last-child { page-break-after: avoid; } /* 왼쪽 명세 영역 */ .label-details { width: 30mm; display: flex; flex-direction: column; justify-content: space-between; font-size: 6.5pt; line-height: 1.25; text-align: left; padding-right: 1mm; word-break: break-all; } .label-header { font-size: 7.5pt; font-weight: 800; border-bottom: 0.5px solid #000; padding-bottom: 0.5mm; margin-bottom: 0.5mm; color: #000; } .label-row { display: flex; margin-bottom: 0.2mm; } .label-row .row-title { font-weight: 700; width: 9.5mm; flex-shrink: 0; } .label-row .row-value { flex: 1; } /* 오른쪽 QR 영역 */ .label-qr-wrapper { width: 15mm; display: flex; flex-direction: column; justify-content: center; align-items: center; } .label-qr-canvas { width: 14mm !important; height: 14mm !important; display: block; } .label-qr-code-text { font-size: 5.5pt; font-weight: 700; margin-top: 1mm; text-align: center; width: 15mm; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } } `; document.head.appendChild(style); } /** * 라벨 인쇄 실행 */ public static async print(items: QRPrintItem[]): Promise { if (items.length === 0) return; this.injectStyles(); // 기존 컨테이너 제거 const oldContainer = document.getElementById(this.containerId); if (oldContainer) oldContainer.remove(); // 새 인쇄 컨테이너 생성 const container = document.createElement('div'); container.id = this.containerId; document.body.appendChild(container); for (let i = 0; i < items.length; i++) { const item = items[i]; const labelDiv = document.createElement('div'); labelDiv.className = 'print-label-item'; // QR 접속 URL 정의 const paramName = item.type === 'asset' ? 'asset' : 'loc'; const qrUrl = `${window.location.origin}/mobile?${paramName}=${encodeURIComponent(item.code)}`; // HTML 구성 if (item.type === 'asset') { labelDiv.innerHTML = `
${item.title}
자산번호 : ${item.code}
자 산 명 : ${item.subtitle || '-'}
부 서 : ${item.dept || '-'}
사 용 자 : ${item.user || '-'}
${item.code}
`; } else { // Location 라벨 레이아웃 labelDiv.innerHTML = `
${item.title}
위치코드 : ${item.code}
구 역 : ${item.subtitle || '-'}
상세위치 : ${item.dept || '-'}
${item.code}
`; } container.appendChild(labelDiv); // QR 코드 렌더링 const canvas = document.getElementById(`qr-canvas-${i}`) as HTMLCanvasElement; if (canvas) { await QRCode.toCanvas(canvas, qrUrl, { margin: 0, width: 100, errorCorrectionLevel: 'H' }); } } // 약간의 딜레이를 주어 QR 코드가 완전히 렌더링되도록 함 setTimeout(() => { window.print(); // 인쇄 완료 후 컨테이너 정리 window.onafterprint = () => { container.remove(); }; }, 250); } }