feat(wms): 新增标签预览功能及相关组件

添加盐雾试验、力学性能、样品、生产和外标签预览组件
实现标签图片下载和打印功能
调整钢卷管理页面布局和功能
优化大屏展示的全屏处理逻辑
This commit is contained in:
砂糖
2025-10-30 14:36:01 +08:00
parent fb78222796
commit 824ce738a9
14 changed files with 1006 additions and 25 deletions

View File

@@ -43,6 +43,9 @@ export default {
required: true
},
},
mounted() {
console.log(this.productId, this.productMap);
},
data() {
return {
showDetail: false,

View File

@@ -7,6 +7,7 @@ import * as echarts from 'echarts'
import dataV from '@jiaminghi/data-view';
import Element from 'element-ui'
import '@/modules/dashboardBig/assets/scss/style.scss';
import './assets/styles/element-variables.scss'
import vueFlvPlayer from 'vue-flv-player'
@@ -14,8 +15,6 @@ import vueFlvPlayer from 'vue-flv-player'
import '@/assets/styles/index.scss' // global css
import '@/assets/styles/klp.scss' // klp css
import '@/modules/dashboardBig/assets/scss/style.scss';
import App from './App'
import store from './store'
import router from './router'

View File

@@ -1,5 +1,8 @@
<template>
<Home></Home>
<!-- 给大屏组件套一个容器并通过ref获取该容器 -->
<div ref="fullscreenContainer" class="fullscreen-container">
<Home></Home>
</div>
</template>
<script>
@@ -7,5 +10,85 @@ import Home from '@/modules/dashboardBig/views/index.vue'
export default {
components: { Home },
mounted() {
// 确保容器DOM已渲染后对容器执行全屏
this.$nextTick(() => {
this.enterFullscreen()
this.addFullscreenListener()
})
},
beforeDestroy() {
// 移除监听,避免内存泄漏
this.removeFullscreenListener()
// 组件销毁时如果仍在全屏状态,退出全屏
this.exitFullscreen()
},
methods: {
// 进入全屏(针对目标容器)
enterFullscreen() {
// 获取大屏组件的容器元素
const container = this.$refs.fullscreenContainer
if (!container) return
// 对容器执行全屏(兼容各浏览器)
if (container.requestFullscreen) {
container.requestFullscreen()
} else if (container.mozRequestFullScreen) { // Firefox
container.mozRequestFullScreen()
} else if (container.webkitRequestFullscreen) { // Chrome, Safari
container.webkitRequestFullscreen()
} else if (container.msRequestFullscreen) { // IE/Edge
container.msRequestFullscreen()
}
},
// 退出全屏(通用方法)
exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen()
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen()
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen()
} else if (document.msExitFullscreen) {
document.msExitFullscreen()
}
},
// 处理全屏状态变化
handleFullscreenChange() {
// 检查是否退出全屏此时全屏元素应为null
const isExit = !document.fullscreenElement &&
!document.mozFullScreenElement &&
!document.webkitFullscreenElement &&
!document.msFullscreenElement
if (isExit) {
// 退出全屏后返回上一页
this.$router.back()
}
},
// 添加全屏状态监听(兼容各浏览器)
addFullscreenListener() {
document.addEventListener('fullscreenchange', this.handleFullscreenChange)
document.addEventListener('mozfullscreenchange', this.handleFullscreenChange)
document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange)
document.addEventListener('MSFullscreenChange', this.handleFullscreenChange)
},
// 移除监听
removeFullscreenListener() {
document.removeEventListener('fullscreenchange', this.handleFullscreenChange)
document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange)
document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange)
document.removeEventListener('MSFullscreenChange', this.handleFullscreenChange)
}
}
}
</script>
</script>
<style scoped>
/* 确保容器占满父容器,避免全屏后显示异常 */
.fullscreen-container {
width: 100%;
height: 100%;
/* 可根据需要添加其他样式(如背景色等) */
}
</style>

View File

