From b8e21948c1b58b1d6d468404612ad75c1dd38c00 Mon Sep 17 00:00:00 2001 From: 86156 <823267011@qq.com> Date: Fri, 9 Jan 2026 13:47:41 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=AD=A3=E5=89=8D=E7=AB=AF=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../panels/LabelRender/OuterTagPreview.vue | 138 +++++++++++++----- .../LabelRender/ProductionTagPreview.vue | 130 ++++++++++++----- 2 files changed, 201 insertions(+), 67 deletions(-) diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue index eb87ba8f..060df98e 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/OuterTagPreview.vue @@ -156,53 +156,105 @@ export default { } }, mounted() { - // 监听打印事件,计算缩放比例 - window.addEventListener('beforeprint', this.calculatePrintScale); - window.addEventListener('afterprint', this.resetPrintScale); + // 使用 matchMedia 监听打印状态(更可靠) + this.printMediaQuery = window.matchMedia('print'); + this.printMediaQuery.addListener(this.handlePrintMediaChange); + + // 监听打印事件作为备用 + window.addEventListener('beforeprint', this.handleBeforePrint); + window.addEventListener('afterprint', this.handleAfterPrint); + // 计算初始缩放比例 this.$nextTick(() => { this.calculatePrintScale(); }); }, beforeDestroy() { - window.removeEventListener('beforeprint', this.calculatePrintScale); - window.removeEventListener('afterprint', this.resetPrintScale); + if (this.printMediaQuery) { + this.printMediaQuery.removeListener(this.handlePrintMediaChange); + } + window.removeEventListener('beforeprint', this.handleBeforePrint); + window.removeEventListener('afterprint', this.handleAfterPrint); }, methods: { + handlePrintMediaChange(mq) { + if (mq.matches) { + // 进入打印模式 + this.calculatePrintScale(); + } else { + // 退出打印模式 + this.resetPrintScale(); + } + }, + handleBeforePrint() { + // 延迟计算,确保DOM已更新 + setTimeout(() => { + this.calculatePrintScale(); + }, 100); + }, + handleAfterPrint() { + this.resetPrintScale(); + }, calculatePrintScale() { this.$nextTick(() => { const container = this.$el; if (!container) return; // 纸张尺寸:180mm x 100mm - // 1mm ≈ 3.779527559px (96 DPI) - const paperWidth = 180 * 3.779527559; // 约 680.3px - const paperHeight = 100 * 3.779527559; // 约 377.95px + // 在打印时,使用 mm 单位更准确 + // 1mm = 3.779527559px (96 DPI) 或 1mm = 3.779527559px (72 DPI) + // 为了更准确,我们直接使用 mm 转 px 的通用计算 + const dpi = 96; // 标准 DPI + const mmToPx = dpi / 25.4; // 1mm = 3.779527559px - // 获取内容实际尺寸 + const paperWidthMm = 180; + const paperHeightMm = 100; + const marginMm = 2; + + const paperWidthPx = paperWidthMm * mmToPx; + const paperHeightPx = paperHeightMm * mmToPx; + const marginPx = marginMm * mmToPx; + + // 获取内容实际尺寸(在屏幕上的尺寸) const rect = container.getBoundingClientRect(); - const contentWidth = rect.width; - const contentHeight = rect.height; + let contentWidth = rect.width; + let contentHeight = rect.height; - // 计算缩放比例(留出2mm边距) - const margin = 2 * 3.779527559; // 约 7.56px - const availableWidth = paperWidth - margin * 2; - const availableHeight = paperHeight - margin * 2; + // 如果尺寸为0或无效,尝试使用 scrollWidth/scrollHeight + if (contentWidth === 0 || contentHeight === 0) { + contentWidth = container.scrollWidth || contentWidth; + contentHeight = container.scrollHeight || contentHeight; + } - const scaleX = availableWidth / contentWidth; - const scaleY = availableHeight / contentHeight; + // 计算可用空间(减去边距) + const availableWidth = paperWidthPx - marginPx * 2; + const availableHeight = paperHeightPx - marginPx * 2; - // 取较小的缩放比例,确保内容完全适配 - this.printScale = Math.min(scaleX, scaleY, 1); // 不超过1,不放大 + // 计算缩放比例 + const scaleX = contentWidth > 0 ? availableWidth / contentWidth : 1; + const scaleY = contentHeight > 0 ? availableHeight / contentHeight : 1; - // 设置CSS变量 + // 取较小的缩放比例,确保内容完全适配(不超过1,不放大) + this.printScale = Math.min(scaleX, scaleY, 1); + + // 设置CSS变量和内联样式 container.style.setProperty('--print-scale', this.printScale); + container.style.setProperty('--paper-width', `${paperWidthMm}mm`); + container.style.setProperty('--paper-height', `${paperHeightMm}mm`); + + console.log('打印缩放计算:', { + contentSize: { width: contentWidth, height: contentHeight }, + paperSize: { width: paperWidthPx, height: paperHeightPx }, + scale: this.printScale + }); }); }, resetPrintScale() { this.printScale = 1; if (this.$el) { this.$el.style.setProperty('--print-scale', 1); + this.$el.style.removeProperty('--paper-width'); + this.$el.style.removeProperty('--paper-height'); } } } @@ -326,44 +378,59 @@ export default { @media print { @page { size: 180mm 100mm; - margin: 0; - padding: 0; + margin: 0 !important; + padding: 0 !important; } * { - -webkit-print-color-adjust: exact; - print-color-adjust: exact; + -webkit-print-color-adjust: exact !important; + print-color-adjust: exact !important; } - html, body { + html { margin: 0 !important; padding: 0 !important; - width: 180mm; - height: 100mm; - overflow: hidden; + width: 180mm !important; + height: 100mm !important; + overflow: hidden !important; } - /* 隐藏所有其他内容,只显示标签 */ + body { + margin: 0 !important; + padding: 0 !important; + width: 180mm !important; + height: 100mm !important; + overflow: hidden !important; + position: relative !important; + } + + /* 隐藏所有其他内容,只显示标签容器 */ body > *:not(.label-container) { display: none !important; } + /* 确保标签容器是 body 的直接子元素且唯一可见 */ .label-container { - /* 使用固定纸张尺寸 */ + /* 强制使用纸张尺寸 */ width: 180mm !important; height: 100mm !important; max-width: 180mm !important; max-height: 100mm !important; + min-width: 180mm !important; + min-height: 100mm !important; + padding: 2mm !important; margin: 0 !important; - /* 防止分页 */ + /* 防止分页 - 多重保护 */ page-break-inside: avoid !important; break-inside: avoid !important; page-break-after: avoid !important; break-after: avoid !important; page-break-before: avoid !important; break-before: avoid !important; + orphans: 999 !important; + widows: 999 !important; /* 确保内容不溢出 */ overflow: hidden !important; @@ -373,8 +440,13 @@ export default { transform: scale(var(--print-scale, 1)) !important; transform-origin: top left !important; - /* 计算缩放后的实际占用空间,确保不超出纸张 */ - position: relative !important; + /* 定位和布局 */ + position: absolute !important; + top: 0 !important; + left: 0 !important; + + /* 确保缩放后不超出纸张 */ + display: block !important; } /* 打印时调整字体和间距,使用相对单位自动缩放 */ diff --git a/klp-ui/src/views/wms/coil/panels/LabelRender/ProductionTagPreview.vue b/klp-ui/src/views/wms/coil/panels/LabelRender/ProductionTagPreview.vue index ab07b665..5fc811cf 100644 --- a/klp-ui/src/views/wms/coil/panels/LabelRender/ProductionTagPreview.vue +++ b/klp-ui/src/views/wms/coil/panels/LabelRender/ProductionTagPreview.vue @@ -90,53 +90,96 @@ export default { } }, mounted() { - // 监听打印事件,计算缩放比例 - window.addEventListener('beforeprint', this.calculatePrintScale); - window.addEventListener('afterprint', this.resetPrintScale); + // 使用 matchMedia 监听打印状态(更可靠) + this.printMediaQuery = window.matchMedia('print'); + this.printMediaQuery.addListener(this.handlePrintMediaChange); + + // 监听打印事件作为备用 + window.addEventListener('beforeprint', this.handleBeforePrint); + window.addEventListener('afterprint', this.handleAfterPrint); + // 计算初始缩放比例 this.$nextTick(() => { this.calculatePrintScale(); }); }, beforeDestroy() { - window.removeEventListener('beforeprint', this.calculatePrintScale); - window.removeEventListener('afterprint', this.resetPrintScale); + if (this.printMediaQuery) { + this.printMediaQuery.removeListener(this.handlePrintMediaChange); + } + window.removeEventListener('beforeprint', this.handleBeforePrint); + window.removeEventListener('afterprint', this.handleAfterPrint); }, methods: { + handlePrintMediaChange(mq) { + if (mq.matches) { + // 进入打印模式 + this.calculatePrintScale(); + } else { + // 退出打印模式 + this.resetPrintScale(); + } + }, + handleBeforePrint() { + // 延迟计算,确保DOM已更新 + setTimeout(() => { + this.calculatePrintScale(); + }, 100); + }, + handleAfterPrint() { + this.resetPrintScale(); + }, calculatePrintScale() { this.$nextTick(() => { const container = this.$el; if (!container) return; // 纸张尺寸:180mm x 100mm - // 1mm ≈ 3.779527559px (96 DPI) - const paperWidth = 180 * 3.779527559; // 约 680.3px - const paperHeight = 100 * 3.779527559; // 约 377.95px + const dpi = 96; // 标准 DPI + const mmToPx = dpi / 25.4; // 1mm = 3.779527559px + + const paperWidthMm = 180; + const paperHeightMm = 100; + const marginMm = 2; + + const paperWidthPx = paperWidthMm * mmToPx; + const paperHeightPx = paperHeightMm * mmToPx; + const marginPx = marginMm * mmToPx; // 获取内容实际尺寸 const rect = container.getBoundingClientRect(); - const contentWidth = rect.width; - const contentHeight = rect.height; + let contentWidth = rect.width; + let contentHeight = rect.height; - // 计算缩放比例(留出2mm边距) - const margin = 2 * 3.779527559; // 约 7.56px - const availableWidth = paperWidth - margin * 2; - const availableHeight = paperHeight - margin * 2; + // 如果尺寸为0或无效,尝试使用 scrollWidth/scrollHeight + if (contentWidth === 0 || contentHeight === 0) { + contentWidth = container.scrollWidth || contentWidth; + contentHeight = container.scrollHeight || contentHeight; + } - const scaleX = availableWidth / contentWidth; - const scaleY = availableHeight / contentHeight; + // 计算可用空间(减去边距) + const availableWidth = paperWidthPx - marginPx * 2; + const availableHeight = paperHeightPx - marginPx * 2; - // 取较小的缩放比例,确保内容完全适配 - this.printScale = Math.min(scaleX, scaleY, 1); // 不超过1,不放大 + // 计算缩放比例 + const scaleX = contentWidth > 0 ? availableWidth / contentWidth : 1; + const scaleY = contentHeight > 0 ? availableHeight / contentHeight : 1; - // 设置CSS变量 + // 取较小的缩放比例,确保内容完全适配(不超过1,不放大) + this.printScale = Math.min(scaleX, scaleY, 1); + + // 设置CSS变量和内联样式 container.style.setProperty('--print-scale', this.printScale); + container.style.setProperty('--paper-width', `${paperWidthMm}mm`); + container.style.setProperty('--paper-height', `${paperHeightMm}mm`); }); }, resetPrintScale() { this.printScale = 1; if (this.$el) { this.$el.style.setProperty('--print-scale', 1); + this.$el.style.removeProperty('--paper-width'); + this.$el.style.removeProperty('--paper-height'); } } } @@ -194,44 +237,58 @@ export default { @media print { @page { size: 180mm 100mm; - margin: 0; - padding: 0; + margin: 0 !important; + padding: 0 !important; } * { - -webkit-print-color-adjust: exact; - print-color-adjust: exact; + -webkit-print-color-adjust: exact !important; + print-color-adjust: exact !important; } - html, body { + html { margin: 0 !important; padding: 0 !important; - width: 180mm; - height: 100mm; - overflow: hidden; + width: 180mm !important; + height: 100mm !important; + overflow: hidden !important; } - /* 隐藏所有其他内容,只显示标签 */ - body > *:not(.label-container) { + body { + margin: 0 !important; + padding: 0 !important; + width: 180mm !important; + height: 100mm !important; + overflow: hidden !important; + position: relative !important; + } + + /* 隐藏所有其他内容,只显示标签容器 */ + body > *:not(.material-label-container) { display: none !important; } - .label-container { - /* 使用固定纸张尺寸 */ + .material-label-container { + /* 强制使用纸张尺寸 */ width: 180mm !important; height: 100mm !important; max-width: 180mm !important; max-height: 100mm !important; + min-width: 180mm !important; + min-height: 100mm !important; + padding: 2mm !important; margin: 0 !important; - /* 防止分页 */ + /* 防止分页 - 多重保护 */ page-break-inside: avoid !important; break-inside: avoid !important; page-break-after: avoid !important; break-after: avoid !important; page-break-before: avoid !important; break-before: avoid !important; + orphans: 999 !important; + widows: 999 !important; /* 确保内容不溢出 */ overflow: hidden !important; @@ -241,8 +298,13 @@ export default { transform: scale(var(--print-scale, 1)) !important; transform-origin: top left !important; - /* 计算缩放后的实际占用空间,确保不超出纸张 */ - position: relative !important; + /* 定位和布局 */ + position: absolute !important; + top: 0 !important; + left: 0 !important; + + /* 确保缩放后不超出纸张 */ + display: block !important; } .material-label-table {