|
@@ -12,6 +12,20 @@
|
|
|
v-for="(card, cIndex) in printList"
|
|
v-for="(card, cIndex) in printList"
|
|
|
:key="cIndex"
|
|
:key="cIndex"
|
|
|
>
|
|
>
|
|
|
|
|
+ <div class="flow-card-header">
|
|
|
|
|
+ <div class="header-code header-qr">
|
|
|
|
|
+ <img
|
|
|
|
|
+ v-if="card.qrCodeUrl"
|
|
|
|
|
+ :src="card.qrCodeUrl"
|
|
|
|
|
+ alt="二维码"
|
|
|
|
|
+ class="qr-img"
|
|
|
|
|
+ />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ <div class="flow-card-title"><span>工序流转卡</span></div>
|
|
|
|
|
+ <div class="header-code header-bar">
|
|
|
|
|
+ <canvas :ref="'barcode_' + cIndex"></canvas>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ </div>
|
|
|
<table class="flow-card-detail">
|
|
<table class="flow-card-detail">
|
|
|
<colgroup>
|
|
<colgroup>
|
|
|
<col style="width: 7%" />
|
|
<col style="width: 7%" />
|
|
@@ -25,11 +39,6 @@
|
|
|
<col style="width: 13%" />
|
|
<col style="width: 13%" />
|
|
|
</colgroup>
|
|
</colgroup>
|
|
|
<thead>
|
|
<thead>
|
|
|
- <tr class="title-row">
|
|
|
|
|
- <th colspan="9" class="title-cell">
|
|
|
|
|
- <div class="flow-card-title"><span>工序流转卡</span></div>
|
|
|
|
|
- </th>
|
|
|
|
|
- </tr>
|
|
|
|
|
<tr class="info-row">
|
|
<tr class="info-row">
|
|
|
<td colspan="2" class="label">产品代号</td>
|
|
<td colspan="2" class="label">产品代号</td>
|
|
|
<td colspan="3" class="value">{{ card.topCategoryCode }}</td>
|
|
<td colspan="3" class="value">{{ card.topCategoryCode }}</td>
|
|
@@ -102,6 +111,9 @@
|
|
|
|
|
|
|
|
<script>
|
|
<script>
|
|
|
import { getTaskInstanceList } from '@/api/produce/job';
|
|
import { getTaskInstanceList } from '@/api/produce/job';
|
|
|
|
|
+ import QRCode from 'qrcode';
|
|
|
|
|
+ import JsBarcode from 'jsbarcode';
|
|
|
|
|
+ import { encryptCode } from '@/utils/crypto';
|
|
|
|
|
|
|
|
export default {
|
|
export default {
|
|
|
name: 'print-flow-card',
|
|
name: 'print-flow-card',
|
|
@@ -130,6 +142,9 @@
|
|
|
|
|
|
|
|
this.printList = cards;
|
|
this.printList = cards;
|
|
|
this.QRvisible = true;
|
|
this.QRvisible = true;
|
|
|
|
|
+ this.$nextTick(() => {
|
|
|
|
|
+ this.generateCodes();
|
|
|
|
|
+ });
|
|
|
},
|
|
},
|
|
|
close() {
|
|
close() {
|
|
|
this.QRvisible = false;
|
|
this.QRvisible = false;
|
|
@@ -154,6 +169,9 @@
|
|
|
const name = item.taskTypeName || item.taskName || '';
|
|
const name = item.taskTypeName || item.taskName || '';
|
|
|
return name !== '完结';
|
|
return name !== '完结';
|
|
|
});
|
|
});
|
|
|
|
|
+ const codeStr = [row.productCode, row.batchNo]
|
|
|
|
|
+ .filter(Boolean)
|
|
|
|
|
+ .join('-');
|
|
|
return {
|
|
return {
|
|
|
topCategoryCode: row.topCategoryCode || '',
|
|
topCategoryCode: row.topCategoryCode || '',
|
|
|
topCategoryName: row.topCategoryName || '',
|
|
topCategoryName: row.topCategoryName || '',
|
|
@@ -165,6 +183,8 @@
|
|
|
semiProductCertNo: row.semiProductCertNo || '',
|
|
semiProductCertNo: row.semiProductCertNo || '',
|
|
|
issueDate: row.issueDate || '',
|
|
issueDate: row.issueDate || '',
|
|
|
recoverDate: row.recoverDate || '',
|
|
recoverDate: row.recoverDate || '',
|
|
|
|
|
+ codeStr,
|
|
|
|
|
+ qrCodeUrl: '',
|
|
|
taskList: filtered.map((item, idx) => ({
|
|
taskList: filtered.map((item, idx) => ({
|
|
|
taskNo: idx + 1,
|
|
taskNo: idx + 1,
|
|
|
taskName: item.taskTypeName || item.taskName || ''
|
|
taskName: item.taskTypeName || item.taskName || ''
|
|
@@ -185,8 +205,48 @@
|
|
|
remark: item.remark || ''
|
|
remark: item.remark || ''
|
|
|
}));
|
|
}));
|
|
|
},
|
|
},
|
|
|
|
|
+ generateCodes() {
|
|
|
|
|
+ this.printList.forEach((card, index) => {
|
|
|
|
|
+ const content = card.codeStr || card.productCode || String(index);
|
|
|
|
|
+ const encoded = encryptCode(content);
|
|
|
|
|
+ QRCode.toDataURL(encoded, { width: 240, margin: 1 })
|
|
|
|
|
+ .then((url) => {
|
|
|
|
|
+ this.$set(this.printList[index], 'qrCodeUrl', url);
|
|
|
|
|
+ })
|
|
|
|
|
+ .catch((err) => {
|
|
|
|
|
+ console.error('QRCode生成失败:', err);
|
|
|
|
|
+ });
|
|
|
|
|
+ const refKey = 'barcode_' + index;
|
|
|
|
|
+ const canvasArr = this.$refs[refKey];
|
|
|
|
|
+ const canvas = Array.isArray(canvasArr) ? canvasArr[0] : canvasArr;
|
|
|
|
|
+ if (canvas) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ JsBarcode(canvas, encoded, {
|
|
|
|
|
+ format: 'CODE128',
|
|
|
|
|
+ width: 2,
|
|
|
|
|
+ height: 50,
|
|
|
|
|
+ displayValue: false,
|
|
|
|
|
+ margin: 0
|
|
|
|
|
+ });
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('Barcode生成失败:', e);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
|
|
+ },
|
|
|
print() {
|
|
print() {
|
|
|
const printSection = document.getElementById('printSection');
|
|
const printSection = document.getElementById('printSection');
|
|
|
|
|
+ const cloned = printSection.cloneNode(true);
|
|
|
|
|
+ const srcCanvases = printSection.querySelectorAll('canvas');
|
|
|
|
|
+ const dstCanvases = cloned.querySelectorAll('canvas');
|
|
|
|
|
+ srcCanvases.forEach((canvas, i) => {
|
|
|
|
|
+ if (dstCanvases[i]) {
|
|
|
|
|
+ const img = document.createElement('img');
|
|
|
|
|
+ img.src = canvas.toDataURL('image/png');
|
|
|
|
|
+ img.className = 'barcode-img';
|
|
|
|
|
+ dstCanvases[i].parentNode.replaceChild(img, dstCanvases[i]);
|
|
|
|
|
+ }
|
|
|
|
|
+ });
|
|
|
const printWindow = window.open('', '_blank');
|
|
const printWindow = window.open('', '_blank');
|
|
|
printWindow.document.open();
|
|
printWindow.document.open();
|
|
|
printWindow.document.write(`<!DOCTYPE html>
|
|
printWindow.document.write(`<!DOCTYPE html>
|
|
@@ -211,6 +271,25 @@
|
|
|
page-break-after: always;
|
|
page-break-after: always;
|
|
|
}
|
|
}
|
|
|
.flow-card-page:last-child { page-break-after: auto; }
|
|
.flow-card-page:last-child { page-break-after: auto; }
|
|
|
|
|
+ .flow-card-header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ padding: 6mm 0 4mm 0;
|
|
|
|
|
+ margin-top: -2mm;
|
|
|
|
|
+ }
|
|
|
|
|
+ .flow-card-header .flow-card-title { flex: 1; padding: 0 4mm; }
|
|
|
|
|
+ .flow-card-header .header-code {
|
|
|
|
|
+ width: 30mm;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ }
|
|
|
|
|
+ .flow-card-header .header-qr { justify-content: flex-start; }
|
|
|
|
|
+ .flow-card-header .header-bar { justify-content: flex-end; }
|
|
|
|
|
+ .flow-card-header .qr-img { width: 25mm; height: 25mm; }
|
|
|
|
|
+ .flow-card-header canvas,
|
|
|
|
|
+ .flow-card-header .barcode-img { width: 45mm; height: 14mm; }
|
|
|
.flow-card-title {
|
|
.flow-card-title {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
margin: 0;
|
|
margin: 0;
|
|
@@ -283,7 +362,7 @@
|
|
|
</style>
|
|
</style>
|
|
|
</head>
|
|
</head>
|
|
|
<body>
|
|
<body>
|
|
|
-${printSection.innerHTML}
|
|
|
|
|
|
|
+${cloned.innerHTML}
|
|
|
</body>
|
|
</body>
|
|
|
</html>`);
|
|
</html>`);
|
|
|
printWindow.document.close();
|
|
printWindow.document.close();
|
|
@@ -315,6 +394,40 @@ ${printSection.innerHTML}
|
|
|
margin: 0 auto 12mm auto;
|
|
margin: 0 auto 12mm auto;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ .flow-card-header {
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: space-between;
|
|
|
|
|
+ padding: 6mm 0 4mm 0;
|
|
|
|
|
+ margin-top: -2mm;
|
|
|
|
|
+
|
|
|
|
|
+ .flow-card-title {
|
|
|
|
|
+ flex: 1;
|
|
|
|
|
+ padding: 0 4mm;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ .header-code {
|
|
|
|
|
+ width: 30mm;
|
|
|
|
|
+ display: flex;
|
|
|
|
|
+ align-items: center;
|
|
|
|
|
+ justify-content: center;
|
|
|
|
|
+ }
|
|
|
|
|
+ .header-qr {
|
|
|
|
|
+ justify-content: flex-start;
|
|
|
|
|
+ }
|
|
|
|
|
+ .header-bar {
|
|
|
|
|
+ justify-content: flex-end;
|
|
|
|
|
+ }
|
|
|
|
|
+ .qr-img {
|
|
|
|
|
+ width: 25mm;
|
|
|
|
|
+ height: 25mm;
|
|
|
|
|
+ }
|
|
|
|
|
+ canvas {
|
|
|
|
|
+ width: 45mm;
|
|
|
|
|
+ height: 14mm;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
.flow-card-title {
|
|
.flow-card-title {
|
|
|
text-align: center;
|
|
text-align: center;
|
|
|
margin: 0;
|
|
margin: 0;
|