From 9a3f1f9136c1f324d080c8b633494dd7298a4f8d Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 21 四月 2026 10:45:40 +0800
Subject: [PATCH] 打印标签样式格式调整

---
 src/views/procurementManagement/procurementLedger/index.vue |  213 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 212 insertions(+), 1 deletions(-)

diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index 4479251..abe1804 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -33,6 +33,20 @@
                       prefix-icon="Search"
                       @change="handleQuery" />
           </el-form-item>
+          <el-form-item label="鍏ュ簱鐘舵�侊細">
+            <el-select v-model="searchForm.stockStatus"
+                       placeholder="璇烽�夋嫨"
+                       clearable
+                       style="width: 140px"
+                       @change="handleQuery">
+              <el-option label="鏈叆搴�"
+                         :value="0" />
+              <el-option label="閮ㄥ垎鍏ュ簱"
+                         :value="1" />
+              <el-option label="宸插叆搴�"
+                         :value="2" />
+            </el-select>
+          </el-form-item>
           <el-form-item label="褰曞叆鏃ユ湡锛�">
             <el-date-picker v-model="searchForm.entryDate"
                             value-format="YYYY-MM-DD"
@@ -96,6 +110,16 @@
                                prop="availableQuality" />
               <el-table-column label="閫�璐ф暟閲�"
                                prop="returnQuality" />
+              <el-table-column label="鍏ュ簱鐘舵��"
+                               width="100px"
+                               align="center">
+                <template #default="scope">
+                  <el-tag :type="getProductStockStatusType(scope.row.productStockStatus)"
+                          size="small">
+                    {{ stockStatusText[scope.row.productStockStatus] || '鏈叆搴�' }}
+                  </el-tag>
+                </template>
+              </el-table-column>
               <el-table-column label="绋庣巼(%)"
                                prop="taxRate" />
               <el-table-column label="鍚◣鍗曚环(鍏�)"
@@ -154,6 +178,16 @@
                          width="200"
                          show-overflow-tooltip
                          :formatter="formattedNumber" />
+        <el-table-column label="鍏ュ簱鐘舵��"
+                         width="120"
+                         align="center">
+          <template #default="scope">
+            <el-tag :type="getStockStatusType(scope.row.stockStatus)"
+                    size="small">
+              {{ stockStatusText[scope.row.stockStatus] || '鏈叆搴�' }}
+            </el-tag>
+          </template>
+        </el-table-column>
         <el-table-column label="褰曞叆浜�"
                          prop="recorderName"
                          width="120"
@@ -168,7 +202,7 @@
                          show-overflow-tooltip />
         <el-table-column fixed="right"
                          label="鎿嶄綔"
-                         width="120"
+                         width="200"
                          align="center">
           <template #default="scope">
             <el-button link
@@ -178,6 +212,9 @@
             <el-button link
                        type="primary"
                        @click="downLoadFile(scope.row)">闄勪欢</el-button>
+            <el-button link
+                       type="primary"
+                       @click="openProcurementQrDialog(scope.row)">浜岀淮鐮�</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -689,6 +726,24 @@
     <FileListDialog ref="fileListRef"
                     v-model="fileListDialogVisible"
                     title="闄勪欢鍒楄〃" />
+    <el-dialog v-model="procurementQrDialogVisible"
+               title="閲囪喘鍙拌处浜岀淮鐮�"
+               width="360px"
+               draggable
+               :close-on-click-modal="false">
+      <div class="procurement-qr-dialog">
+        <img v-if="procurementQrCompositeUrl"
+             :src="procurementQrCompositeUrl"
+             alt="閲囪喘鍙拌处浜岀淮鐮�"
+             class="procurement-qr-composite-img" />
+        <el-button type="primary"
+                   class="procurement-qr-save-btn"
+                   :disabled="!procurementQrCompositeUrl"
+                   @click="downloadProcurementQrCode">
+          淇濆瓨鍥剧墖
+        </el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 
@@ -732,6 +787,7 @@
     delPurchaseTemplate,
   } from "@/api/procurementManagement/procurementLedger.js";
   import useFormData from "@/hooks/useFormData.js";
+  import QRCode from "qrcode";
 
   const { proxy } = getCurrentInstance();
   const tableData = ref([]);
@@ -784,6 +840,33 @@
       4: "danger", // 瀹℃壒澶辫触 - 绾㈣壊
     };
     return typeMap[status] || "";
+  };
+
+  // 鍏ュ簱鐘舵�佹樉绀烘枃鏈�
+  const stockStatusText = {
+    0: "鏈叆搴�",
+    1: "閮ㄥ垎鍏ュ簱",
+    2: "宸插叆搴�",
+  };
+
+  // 鑾峰彇涓昏〃鍏ュ簱鐘舵�佹爣绛剧被鍨�
+  const getStockStatusType = status => {
+    const typeMap = {
+      0: "info",
+      1: "success",
+      2: "success",
+    };
+    return typeMap[status] || "info";
+  };
+
+  // 鑾峰彇浜у搧鍏ュ簱鐘舵�佹爣绛剧被鍨�
+  const getProductStockStatusType = status => {
+    const typeMap = {
+      0: "info",
+      1: "warning",
+      2: "success",
+    };
+    return typeMap[status] || "info";
   };
 
   const templateName = ref("");
@@ -897,6 +980,7 @@
       purchaseContractNumber: "", // 閲囪喘鍚堝悓缂栧彿
       salesContractNo: "", // 閿�鍞悎鍚岀紪鍙�
       projectName: "", // 椤圭洰鍚嶇О
