/** * 🔥 Vue后台专用 - 打印指定DIV(样式完全还原 + 无侧边栏/导航) * 适配 Element Plus / scoped样式 / 后台管理系统 */ export function printVueDiv(elementId: string, title: string = '打印') { const el = document.getElementById(elementId); if (!el) { console.error('未找到打印元素'); return; } const win = window.open('', '_blank', 'width=1000,height=800'); if (!win) return; // ============================================== // 【核心1】复制 全局样式 + Element Plus 样式 // ============================================== const styles = Array.from(document.querySelectorAll('link[rel="stylesheet"], style:not([scoped])')) .map((item) => item.outerHTML) .join(''); // ============================================== // 【核心2】手动注入打印区域的 scoped 样式(关键!) // ============================================== const printScopeStyle = ` `; // ============================================== // 【核心3】写入新窗口 // ============================================== win.document.write(` ${title} ${styles} ${printScopeStyle} ${el.outerHTML} `); win.document.close(); win.onload = () => { setTimeout(() => { win.print(); win.close(); }, 300); }; } /** * 打印指定 DOM 元素(绝对不会打印其他内容) * @param elementId 目标 div 的 id * @param title 打印标题(可选) */ export function printDivPure(elementId: string, title: string = '打印') { // 1. 获取目标元素 const targetElement = document.getElementById(elementId); if (!targetElement) { console.error(`未找到 id 为 "${elementId}" 的元素`); return; } // 2. 保存原页面的所有内容 const originalBodyContent = document.body.innerHTML; // 3. 克隆目标元素 const cloneElement = targetElement.cloneNode(true) as HTMLElement; // 4. 【核心】把 body 替换成只有目标元素的内容 document.body.innerHTML = ''; // 添加打印专用样式 const printStyle = document.createElement('style'); printStyle.innerHTML = ` @page { size: A4; margin: 10mm; } body { margin: 0; padding: 20px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; } `; document.head.appendChild(printStyle); // 插入目标元素 document.body.appendChild(cloneElement); // 5. 打印 window.print(); // 6. 【核心】打印完恢复原页面内容 setTimeout(() => { document.body.innerHTML = originalBodyContent; document.head.removeChild(printStyle); // 强制刷新一下 Vue 组件(避免恢复后事件丢失) window.location.reload(); }, 100); } /** * 打印指定 DOM 元素(新窗口法加强版,不刷新页面) * @param elementId 目标 div 的 id * @param title 打印标题(可选) */ export function printDivNewWindow(elementId: string, title: string = '打印') { const targetElement = document.getElementById(elementId); if (!targetElement) { console.error(`未找到 id 为 "${elementId}" 的元素`); return; } const printWindow = window.open('', '_blank', 'width=800,height=1000'); if (!printWindow) { console.error('无法打开新窗口,请检查浏览器弹窗拦截设置'); return; } // 【关键】深度克隆目标元素,包括所有子节点 const clone = targetElement.cloneNode(true) as HTMLElement; printWindow.document.write(` ${title} ${Array.from(document.querySelectorAll('link[rel="stylesheet"]')) .map((l) => l.outerHTML) .join('')} ${Array.from(document.querySelectorAll('style')) .map((s) => s.outerHTML) .join('')} `); // 把克隆的元素插入到新窗口 printWindow.document.body.appendChild(clone); printWindow.document.close(); // 等待加载完成后打印 printWindow.onload = () => { printWindow.focus(); setTimeout(() => { printWindow.print(); printWindow.close(); }, 300); }; } /** * 🔥 Vue后台专用 - 票据专用打印(固定尺寸 宽10cm 高25cm) * 新窗口打印指定DIV、还原原样式、屏蔽后台侧边栏/导航、适配Element Plus * 纸张规格:10cm(宽) × 25cm(高) 票据纸 */ export function printTicketDiv(elementId: string, title: string = '票据打印', callback?: () => void) { const el = document.getElementById(elementId); if (!el) { console.error('未找到打印元素'); return; } const win = window.open('', '_blank', 'width=1200,height=1000'); if (!win) return; const styles = ''; const printScopeStyle = ` `; const html = ` ${title} ${styles} ${printScopeStyle} ${el.outerHTML} `; win.document.write(html); win.document.close(); win.onload = () => { setTimeout(() => { win.print(); win.close(); callback && callback(); }, 300); }; }