/**
* 🔥 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);
};
}