Files
klp-oa/klp-ui/src/views/wms/coil/panels/LabelRender/index.vue
砂糖 db263f21c6 feat(wms): 将班组输入框改为下拉选择并调整标签样式
- 将多个页面中的班组输入框替换为下拉选择框,提供甲、乙两个选项
- 调整标签预览组件的样式,移除部分内边距和边框
- 修改数值输入框的v-model绑定方式,移除.number修饰符
2026-01-09 11:49:54 +08:00

254 lines
8.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<div class="label-render-container">
<!-- 标签预览容器 -->
<div class="preview-container" id="label-preview-container" ref="labelRef">
<ProductionTagPreview v-if="labelType === '2'" :content="content" />
<OuterTagPreview v-if="labelType === '3'" :content="content" />
<SampleTagPreview v-if="labelType === '4'" :content="content" />
<ForgeTagPreview v-if="labelType === '5'" :content="content" />
<SaltSprayTagPreview v-if="labelType === '6'" :content="content" />
</div>
<div class="action-buttons">
<el-button type="primary" @click="downloadLabelAsImage">下载标签图片</el-button>
<el-button type="primary" @click="printLabel" style="margin-left: 10px;">打印标签</el-button>
</div>
</div>
</template>
<script>
import domToImage from 'dom-to-image';
import printJS from 'print-js';
import html2canvas from 'html2canvas'; // 新增:引入高清渲染库
import { Message } from 'element-ui';
import ProductionTagPreview from './ProductionTagPreview.vue';
import OuterTagPreview from './OuterTagPreview.vue';
import SampleTagPreview from './SampleTagPreview.vue';
import ForgeTagPreview from './ForgeTagPreview.vue';
import SaltSprayTagPreview from './SaltSprayTagPreview.vue';
export default {
name: 'LabelRender',
components: {
ProductionTagPreview,
OuterTagPreview,
SampleTagPreview,
ForgeTagPreview,
SaltSprayTagPreview,
},
props: {
labelType: {
type: String,
required: true,
},
content: {
type: Object,
required: true,
},
},
methods: {
// -------- 图片下载方法保留可按需替换为html2canvas --------
async downloadLabelAsImage() {
const labelContainer = document.getElementById('label-preview-container');
if (!labelContainer) {
Message.error('未找到标签容器,无法下载');
return;
}
try {
// 可选也替换为html2canvas提升下载清晰度
// const canvas = await html2canvas(labelContainer, { scale: 3, backgroundColor: '#ffffff', allowTaint: true, taintTest: false });
// const dataUrl = canvas.toDataURL('image/png', 1.0);
const dataUrl = await domToImage.toPng(labelContainer);
const downloadLink = document.createElement('a');
downloadLink.href = dataUrl;
downloadLink.download = `标签_${new Date().getTime()}.png`;
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
} catch (error) {
console.error('标签图片下载失败:', error);
Message.error('标签图片下载失败,请重试');
}
},
// -------- 重构后的打印方法(核心优化) --------
async printLabel() {
// 1. 获取标签容器DOM
const labelContainer = document.getElementById('label-preview-container');
if (!labelContainer) {
Message.error('未找到标签容器,无法打印');
return;
}
try {
Message.info('正在准备打印内容,请稍等...');
// 2. 等待二维码/字体等资源加载完成(复用之前的等待逻辑)
await this.waitForAllResources(labelContainer);
// 3. 用html2canvas生成高清Canvas解决文字模糊+二维码丢失)
const canvas = await html2canvas(labelContainer, {
scale: 1.5, // 3倍高清渲染核心
backgroundColor: '#ffffff', // 强制白色背景,避免打印时背景透明
useCORS: true, // 支持跨域图片
allowTaint: true, // 允许渲染canvas二维码
taintTest: false, // 关闭canvas污染检测
windowWidth: labelContainer.offsetWidth * 1.5, // 适配缩放后的宽度
windowHeight: labelContainer.offsetHeight * 1.5, // 适配缩放后的高度
logging: false,
});
// 4. 创建临时打印容器避免影响原DOM
const printContainerId = 'temp-print-container-' + new Date().getTime();
const tempPrintContainer = document.createElement('div');
tempPrintContainer.id = printContainerId;
// 将高清Canvas插入临时容器
tempPrintContainer.appendChild(canvas);
// document.body.appendChild(tempPrintContainer);
// 5. 调用printJS打印高清Canvas而非原HTML
printJS({
printable: tempPrintContainer, // 打印临时容器
type: 'html',
header: null,
footer: null,
scanStyles: false, // 禁用自动扫描样式,手动控制
// 自定义打印样式确保Canvas适配纸张、无多余边距
style: `
#${printContainerId} {
width: 100%;
height: auto;
margin: 0;
padding: 0;
}
#${printContainerId} canvas {
max-width: 100%;
height: auto;
border: none;
}
@media print {
body * { visibility: hidden; }
#${printContainerId}, #${printContainerId} * { visibility: visible; }
#${printContainerId} { position: absolute; top: 0; left: 0; }
}
`,
printContainer: true,
onAfterPrint: () => {
// 6. 打印完成后清理临时容器
document.body.removeChild(tempPrintContainer);
Message.success('打印准备完成,请在打印预览中确认打印');
},
onError: (error) => {
// 异常时也清理临时容器
document.body.removeChild(tempPrintContainer);
console.error('打印失败:', error);
Message.error('打印失败,请重试');
}
});
// document.removeChild(tempPrintContainer);
} catch (error) {
console.error('打印准备失败:', error);
Message.error('打印内容准备失败,请重试');
}
},
// -------- 辅助方法:等待所有资源加载(图片+字体+二维码) --------
async waitForAllResources(element) {
// 等待图片加载
const images = element.querySelectorAll('img');
const imgPromises = Array.from(images).map(img =>
img.complete ? Promise.resolve() : new Promise(resolve => {
img.onload = resolve;
img.onerror = resolve;
})
);
await Promise.all(imgPromises);
// 等待字体加载
await document.fonts.ready;
// 等待二维码Canvas渲染
await this.waitForQRCodeRender(element);
// 最终等待样式稳定
await new Promise(resolve => setTimeout(resolve, 300));
},
// -------- 辅助方法等待二维码Canvas渲染完成 --------
async waitForQRCodeRender(element) {
const qrCanvasList = element.querySelectorAll('canvas');
if (qrCanvasList.length === 0) return;
const qrLoadPromises = Array.from(qrCanvasList).map(canvas => {
return new Promise(resolve => {
const checkInterval = setInterval(() => {
const ctx = canvas.getContext('2d');
if (!ctx) {
clearInterval(checkInterval);
resolve();
return;
}
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const hasContent = imageData.data.some(value => value !== 0);
if (hasContent || Date.now() - (ctx.startTime || 0) > 2000) {
clearInterval(checkInterval);
resolve();
}
}, 100);
});
});
await Promise.all(qrLoadPromises);
}
},
};
</script>
<style scoped>
.label-render-container {
width: 100%;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
/* padding: 1rem; */
box-sizing: border-box;
}
.action-buttons {
margin-top: 1rem;
}
.preview-container {
background-color: #fff;
color: #000;
/* padding: 1.5rem; */
width: fit-content;
/* min-width: 200px; */
box-shadow: 0 0 60px rgba(255, 255, 255, 0.2);
/* border: 1px solid rgba(255, 255, 255, 0.1); */
overflow: hidden;
transition: all 0.3s ease;
}
.preview-container:hover {
box-shadow: 0 0 80px rgba(255, 255, 255, 0.3);
transform: translateY(-2px);
}
/* 强制二维码Canvas可见避免渲染丢失 */
:deep(canvas) {
display: block;
visibility: visible;
opacity: 1;
}
/* 字体平滑,提升文字清晰度 */
:deep(.preview-container) {
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
font-smooth: always;
}
</style>