@@ -264,11 +264,11 @@ export default {
itemType: item.itemType,
itemId: item.itemId,
itemStyle: { color: this.getTechColor(index) },
children: [{
name: `卷数: ${item.coilCount}`,
value: item.coilCount,
itemStyle: { color: this.getTechColor(index + 1).replace('rgb', 'rgba').replace(')', ', 0.7)') }
}]
// children: [{
// name: `卷数: ${item.coilCount}`,
// value: item.coilCount,
// itemStyle: { color: this.getTechColor(index + 1).replace('rgb', 'rgba').replace(')', ', 0.7)') }
// }]
}))
};
} else {

View File

@@ -1,5 +1,5 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys"/>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" />
</template>
<script>
@@ -11,10 +11,11 @@ export default {
},
data() {
return {
qrcode: false,
qrcode: true,
querys: {
dataType: 0
}
},
labelType: '2'
}
}
}

View File

@@ -1,5 +1,5 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys"/>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" />
</template>
<script>
@@ -14,7 +14,8 @@ export default {
qrcode: true,
querys: {
dataType: 1
}
},
labelType: '2'
}
}
}

View File

@@ -0,0 +1,120 @@
<template>
<div class="label-container">
<div class="company-name">嘉祥科伦普重工有限公司</div>
<div class="label-title">力学性能标签</div>
<table class="info-table">
<tr>
<td class="label-cell">卷号</td>
<td class="value-cell">{{ content.coilNumber || '' }}</td>
<td class="label-cell">屈服</td>
<td class="value-cell">{{ content.yieldStrength || '' }}</td>
</tr>
<tr>
<td class="label-cell">规格</td>
<td class="value-cell">{{ content.specification || '' }}</td>
<td class="label-cell">抗拉</td>
<td class="value-cell">{{ content.tensileStrength || '' }}</td>
</tr>
<tr>
<td class="label-cell">材质</td>
<td class="value-cell">{{ content.material || '' }}</td>
<td class="label-cell">延伸</td>
<td class="value-cell">{{ content.elongation || '' }}</td>
</tr>
<tr>
<td class="label-cell">原料厂家</td>
<td class="value-cell">{{ content.rawMaterialFactory || '' }}</td>
<td class="label-cell">锌层质量</td>
<td class="value-cell">{{ content.platingQuality || '' }}</td>
</tr>
<tr>
<td class="label-cell">备注</td>
<td class="value-cell" colspan="3">{{ content.remark || '' }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'MechanicalPropertyLabel',
props: {
content: {
type: Object,
default: () => ({
coilNumber: '',
yieldStrength: '',
specification: '',
tensileStrength: '',
material: '',
elongation: '',
rawMaterialFactory: '',
platingQuality: '',
remark: ''
})
}
}
}
</script>
<style scoped>
.label-container {
width: 50em; /* 容器宽度(可根据需求调整) */
min-height: 30em; /* 容器最小高度 */
border: 1px solid #000;
padding: 2px;
box-sizing: border-box;
font-family: "SimSun", serif;
font-size: 8px;
line-height: 1.2;
display: flex;
flex-direction: column; /* 垂直分布子元素 */
}
.company-name {
text-align: center;
font-weight: bold;
margin-bottom: 1px;
font-size: 2em;
}
.label-title {
text-align: center;
font-weight: bold;
margin-bottom: 2px;
border-bottom: 1px solid #000;
padding-bottom: 1px;
font-size: 2em;
}
.info-table {
width: 100%;
border-collapse: collapse; /* 合并边框 */
font-size: 7px;
flex-grow: 1; /* 拉伸占据剩余垂直空间 */
}
.info-table td {
border: 1px solid #000; /* 表格单元格边框 */
text-align: center;
vertical-align: middle;
font-size: 2em;
width: 25%; /* 4列均分宽度每列占25%,确保 label/value 空间相同 */
}
.label-cell {
font-weight: bold;
/* 去掉背景色:删除原有的 background-color 声明 */
}
.value-cell {
background-color: #fff; /* 可根据需求保留/删除,与原图视觉一致 */
}
.label-footnote {
margin-top: 2px;
text-align: center;
font-size: 7px;
color: #555;
}
</style>

View File

