更正前端内容
This commit is contained in:
@@ -61,6 +61,7 @@
|
||||
"konva": "^10.0.2",
|
||||
"mqtt": "^5.13.3",
|
||||
"nprogress": "0.2.0",
|
||||
"pdf-lib": "^1.17.1",
|
||||
"pdfjs-dist": "^3.6.172",
|
||||
"print-js": "^1.6.0",
|
||||
"qrcode": "^1.5.4",
|
||||
|
||||
@@ -63,6 +63,9 @@
|
||||
<el-col :span="1.5">
|
||||
<el-button type="warning" plain icon="el-icon-download" size="mini" @click="handleExportAll">导出</el-button>
|
||||
</el-col>
|
||||
<el-col :span="2">
|
||||
<el-button type="info" plain icon="el-icon-printer" size="mini" :disabled="multiple" @click="handleBatchPrintLabel">批量打印标签</el-button>
|
||||
</el-col>
|
||||
<right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
|
||||
</el-row>
|
||||
|
||||
@@ -229,6 +232,24 @@
|
||||
<el-dialog title="标签预览" :visible.sync="labelRender.visible" append-to-body>
|
||||
<label-render :content="labelRender.data" :labelType="labelType" />
|
||||
</el-dialog>
|
||||
|
||||
<!-- 批量导出标签PDF弹窗 -->
|
||||
<el-dialog title="批量导出标签PDF" :visible.sync="batchPrint.visible" width="520px" append-to-body>
|
||||
<div style="line-height: 22px; font-size: 12px; color: #909399; margin-bottom: 10px;">
|
||||
已选择 <b>{{ batchPrint.list.length }}</b> 个钢卷。点击“生成PDF并打开”将每个标签作为一页(180mm × 100mm)。
|
||||
</div>
|
||||
<div style="text-align:right;">
|
||||
<el-button size="mini" @click="batchPrint.visible = false">取消</el-button>
|
||||
<el-button type="primary" size="mini" :loading="batchPrint.loading" @click="handleBatchExportLabelPdf">生成PDF并打开</el-button>
|
||||
</div>
|
||||
|
||||
<!-- 渲染容器:屏幕隐藏,仅用于截图生成PDF -->
|
||||
<div ref="batchPdfContainer" class="batch-pdf-root" aria-hidden="true">
|
||||
<div v-for="(item, idx) in batchPrint.list" :key="item.coilId || idx" class="batch-pdf-page">
|
||||
<OuterTagPreview :content="item" :paperWidthMm="180" :paperHeightMm="100" />
|
||||
</div>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -247,12 +268,16 @@ import RawMaterialInfo from "@/components/KLPService/Renderer/RawMaterialInfo";
|
||||
// 引入封装的追溯结果组件
|
||||
import CoilTraceResult from "./CoilTraceResult.vue";
|
||||
import LabelRender from './LabelRender/index.vue'
|
||||
import OuterTagPreview from './LabelRender/OuterTagPreview.vue'
|
||||
import MaterialSelect from "@/components/KLPService/MaterialSelect";
|
||||
import ActualWarehouseSelect from "@/components/KLPService/ActualWarehouseSelect";
|
||||
import { findItemWithBom } from "@/store/modules/category";
|
||||
import CoilNo from "@/components/KLPService/Renderer/CoilNo.vue";
|
||||
import MemoInput from "@/components/MemoInput";
|
||||
import MutiSelect from "@/components/MutiSelect";
|
||||
import html2canvas from 'html2canvas';
|
||||
import { PDFDocument } from 'pdf-lib';
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
@@ -272,6 +297,7 @@ export default {
|
||||
CoilNo,
|
||||
MemoInput,
|
||||
MutiSelect,
|
||||
OuterTagPreview,
|
||||
},
|
||||
dicts: ['product_coil_status', 'coil_material', 'coil_itemname', 'coil_manufacturer'],
|
||||
props: {
|
||||
@@ -407,6 +433,12 @@ export default {
|
||||
data: {},
|
||||
type: '2'
|
||||
},
|
||||
batchPrint: {
|
||||
visible: false,
|
||||
loading: false,
|
||||
list: [],
|
||||
},
|
||||
__printOldTitle: document.title,
|
||||
floatLayerConfig: {
|
||||
columns: [
|
||||
{ label: '入场钢卷号', prop: 'enterCoilNo' },
|
||||
@@ -736,6 +768,136 @@ export default {
|
||||
...this.queryParams
|
||||
}, `materialCoil_${new Date().getTime()}.xlsx`)
|
||||
},
|
||||
|
||||
/** 批量打印标签按钮 */
|
||||
handleBatchPrintLabel() {
|
||||
if (!this.ids || this.ids.length === 0) {
|
||||
this.$message.warning('请先勾选要打印标签的钢卷');
|
||||
return;
|
||||
}
|
||||
|
||||
// 取出选中行数据,并补齐标签渲染需要的字段
|
||||
const selectedData = this.materialCoilList
|
||||
.filter(item => this.ids.includes(item.coilId))
|
||||
.map(row => {
|
||||
const item = row.itemType === 'product' ? row.product : row.rawMaterial;
|
||||
const itemName = row.itemType === 'product' ? item?.productName || '' : item?.rawMaterialName || '';
|
||||
|
||||
return {
|
||||
...row,
|
||||
itemName,
|
||||
// OuterTagPreview.vue 里字段名使用了 specification/material(而列表里是 itemSpecification/itemMaterial)
|
||||
specification: row.itemSpecification || row.specification || '',
|
||||
material: row.itemMaterial || row.material || '',
|
||||
updateTime: row.updateTime?.split(' ')[0] || row.updateTime || '',
|
||||
}
|
||||
});
|
||||
|
||||
this.batchPrint.list = selectedData;
|
||||
this.batchPrint.visible = true;
|
||||
},
|
||||
|
||||
/** 批量导出标签PDF:每个标签一页(180mm × 100mm) */
|
||||
async handleBatchExportLabelPdf() {
|
||||
if (!this.batchPrint.list || this.batchPrint.list.length === 0) {
|
||||
this.$message.warning('没有可导出的数据');
|
||||
return;
|
||||
}
|
||||
|
||||
const container = this.$refs.batchPdfContainer;
|
||||
if (!container) {
|
||||
this.$message.error('PDF渲染容器未初始化');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.batchPrint.loading = true;
|
||||
|
||||
await this.$nextTick();
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
const mmToPt = 72 / 25.4;
|
||||
// 纸张尺寸
|
||||
const paperWidthMm = 180;
|
||||
const paperHeightMm = 100;
|
||||
// 留白:左右约 4mm;上下更小一些,避免底部空得太多
|
||||
const marginXmm = 4;
|
||||
const marginTopMm = 2;
|
||||
const marginBottomMm = 1;
|
||||
|
||||
const pageWidthPt = paperWidthMm * mmToPt;
|
||||
const pageHeightPt = paperHeightMm * mmToPt;
|
||||
const marginXPt = marginXmm * mmToPt;
|
||||
const marginTopPt = marginTopMm * mmToPt;
|
||||
const marginBottomPt = marginBottomMm * mmToPt;
|
||||
|
||||
const contentWidthPt = pageWidthPt - marginXPt * 2;
|
||||
const contentHeightPt = pageHeightPt - marginTopPt - marginBottomPt;
|
||||
|
||||
const pdfDoc = await PDFDocument.create();
|
||||
|
||||
// 关键:只截取标签自身(OuterTagPreview),不要把页面菜单/弹窗带进去
|
||||
const pageEls = container.querySelectorAll('.batch-pdf-page');
|
||||
|
||||
for (let i = 0; i < pageEls.length; i++) {
|
||||
const el = pageEls[i];
|
||||
|
||||
// 强制用标签的mm尺寸作为截图基准,避免被外层布局影响
|
||||
const canvas = await html2canvas(el, {
|
||||
backgroundColor: '#ffffff',
|
||||
scale: 2,
|
||||
useCORS: true,
|
||||
// 让 html2canvas 为频繁读回优化 Canvas(浏览器会提示 willReadFrequently)
|
||||
willReadFrequently: true,
|
||||
// 确保按元素尺寸截图
|
||||
width: el.offsetWidth,
|
||||
height: el.offsetHeight,
|
||||
windowWidth: el.scrollWidth,
|
||||
windowHeight: el.scrollHeight,
|
||||
});
|
||||
|
||||
const imgDataUrl = canvas.toDataURL('image/png');
|
||||
const pngImage = await pdfDoc.embedPng(imgDataUrl);
|
||||
|
||||
const page = pdfDoc.addPage([pageWidthPt, pageHeightPt]);
|
||||
|
||||
// 图片铺满页面(保持比例,居中)
|
||||
const imgW = pngImage.width;
|
||||
const imgH = pngImage.height;
|
||||
// 按“内容区域(去掉边距)”计算缩放,让四周留下约 4mm 空白
|
||||
const scale = Math.min(contentWidthPt / imgW, contentHeightPt / imgH);
|
||||
const drawW = imgW * scale;
|
||||
const drawH = imgH * scale;
|
||||
|
||||
// 内容区域内居中 + 外层边距
|
||||
const x = marginXPt + (contentWidthPt - drawW) / 2;
|
||||
const y = marginBottomPt + (contentHeightPt - drawH) / 2;
|
||||
|
||||
page.drawImage(pngImage, { x, y, width: drawW, height: drawH });
|
||||
}
|
||||
|
||||
const pdfBytes = await pdfDoc.save();
|
||||
const blob = new Blob([pdfBytes], { type: 'application/pdf' });
|
||||
const url = URL.createObjectURL(blob);
|
||||
|
||||
// 尽量避免被浏览器拦截弹窗:优先在当前tab打开;如仍被策略限制,可改为下载
|
||||
const win = window.open(url, '_blank');
|
||||
if (!win) {
|
||||
// fallback:触发下载
|
||||
const a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = `钢卷标签_${new Date().getTime()}.pdf`;
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
this.$message.error('生成PDF失败,请重试');
|
||||
} finally {
|
||||
this.batchPrint.loading = false;
|
||||
}
|
||||
},
|
||||
/** 导出选中数据操作 */
|
||||
handleExport() {
|
||||
// 1. 判断是否有选中数据
|
||||
@@ -792,4 +954,22 @@ export default {
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* 批量导出PDF:渲染容器屏幕隐藏,但保留真实布局尺寸给 html2canvas 截图 */
|
||||
.batch-pdf-root {
|
||||
position: fixed;
|
||||
left: -100000px;
|
||||
top: 0;
|
||||
width: 180mm;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.batch-pdf-page {
|
||||
width: 180mm;
|
||||
height: 100mm;
|
||||
box-sizing: border-box;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user