695593266@qq.com 1 mese fa
parent
commit
cf96bdf4eb

BIN
src/views/produceOrder/image.png


+ 119 - 6
src/views/produceOrder/printFlowCard.vue

@@ -12,6 +12,20 @@
         v-for="(card, cIndex) in printList"
         :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">
           <colgroup>
             <col style="width: 7%" />
@@ -25,11 +39,6 @@
             <col style="width: 13%" />
           </colgroup>
           <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">
               <td colspan="2" class="label">产品代号</td>
               <td colspan="3" class="value">{{ card.topCategoryCode }}</td>
@@ -102,6 +111,9 @@
 
 <script>
   import { getTaskInstanceList } from '@/api/produce/job';
+  import QRCode from 'qrcode';
+  import JsBarcode from 'jsbarcode';
+  import { encryptCode } from '@/utils/crypto';
 
   export default {
     name: 'print-flow-card',
@@ -130,6 +142,9 @@
 
         this.printList = cards;
         this.QRvisible = true;
+        this.$nextTick(() => {
+          this.generateCodes();
+        });
       },
       close() {
         this.QRvisible = false;
@@ -154,6 +169,9 @@
           const name = item.taskTypeName || item.taskName || '';
           return name !== '完结';
         });
+        const codeStr = [row.productCode, row.batchNo]
+          .filter(Boolean)
+          .join('-');
         return {
           topCategoryCode: row.topCategoryCode || '',
           topCategoryName: row.topCategoryName || '',
@@ -165,6 +183,8 @@
           semiProductCertNo: row.semiProductCertNo || '',
           issueDate: row.issueDate || '',
           recoverDate: row.recoverDate || '',
+          codeStr,
+          qrCodeUrl: '',
           taskList: filtered.map((item, idx) => ({
             taskNo: idx + 1,
             taskName: item.taskTypeName || item.taskName || ''
@@ -185,8 +205,48 @@
           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() {
         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');
         printWindow.document.open();
         printWindow.document.write(`<!DOCTYPE html>
@@ -211,6 +271,25 @@
     page-break-after: always;
   }
   .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 {
     text-align: center;
     margin: 0;
@@ -283,7 +362,7 @@
 </style>
 </head>
 <body>
-${printSection.innerHTML}
+${cloned.innerHTML}
 </body>
 </html>`);
         printWindow.document.close();
@@ -315,6 +394,40 @@ ${printSection.innerHTML}
     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 {
     text-align: center;
     margin: 0;

+ 3 - 3
src/views/taskList/index.vue

@@ -45,7 +45,7 @@
           </el-link>
         </template>
 
-        <template v-slot:code="{ row }" v-if="tabValue == '4'">
+        <template v-slot:code="{ row }">
           <el-link
             :underline="false"
             type="primary"
@@ -135,7 +135,7 @@
             :underline="false"
             type="primary"
             @click="details('report', row)"
-            v-if="tabValue == '4' && row.status != 5"
+            v-if="tabValue == '4' && (!row.status || row.status.code != 5)"
             >报工
           </el-link>
           <!-- <el-link
@@ -708,7 +708,7 @@
           },
           {
             prop: 'reportRemark',
-            label: '报备注',
+            label: '报备注',
             align: 'center',
             showOverflowTooltip: true,
             width: 180