@@ -0,0 +1,261 @@
<template>
<div class="label-container">
<!-- 顶部公司信息 -->
<div class="company-header">
<img :src="logo" alt="Company Logo" class="company-logo" />
<div class="company-name">
嘉祥科伦普重工有限公司<br />
<span class="english-name">Jiaxiang KLP Heavy Industry Co., Ltd.</span>
</div>
</div>
<!-- 核心信息网格布局替代原表格 -->
<div class="info-grid">
<!-- 第一行订货单位 + 合同号 -->
<div class="info-grid-item label-cell">订货单位</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.orderUnit || ''" />
</div>
<div class="info-grid-item label-cell">合同号</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.contractNumber || ''" />
</div>
<!-- 第二行执行标准 + 钢卷号 -->
<div class="info-grid-item label-cell">产品名称</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.productName || ''" />
</div>
<div class="info-grid-item label-cell">执行标准</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.executionStandard || ''" />
</div>
<div class="info-grid-item label-cell">钢卷号</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.currentCoilNo || ''" />
</div>
<!-- 第三行原料卷号 + 规格 -->
<div class="info-grid-item label-cell">原料卷号</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.enterCoilNo || ''" />
</div>
<div class="info-grid-item label-cell">规格</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.specification || ''" />
</div>
<!-- 第四行材质 + 表面质量 -->
<div class="info-grid-item label-cell">材质</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.material || ''" />
</div>
<div class="info-grid-item label-cell">表面质量</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.surfaceQuality || ''" />
</div>
<!-- 第五行表面处理 + 剪切要求 -->
<div class="info-grid-item label-cell">表面处理</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.surfaceTreatment || ''" />
</div>
<div class="info-grid-item label-cell">剪切要求</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.cuttingRequirements || ''" />
</div>
<!-- 第六行包装种类 + 毛重 -->
<div class="info-grid-item label-cell">包装种类</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.packagingType || ''" />
</div>
<div class="info-grid-item label-cell">毛重</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.grossWeight || ''" />
</div>
<!-- 第七行净重 + 参考长度 -->
<div class="info-grid-item label-cell">净重</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.netWeight || ''" />
</div>
<div class="info-grid-item label-cell">参考长度</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.referenceLength || ''" />
</div>
<!-- 第八行生产日期跨3列 -->
<div class="info-grid-item label-cell">生产日期</div>
<div class="info-grid-item value-cell">
<input type="text" class="nob" :value="content.productionDate || ''" />
</div>
</div>
<!-- 底部信息 -->
<div class="footer-info">
<div class="address">
地址山东省济宁市嘉祥县开发区生物产业园区新民路北<br />
<span class="english-address">Address: Donghai special steel, ciyutuo Industrial Zone, Luanzhou, Tangshan, Hebei province, China.</span>
<span>
TEL0537-6625068
</span>
</div>
<div class="contact-timestamp">
<QRCode :content="content.qrcodeRecordId || ''" :size="10" />
</div>
</div>
</div>
</template>
<script>
import logo from '@/assets/logo/logo.png'
import QRCode from '../../../print/components/QRCode.vue';
export default {
name: 'MetalSheetLabel',
components: {
QRCode
},
props: {
content: {
type: Object,
default: () => ({
// form3 所有字段
orderUnit: '',
contractNumber: '',
productName: '镀锌卷板合格品(GI)',
executionStandard: '',
coilNumber: 'D2Z125031809202',
rawBlankNumber: '',
specification: '2.28*1250',
material: '',
surfaceQuality: '',
surfaceTreatment: '环保钝化/不涂油',
cuttingRequirements: '',
packagingType: 'A03',
grossWeight: '',
netWeight: '7080',
referenceLength: '320',
productionDate: '2025-03-19',
// 底部信息字段
address: '唐山市滦州市茨榆坨工业区',
englishAddress: 'Donghai special steel, ciyutuo Industrial Zone, Luanzhou, Tangshan, Hebei province, China.',
tel: '0315-7560777',
timestamp: '2025.04.12 10:14'
})
}
},
data() {
return {
logo,
}
}
}
</script>
<style scoped>
.label-container {
width: 45em;
height: 25em;
padding: 0.5em;
box-sizing: border-box;
font-family: 'Arial', sans-serif;
border: 1px solid #000;
}
.company-header {
display: flex;
align-items: center;
margin-bottom: 0.3em;
}
.company-logo {
width: 2.8em;
height: 2.8em;
margin-right: 0.5em;
}
.company-name {
font-size: 0.95em;
width: 100%;
line-height: 1.1;
}
.english-name {
width: 100%;
font-size: 0.6em;
opacity: 0.8;
}
.product-title {
font-size: 1.4em;
font-weight: bold;
text-align: center;
margin-bottom: 0.4em;
border-bottom: 1.5px solid #000;
padding-bottom: 0.2em;
}
/* 网格布局核心样式 */
.info-grid {
display: grid;
grid-template-columns: repeat(4, 1fr); /* 4列等宽 */
gap: 0; /* 消除网格间距,确保边框连贯 */
margin-bottom: 0.5em;
}
.info-grid-item {
border: 1px solid #000;
padding: 0.25em;
font-size: 0.78em;
height: 2.1em;
text-align: center;
vertical-align: middle;
word-break: break-all;
display: flex;
align-items: center;
justify-content: center;
}
.label-cell {
font-weight: bold;
}
/* 生产日期跨3列 */
.date-colspan {
grid-column: span 3; /* 占据3列 */
}
.footer-info {
display: flex;
justify-content: space-between;
align-items: flex-start;
font-size: 0.7em;
margin-top: 0.3em;
}
.address {
line-height: 1.2;
width: 65%;
}
.english-address {
opacity: 0.8;
font-size: 0.9em;
}
.contact-timestamp {
text-align: right;
line-height: 1.4;
}
.nob {
width: 100%;
height: 100%;
border: none;
outline: none;
background: transparent;
text-align: center;
}
</style>