+      stockStatus: undefined, // 鍏ュ簱鐘舵��
       entryDate: null, // 褰曞叆鏃ユ湡
       entryDateStart: undefined,
       entryDateEnd: undefined,
@@ -1871,6 +1955,117 @@
     }
   };
 
+  const procurementQrDialogVisible = ref(false);
+  const procurementQrCompositeUrl = ref("");
+  const procurementQrDownloadBaseName = ref("");
+
+  const sanitizeProcurementQrFilename = s =>
+    String(s)
+      .replace(/[\\/:*?"<>|]/g, "_")
+      .trim()
+      .slice(0, 80) || "ledger";
+
+  const wrapProcurementQrTextLines = (ctx, text, maxWidth) => {
+    const chars = [...text];
+    const lines = [];
+    let line = "";
+    for (const ch of chars) {
+      const test = line + ch;
+      if (ctx.measureText(test).width > maxWidth && line.length) {
+        lines.push(line);
+        line = ch;
+      } else {
+        line = test;
+      }
+    }
+    if (line) lines.push(line);
+    return lines;
+  };
+
+  const buildProcurementQrCompositeDataUrl = row =>
+    new Promise((resolve, reject) => {
+      const payload = JSON.stringify({
+        id: row.id,
+        purchaseContractNumber: (row.purchaseContractNumber ?? "").trim(),
+        type: "CG",
+      });
+      QRCode.toDataURL(payload, { width: 220, margin: 2 })
+        .then(qrDataUrl => {
+          const contract = (row.purchaseContractNumber ?? "").trim() || "鈥�";
+          const img = new Image();
+          img.onload = () => {
+            const QR_SIZE = 220;
+            const padTop = 16;
+            const gapAfterQr = 14;
+            const bottomPad = 48;
+            const horizontalPad = 20;
+            const lineHeight = 20;
+            const fontSize = 14;
+            const label = `閲囪喘鍚堝悓鍙凤細${contract}`;
+
+            const canvas = document.createElement("canvas");
+            const ctx = canvas.getContext("2d");
+            canvas.width = Math.max(QR_SIZE + horizontalPad * 2, 280);
+            ctx.font = `${fontSize}px "Microsoft YaHei", "PingFang SC", sans-serif`;
+            const lines = wrapProcurementQrTextLines(
+              ctx,
+              label,
+              canvas.width - horizontalPad * 2
+            );
+            const textBlockHeight = lines.length * lineHeight;
+            canvas.height = padTop + QR_SIZE + gapAfterQr + textBlockHeight + bottomPad;
+
+            ctx.fillStyle = "#ffffff";
+            ctx.fillRect(0, 0, canvas.width, canvas.height);
+
+            const qrX = (canvas.width - QR_SIZE) / 2;
+            ctx.drawImage(img, qrX, padTop, QR_SIZE, QR_SIZE);
+
+            ctx.fillStyle = "#606266";
+            ctx.font = `${fontSize}px "Microsoft YaHei", "PingFang SC", sans-serif`;
+            ctx.textAlign = "center";
+            ctx.textBaseline = "top";
+            const textY0 = padTop + QR_SIZE + gapAfterQr;
+            lines.forEach((ln, i) => {
+              ctx.fillText(ln, canvas.width / 2, textY0 + i * lineHeight);
+            });
+
+            const baseName = sanitizeProcurementQrFilename(
+              contract !== "鈥�" ? contract : String(row.id)
+            );
+            resolve({ dataUrl: canvas.toDataURL("image/png"), baseName });
+          };
+          img.onerror = () => reject(new Error("浜岀淮鐮佸浘鐗囧姞杞藉け璐�"));
+          img.src = qrDataUrl;
+        })
+        .catch(reject);
+    });
+
+  const openProcurementQrDialog = async row => {
+    if (row?.id === undefined || row?.id === null || row?.id === "") {
+      ElMessage.warning("鏃犳硶鐢熸垚浜岀淮鐮侊細缂哄皯鍙拌处 ID");
+      return;
+    }
+    procurementQrCompositeUrl.value = "";
+    procurementQrDownloadBaseName.value = "";
+    try {
+      const { dataUrl, baseName } = await buildProcurementQrCompositeDataUrl(row);
+      procurementQrCompositeUrl.value = dataUrl;
+      procurementQrDownloadBaseName.value = baseName;
+      procurementQrDialogVisible.value = true;
+    } catch {
+      ElMessage.error("浜岀淮鐮佺敓鎴愬け璐�");
+    }
+  };
+
+  const downloadProcurementQrCode = () => {
+    if (!procurementQrCompositeUrl.value) return;
+    const a = document.createElement("a");
+    a.href = procurementQrCompositeUrl.value;
+    a.download = `閲囪喘鍙拌处浜岀淮鐮�-${procurementQrDownloadBaseName.value}.png`;
+    a.click();
+  };
+
   // 鑾峰彇妯℃澘淇℃伅
   const getTemplateList = async () => {
     let res = await getPurchaseTemplateList();
@@ -2009,4 +2204,20 @@
       transform: scale(1.2);
     }
   }
+
+  .procurement-qr-dialog {
+    text-align: center;
+    padding-bottom: 8px;
+  }
+
+  .procurement-qr-composite-img {
+    max-width: 100%;
+    height: auto;
+    display: block;
+    margin: 0 auto 28px;
+  }
+
+  .procurement-qr-save-btn {
+    margin-bottom: 12px;
+  }
 </style>

--
Gitblit v1.9.3