云
3 天以前 59b12b835c99b1318557e149c8913c16718664fb
refactor(mes): 重构二维码标签生成逻辑

- 修改二维码配置,将码值显示在下方而非右侧文本区域
- 更新二维码标签图片生成算法,调整布局为二维码在上、码值在下
- 简化标签生成参数,移除复杂的键值对文本叠加功能
- 更新本地环境配置中的追溯基础URL地址
- 调整前端模态框中的二维码下载和打印逻辑以匹配新布局
- 更新追溯页面中部门名称显示和生产明细展示规则
已修改1个文件
121 ■■■■■ 文件已修改
src/views/mes/pro/components/qr-trace-modal.vue 121 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/mes/pro/components/qr-trace-modal.vue
@@ -131,58 +131,6 @@
    }
  }
  /** 当前追溯数据的关键信息(下载/打印图片叠加文字用) */
  function buildLabelText(): { label: string; value: string }[] {
    if (traceType.value === "bag" && bagTrace.value) {
      const d = bagTrace.value;
      return [
        { label: "袋码", value: d.code || "" },
        { label: "袋序号", value: d.bagNo ? String(d.bagNo) : "" },
        { label: "批次号", value: d.batchCode || "" },
        { label: "品种", value: d.itemName || "" },
        { label: "规格", value: d.itemSpecification || "" },
        {
          label: "产线",
          value: [d.lineCode, d.lineName].filter(Boolean).join(" / "),
        },
        { label: "生产日期", value: d.produceDate || "" },
        { label: "责任人", value: d.ownerUserName || "" },
      ];
    }
    if (traceType.value === "pallet" && palletTrace.value) {
      const d = palletTrace.value;
      return [
        { label: "托盘码", value: d.code || d.tempCode || "" },
        { label: "托盘序号", value: d.palletNo ? String(d.palletNo) : "" },
        { label: "批次号", value: d.batchCode || "" },
        { label: "品种", value: d.itemName || "" },
        { label: "规格", value: d.itemSpecification || "" },
        {
          label: "产线",
          value: [d.lineCode, d.lineName].filter(Boolean).join(" / "),
        },
        { label: "生产日期", value: d.produceDate || "" },
        { label: "责任人", value: d.ownerUserName || "" },
      ];
    }
    if (batchTrace.value) {
      const d = batchTrace.value;
      return [
        { label: "批次号", value: d.code || d.tempCode || "" },
        { label: "品种", value: d.itemName || "" },
        { label: "规格", value: d.itemSpecification || "" },
        {
          label: "产线",
          value: [d.lineCode, d.lineName].filter(Boolean).join(" / "),
        },
        { label: "生产日期", value: d.produceDate || "" },
        { label: "计划数量", value: d.planQuantity ? String(d.planQuantity) : "" },
        { label: "责任人", value: d.ownerUserName || "" },
      ];
    }
    return [];
  }
  function escapeHtml(value: string) {
    return value
      .replaceAll("&", "&")
@@ -190,14 +138,14 @@
      .replaceAll(">", ">");
  }
  /** 下载二维码 PNG(二维码 + 关键信息文字合成) */
  /** 下载二维码 PNG(二维码在上,码值在下) */
  function handleDownload() {
    const base64 = barcodeRef.value?.getImageBase64();
    if (!base64) {
      message.warning("二维码生成失败,无法下载");
      return;
    }
    const items = buildLabelText();
    const code = currentCode.value || "";
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");
    if (!ctx) {
@@ -206,45 +154,23 @@
    }
    const img = new Image();
    img.onload = () => {
      const padding = 20;
      const infoX = img.width + padding * 2;
      const infoWidth = 320;
      canvas.width = infoX + infoWidth + padding;
      canvas.height = Math.max(img.height + padding * 2, 300);
      const padding = 16;
      const gap = 4;
      const textHeight = 28;
      canvas.width = img.width + padding * 2;
      canvas.height = img.height + padding * 2 + gap + textHeight;
      ctx.fillStyle = "#ffffff";
      ctx.fillRect(0, 0, canvas.width, canvas.height);
      ctx.drawImage(img, padding, padding);
      ctx.fillStyle = "#000000";
      let y = padding + 10;
      const lineHeight = 26;
      items.forEach((item) => {
        ctx.font = "bold 14px 'Microsoft YaHei', Arial, sans-serif";
        ctx.fillText(`${item.label}:`, infoX, y);
        y += 18;
        ctx.font = "14px 'Microsoft YaHei', Arial, sans-serif";
        const text = item.value || "-";
        const maxWidth = infoWidth - 10;
        if (ctx.measureText(text).width > maxWidth) {
          let currentText = text;
          while (currentText.length > 0) {
            let line = "";
            for (let i = 0; i < currentText.length; i++) {
              const testLine = line + currentText[i];
              if (ctx.measureText(testLine).width > maxWidth) {
                break;
              }
              line = testLine;
            }
            ctx.fillText(line, infoX + 5, y);
            y += 16;
            currentText = currentText.slice(line.length);
          }
          y += 6;
        } else {
          ctx.fillText(text, infoX + 5, y);
          y += lineHeight;
        }
      });
      let fontSize = 20;
      ctx.font = `bold ${fontSize}px Arial, sans-serif`;
      while (ctx.measureText(code).width > img.width && fontSize > 1) {
        ctx.font = `bold ${--fontSize}px Arial, sans-serif`;
      }
      ctx.textAlign = "center";
      ctx.textBaseline = "middle";
      ctx.fillText(code, canvas.width / 2, padding + img.height + gap + textHeight / 2);
      const link = document.createElement("a");
      link.href = canvas.toDataURL("image/png");
      link.download = `${currentCode.value || "qr"}_${Date.now()}.png`;
@@ -261,7 +187,7 @@
      message.warning("二维码生成失败,无法打印");
      return;
    }
    const items = buildLabelText();
    const code = currentCode.value || "";
    const printWindow = window.open("", "_blank");
    if (!printWindow) {
      message.error("无法打开打印窗口,请检查浏览器设置");
@@ -269,12 +195,19 @@
    }
    printWindow.document.write(`<!DOCTYPE html>
<html><head><meta charset="UTF-8"><title>打印二维码</title>
<style>*{margin:0;padding:0}body{font-family:'Microsoft YaHei',Arial,sans-serif;padding:20px}.print-container{text-align:center}.qr-img{max-width:100%;margin:20px 0}.info{margin-top:20px;text-align:left;font-size:13px}.info p{margin:4px 0}@media print{body{padding:0}.print-container{padding:20px}}</style>
<style>
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:Arial,sans-serif;background:#fff;color:#000}
.print-container{width:40mm;padding:2mm;break-inside:avoid;text-align:center}
.qr-img{display:block;width:36mm;height:36mm;object-fit:contain}
.code{display:block;width:36mm;height:5mm;margin-top:0.5mm}
@page{margin:0}
</style>
</head><body><div class="print-container">
<img src="${base64}" class="qr-img" alt="二维码" />
<div class="info">
${items.map((item) => `<p><strong>${escapeHtml(item.label)}:</strong> ${escapeHtml(item.value || "-")}</p>`).join("")}
</div></div></body></html>`);
<svg class="code" viewBox="0 0 200 28" xmlns="http://www.w3.org/2000/svg" aria-label="码值">
<text x="100" y="20" text-anchor="middle" font-family="Arial,sans-serif" font-size="20" font-weight="700"${code.length > 16 ? ' textLength="196" lengthAdjust="spacingAndGlyphs"' : ''}>${escapeHtml(code)}</text>
</svg></div></body></html>`);
    printWindow.document.close();
    printWindow.addEventListener("load", () => {
      setTimeout(() => printWindow.print(), 500);