View File

@@ -0,0 +1,119 @@
<template>
<div class="material-label-container">
<table class="material-label-table">
<!-- 调整第一行结构使label和value各占2列等宽 -->
<tr>
<td class="label-cell" colspan="1">料卷号</td>
<td class="value-cell" colspan="2">
<input type="text" class="nob" :value="content.enterCoilNo || ''" />
</td>
<td class="value-cell" colspan="1">
<QRCode :content="content.qrcodeRecordId || ' '" :size="5" />
</td>
</tr>
<tr>
<td class="label-cell">规格(mm)</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.specification || ''" />
</td>
<td class="label-cell">净重</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.netWeight || ''" />
</td>
</tr>
<tr>
<td class="label-cell">材质</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.material || ''" />
</td>
<td class="label-cell">下道</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.nextProcess || ''" />
</td>
</tr>
<tr>
<td class="label-cell">生产班组</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.team || ''" />
</td>
<td class="label-cell">时间</td>
<td class="value-cell">
<input type="text" class="nob" :value="content.productionDate || ''" />
</td>
</tr>
</table>
</div>
</template>
<script>
import QRCode from '../../../print/components/QRCode.vue';
export default {
name: 'MaterialLabel',
components: {
QRCode
},
props: {
content: {
type: Object,
default: () => ({
coilNumber: '',
specification: '',
netWeight: '',
material: '',
nextProcess: '',
productionTeam: '',
productionDate: ''
})
}
}
}
</script>
<style scoped>
.material-label-container {
width: 25em;
height: 15em;
padding: 0px;
display: flex; /* 启用Flex布局 */
flex-direction: column; /* 子元素垂直排列 */
font-family: "SimSun", serif;
box-sizing: border-box; /* 确保内边距/边框不影响总尺寸 */
}
.material-label-table {
border-collapse: collapse;
width: 100%;
table-layout: fixed;
flex-grow: 1; /* 让表格拉伸,占满剩余垂直空间 */
height: 0; /* 配合flex-grow自动计算高度 */
}
/* 四列均分宽度每列占25% */
.material-label-table td {
border: 1px solid #333;
padding: 0;
font-size: 14px;
/* width: 25%; */
box-sizing: border-box;
text-align: center;
}
.label-cell {
background-color: #f5f5f5;
font-weight: bold;
}
.value-cell {
text-align: center;
}
.nob {
width: 100%;
height: 100%;
border: none;
outline: none;
background: transparent;
text-align: center;
}
</style>

