fix: 修复出库单打印预览空白 - iframe 改用 screen 隐藏/print 显示,并等待字体加载
This commit is contained in:
@@ -57,3 +57,22 @@ canvas * {
|
||||
.n-input-number .n-input__input-el {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* 静默打印 iframe:
|
||||
- screen 下隐藏在屏幕下方,避免遮挡 UI
|
||||
- print 下显示在左上角,确保 Chrome/Edge 打印对话框能正确渲染预览
|
||||
(left:-9999px 会使部分浏览器不渲染屏幕外 iframe)。 */
|
||||
@media screen {
|
||||
.op-silent-print-frame {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
z-index: -1;
|
||||
}
|
||||
}
|
||||
@media print {
|
||||
.op-silent-print-frame {
|
||||
opacity: 1;
|
||||
z-index: 999999;
|
||||
top: 0 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,8 +161,8 @@ function parsePaperSize(html: string): { w: string; h: string } {
|
||||
|
||||
/**
|
||||
* 静默打印:瞬态 iframe + srcdoc + window.print(),完成后立即移除。
|
||||
* 注意:iframe 必须带实际纸张尺寸并移出屏幕(不可 0×0,否则 Chrome/Edge
|
||||
* 打印对话框以 0 视口渲染,预览为空白),
|
||||
* 注意:iframe 必须有实际纸张尺寸;将其放在屏幕下方并通过 CSS 在 screen 下隐藏、
|
||||
* print 下显示,避免 left:-9999px 导致某些 Chrome/Edge 版本的打印对话框预览空白。
|
||||
*/
|
||||
function silentPrint(html: string): Promise<void> {
|
||||
return new Promise((resolve, reject) => {
|
||||
@@ -173,21 +173,31 @@ function silentPrint(html: string): Promise<void> {
|
||||
const { w, h } = parsePaperSize(html)
|
||||
const iframe = document.createElement('iframe')
|
||||
iframe.setAttribute('aria-hidden', 'true')
|
||||
// 移到屏幕外但保留纸张尺寸视口,保证打印对话框预览可见
|
||||
iframe.style.cssText = `position:fixed;left:-9999px;top:0;width:${w};height:${h};border:0;`
|
||||
// 通过 class + @media 在 screen 下隐藏、print 下显示,避免屏幕外渲染问题
|
||||
iframe.className = 'op-silent-print-frame'
|
||||
iframe.style.cssText = `position:fixed;left:0;top:100vh;width:${w};height:${h};border:0;`
|
||||
let removed = false
|
||||
const cleanup = () => {
|
||||
if (removed) return
|
||||
removed = true
|
||||
setTimeout(() => iframe.remove(), 300)
|
||||
}
|
||||
iframe.onload = () => {
|
||||
iframe.onload = async () => {
|
||||
const cw = iframe.contentWindow
|
||||
if (!cw) {
|
||||
const cd = iframe.contentDocument
|
||||
if (!cw || !cd) {
|
||||
cleanup()
|
||||
reject(new Error('iframe 无 contentWindow'))
|
||||
return
|
||||
}
|
||||
// 等待字体就绪,避免打印预览空白/缺字
|
||||
if (cd.fonts && cd.fonts.ready) {
|
||||
try {
|
||||
await Promise.race([cd.fonts.ready, new Promise((r) => setTimeout(r, 2000))])
|
||||
} catch {
|
||||
/* ignore */
|
||||
}
|
||||
}
|
||||
// onafterprint 在用户确认打印或取消时都会触发
|
||||
cw.onafterprint = () => {
|
||||
cleanup()
|
||||
|
||||
Reference in New Issue
Block a user