View File

@@ -0,0 +1,112 @@
<template>
<div class="label-container">
<div class="company-name">嘉祥科伦普重工有限公司</div>
<div class="label-title">盐雾试验标签</div>
<table class="info-table">
<tr>
<td class="label-cell">卷号</td>
<td class="value-cell">{{ content.coilNumber || '' }}</td>
<td class="label-cell">开始时间</td>
<td class="value-cell">{{ content.startDate || '' }}</td>
</tr>
<tr>
<td class="label-cell">规格</td>
<td class="value-cell">{{ content.specification || '' }}</td>
<td class="label-cell">结束时间</td>
<td class="value-cell">{{ content.endDate || '' }}</td>
</tr>
<tr>
<td class="label-cell">材质</td>
<td class="value-cell">{{ content.material || '' }}</td>
<td class="label-cell">锌层质量</td>
<td class="value-cell">{{ content.platingQuality || '' }}</td>
</tr>
<tr>
<td class="label-cell">原料厂家</td>
<td class="value-cell" colspan="3">{{ content.rawMaterialFactory || '' }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'SaltSprayTestLabel',
props: {
content: {
type: Object,
default: () => ({
coilNumber: '',
startDate: '',
specification: '',
endDate: '',
material: '',
rawMaterialFactory: '',
platingQuality: ''
})
}
}
}
</script>
<style scoped>
.label-container {
width: 50em; /* 容器宽度(可根据需求调整) */
min-height: 30em; /* 容器最小高度 */
border: 1px solid #000;
padding: 2px;
box-sizing: border-box;
font-family: "SimSun", serif;
font-size: 8px;
line-height: 1.2;
display: flex;
flex-direction: column; /* 垂直分布子元素 */
}
.company-name {
text-align: center;
font-weight: bold;
margin-bottom: 1px;
font-size: 2em;
}
.label-title {
text-align: center;
font-weight: bold;
margin-bottom: 2px;
border-bottom: 1px solid #000;
padding-bottom: 1px;
font-size: 2em;
}
.info-table {
width: 100%;
border-collapse: collapse; /* 合并边框 */
font-size: 7px;
flex-grow: 1; /* 拉伸占据剩余垂直空间 */
}
.info-table td {
border: 1px solid #000; /* 表格单元格边框 */
text-align: center;
vertical-align: middle;
font-size: 2em;
width: 25%; /* 4列均分宽度每列占25%,确保 label/value 空间相同 */
}
.label-cell {
font-weight: bold;
/* 去掉背景色:删除原有的 background-color 声明 */
}
.value-cell {
background-color: #fff; /* 可根据需求保留/删除,与原图视觉一致 */
}
.label-footnote {
margin-top: 2px;
text-align: center;
font-size: 7px;
color: #555;
}
</style>

View File

@@ -0,0 +1,122 @@
<template>
<div class="sample-label-container">
<div class="company-title">嘉祥科伦普重工有限公司</div>
<div class="label-title">样品标签</div>
<table class="info-table">
<tr>
<td class="label-cell">品名</td>
<td class="value-cell" colspan="3">{{ content.productName || '' }}</td>
</tr>
<tr>
<td class="label-cell">执行标准</td>
<td class="value-cell" colspan="3">{{ content.executionStandard || '' }}</td>
</tr>
<tr>
<td class="label-cell">材质</td>
<td class="value-cell">{{ content.material || '' }}</td>
<td class="label-cell">厚度</td>
<td class="value-cell">{{ content.thickness || '' }}</td>
</tr>
<tr>
<td class="label-cell">镀层种类</td>
<td class="value-cell">{{ content.platingType || '' }}</td>
<td class="label-cell">镀层质量</td>
<td class="value-cell">{{ content.platingQuality || '' }}</td>
</tr>
<tr>
<td class="label-cell">表面状态</td>
<td class="value-cell">{{ content.surfaceState || '' }}</td>
<td class="label-cell">表面处理</td>
<td class="value-cell">{{ content.surfaceTreatment || '' }}</td>
</tr>
<tr>
<td class="label-cell">样品日期</td>
<td class="value-cell" colspan="3">{{ content.sampleDate || '' }}</td>
</tr>
</table>
</div>
</template>
<script>
export default {
name: 'SampleLabelRenderer',
props: {
content: {
type: Object,
default: () => ({
productName: '',
executionStandard: '',
material: '',
thickness: '',
platingType: '',
platingQuality: '',
surfaceState: '',
surfaceTreatment: '',
sampleDate: ''
})
}
}
}
</script>
<style scoped>
.sample-label-container {
width: 50em;
height: 40em;
border: 1px solid #000;
padding: 2px;
box-sizing: border-box;
font-family: "SimSun", serif;
font-size: 10px;
line-height: 1.5;
display: flex;
flex-direction: column;
}
.company-title {
text-align: center;
font-weight: bold;
margin-bottom: 2px;
font-size: 11px;
}
.label-title {
text-align: center;
font-weight: bold;
margin-bottom: 3px;
border-bottom: 1px solid #000;
padding-bottom: 1px;
font-size: 11px;
}
.info-table {
width: 100%;
border-collapse: collapse;
flex-grow: 1; /* 让表格占据剩余空间 */
table-layout: fixed; /* 固定表格布局,确保列宽均匀 */
}
.info-table td {
border: 1px solid #000;
padding: 4px 2px;
text-align: center;
vertical-align: middle;
word-break: break-all; /* 处理长文本 */
}
.label-cell {
font-weight: bold;
width: 25%; /* 标签单元格固定占25%宽度 */
background-color: #f9f9f9;
}
/* 调整不同单元格的宽度比例 */
.value-cell {
width: 75%; /* 单标签对应的值占75% */
}
/* 四列布局时每个单元格占25% */
tr:nth-child(n+3) td:not([colspan]) {
width: 25%;
}
</style>

View File

@@ -0,0 +1,140 @@
<template>
<div class="label-render-container">
<!-- 操作按钮 -->
<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 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>
</template>
<script>
import domToImage from 'dom-to-image';
import printJS from 'print-js';
import { Message } from 'element-ui'; // 若使用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: {
// -------- 图片下载方法 --------
async downloadLabelAsImage() {
// 1. 获取要转换的DOM容器
const labelContainer = document.getElementById('label-preview-container');
if (!labelContainer) {
Message.error('未找到标签容器,无法下载');
return;
}
try {
// 2. 用dom-to-image生成PNG图片的DataURL
const dataUrl = await domToImage.toPng(labelContainer);
// 3. 创建临时a标签触发下载
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('标签图片下载失败,请重试');
}
},
// 打印方法
printLabel() {
// 1. 获取标签容器DOM
const labelContainer = document.getElementById('label-preview-container');
if (!labelContainer) {
Message.error('未找到标签容器,无法打印');
return;
}
// 4. 调用print-js打印
printJS({
printable: 'label-preview-container', // 要打印的元素ID
type: 'html', // 打印类型为HTML
header: null, // 不显示页眉
footer: null, // 不显示页脚
// style: printStyles, // 注入打印样式
scanStyles: true, // 禁用自动扫描页面样式(避免冲突)
targetStyles: ['*'], // 允许所有样式生效
printContainer: true, // 打印指定容器
onError: (error) => { // 错误处理
console.error('打印失败:', error);
Message.error('打印失败,请重试');
}
});
}
},
};
</script>
<style scoped>
.label-render-container {
width: 100%;
height: calc(100vh - 200px);
display: flex;
flex-direction: column;
/* 按钮与预览垂直排列 */
justify-content: flex-start;
align-items: center;
padding: 2rem;
box-sizing: border-box;
}
.action-buttons {
margin-bottom: 1rem;
/* 按钮与预览区的间距 */
}
.preview-container {
background-color: #fff;
color: #000;
padding: 1.5rem;
width: fit-content;
min-width: 200px;
border-radius: 6px;
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);
}
</style>

View File

@@ -56,9 +56,10 @@
{{ scope.row.itemType == 'product' ? '成品' : '原料' }}
</template>
</el-table-column>
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="物品" align="center" prop="itemName">
<template slot-scope="scope">
<ProductInfo v-if="scope.row.itemType == 'product'" productId="scope.row.itemId">
<ProductInfo v-if="scope.row.itemType == 'product'" :productId="scope.row.itemId">
<template slot-scope="{ product }">
{{ product.productName }}({{ product.productCode }})
</template>
@@ -83,8 +84,6 @@
<el-table-column label="班组" align="center" prop="team" />
<el-table-column label="毛重" align="center" prop="grossWeight" />
<el-table-column label="净重" align="center" prop="netWeight" />
<el-table-column label="仓库" align="center" prop="warehouseName" />
<el-table-column label="备注" align="center" prop="remark" />
<el-table-column label="操作" align="center" class-name="small-padding fixed-width">
<template slot-scope="scope">
@@ -92,6 +91,9 @@
v-if="qrcode">
下载二维码
</el-button>
<el-button size="mini" type="text" icon="el-icon-view" @click="handlePreviewLabel(scope.row)">
预览标签
</el-button>
<el-button size="mini" type="text" icon="el-icon-edit" @click="handleCheck(scope.row)">修正</el-button>
<el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)">删除</el-button>
<el-button size="mini" type="text" icon="el-icon-search" @click="handleTrace(scope.row)">追溯</el-button>
@@ -150,6 +152,11 @@
<el-dialog title="钢卷追溯" :visible.sync="traceOpen" width="90%" append-to-body>
<coil-trace-result :trace-result="traceResult"></coil-trace-result>
</el-dialog>
<!-- 标签预览弹窗 -->
<el-dialog title="标签预览" :visible.sync="labelRender.visible" append-to-body>
<label-render :content="labelRender.data" :labelType="labelType" />
</el-dialog>
</div>
</template>
@@ -164,10 +171,9 @@ import RawMaterialSelect from "@/components/KLPService/RawMaterialSelect";
import ProductInfo from "@/components/KLPService/Renderer/ProductInfo";
import BomInfoMini from "@/components/KLPService/Renderer/BomInfoMini";
import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
import RightToolbar from "@/components/RightToolbar";
import Pagination from "@/components/Pagination";
// 引入封装的追溯结果组件
import CoilTraceResult from "./CoilTraceResult.vue"; // 路径根据实际存放位置调整
import LabelRender from './LabelRender/index.vue'
export default {
name: "MaterialCoil",
@@ -180,9 +186,8 @@ export default {
ProductInfo,
RawMaterialInfo,
BomInfoMini,
RightToolbar,
Pagination,
CoilTraceResult // 注册组件
CoilTraceResult,
LabelRender
},
props: {
qrcode: {
@@ -192,6 +197,10 @@ export default {
querys: {
type: Object,
default: () => {},
},
labelType: {
type: String,
default: '2'
}
},
data() {
@@ -254,6 +263,11 @@ export default {
itemType: [
{ required: true, message: "物品类型不能为空", trigger: "change" }
]
},
labelRender: {
visible: false,
data: {},
type: '2'
}
};
},
@@ -284,6 +298,11 @@ export default {
this.$message.error('溯源查询失败,请重试');
});
},
/** 预览标签 */
handlePreviewLabel(row) {
this.labelRender.visible = true;
this.labelRender.data = row;
},
/** 下载二维码 */
handleDownloadQRCode(row) {
try {
@@ -424,7 +443,7 @@ export default {
},
/** 导出按钮操作 */
handleExport() {
this.download('system/materialCoil/export', {
this.download('wms/materialCoil/export', {
...this.queryParams
}, `materialCoil_${new Date().getTime()}.xlsx`)
}

View File

@@ -1,5 +1,5 @@
<template>
<BasePage :qrcode="qrcode" :querys="querys"/>
<BasePage :qrcode="qrcode" :querys="querys" :labelType="labelType" />
</template>
<script>
@@ -14,7 +14,8 @@ export default {
qrcode: false,
querys: {
itemType: 'product'
}
},
labelType: '3'
}
}
}