From ee7ac8df8bce38add1f75baf876b49de94b9e00a Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期五, 16 十月 2026 17:58:33 +0800
Subject: [PATCH] feat(mes): 赋码管理绑定托盘支持未录入批次的袋码
---
src/views/mes/pro/components/qr-trace-modal.vue | 173 +++++++++++++++------------------------------------------
1 files changed, 47 insertions(+), 126 deletions(-)
diff --git a/src/views/mes/pro/components/qr-trace-modal.vue b/src/views/mes/pro/components/qr-trace-modal.vue
index 7834a3f..f701da6 100644
--- a/src/views/mes/pro/components/qr-trace-modal.vue
+++ b/src/views/mes/pro/components/qr-trace-modal.vue
@@ -11,7 +11,7 @@
import { Button, Empty, Input, message, Spin, Tag } from "ant-design-vue";
- import { getBagCodeByCode } from "#/api/mes/pro/bagCode";
+ import { getBagCodeByCode, resolveTraceType } from "#/api/mes/pro/bagCode";
import { getBatchByCode } from "#/api/mes/pro/batch";
import { getPalletByCode } from "#/api/mes/pro/pallet";
import { getQrConfig } from "#/api/mes/trace/config";
@@ -52,9 +52,10 @@
/** 浜岀淮鐮佸睍绀哄唴瀹癸細閰嶇疆浜嗘函婧愬湴鍧�鍒欐嫾 H5 URL锛屽惁鍒欏洖閫�绾爜鍊硷紙涓庡悗绔� buildQrCodeContent 涓�鑷达級 */
const qrContent = computed(() => {
if (!currentCode.value) return "";
+ const code = bagTrace.value?.code || currentCode.value;
return traceBaseUrl.value
- ? `${traceBaseUrl.value}?code=${encodeURIComponent(currentCode.value)}`
- : currentCode.value;
+ ? `${traceBaseUrl.value}?code=${encodeURIComponent(code)}`
+ : code;
});
/** 浠庡畬鏁� H5 閾炬帴涓彁鍙栬拷婧爜锛堝吋瀹规壂鐮佹灙鎵弿鎵撳嵃鏍囩閾炬帴锛� */
@@ -70,24 +71,6 @@
}
}
return trimmed;
- }
-
- /** 璇嗗埆浜岀淮鐮佸唴瀹圭被鍨嬶細鎵规鍙凤紙鍚复鏃舵壒娆$爜锛�/ 鎵樼洏鐮侊紙鍚复鏃舵墭鐩樼爜锛�/ 琚嬬爜 */
- function resolveCodeType(raw: string): TraceType | undefined {
- const value = raw.trim().toUpperCase();
- if (/^PB-\d{8}$/.test(value)) {
- return "batch";
- }
- if (/^PL-\d{8}$/.test(value)) {
- return "pallet";
- }
- if (/^.*-P\d{2}$/.test(value)) {
- return "pallet";
- }
- if (/^BAG-\d{8}$/.test(value) || /^.*-\d{4}$/.test(value)) {
- return "bag";
- }
- return "batch";
}
function resetState() {
@@ -113,11 +96,6 @@
message.warning("浜岀淮鐮佸唴瀹硅繃闀匡紝璇锋鏌ユ槸鍚︽壂鎻忔纭�");
return;
}
- const type = resolveCodeType(value);
- if (!type) {
- message.warning("鏃犳硶璇嗗埆浜岀淮鐮佺被鍨�");
- return;
- }
loading.value = true;
searched.value = true;
searchError.value = false;
@@ -128,15 +106,24 @@
palletTrace.value = undefined;
batchTrace.value = undefined;
try {
- if (type === "batch") {
- batchTrace.value = await getBatchByCode(value);
- traceTypeLabel.value = "鎵规鍙�";
+ // 缂栫爜宸茬粺涓�涓恒��16 浣嶇函鏁板瓧銆嶏紝鏃犳硶鍐嶆寜鍓嶇紑鍒ゆ柇绫诲瀷锛屾敼鐢卞悗绔寜缂栫爜瑙f瀽绫诲瀷
+ const type = await resolveTraceType(value);
+ if (type === "bag") {
+ bagTrace.value = await getBagCodeByCode(value);
+ currentCode.value = bagTrace.value.code || value;
+ traceTypeLabel.value = "琚嬬爜";
} else if (type === "pallet") {
palletTrace.value = await getPalletByCode(value);
+ currentCode.value = palletTrace.value.code || palletTrace.value.tempCode || value;
traceTypeLabel.value = "鎵樼洏鐮�";
+ } else if (type === "batch") {
+ batchTrace.value = await getBatchByCode(value);
+ currentCode.value = batchTrace.value.code || batchTrace.value.tempCode || value;
+ traceTypeLabel.value = "鎵规鍙�";
} else {
- bagTrace.value = await getBagCodeByCode(value);
- traceTypeLabel.value = "琚嬬爜";
+ searchError.value = true;
+ currentCode.value = undefined;
+ return;
}
traceType.value = type;
} catch {
@@ -148,58 +135,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: "璐d换浜�", 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: "璐d换浜�", 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: "璐d换浜�", value: d.ownerUserName || "" },
- ];
- }
- return [];
- }
-
function escapeHtml(value: string) {
return value
.replaceAll("&", "&")
@@ -207,14 +142,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) {
@@ -223,45 +158,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`;
@@ -278,7 +191,7 @@
message.warning("浜岀淮鐮佺敓鎴愬け璐ワ紝鏃犳硶鎵撳嵃");
return;
}
- const items = buildLabelText();
+ const code = currentCode.value || "";
const printWindow = window.open("", "_blank");
if (!printWindow) {
message.error("鏃犳硶鎵撳紑鎵撳嵃绐楀彛锛岃妫�鏌ユ祻瑙堝櫒璁剧疆");
@@ -286,12 +199,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);
@@ -319,9 +239,10 @@
schema: [
{
field: "code",
- label: "琚嬬爜锛堜簩缁寸爜鍐呭锛�",
+ label: "杩芥函鐮�",
span: 2,
},
+ { field: 'businessCode', label: '涓氬姟鐮侊紙鍑哄叆搴擄級', span: 2 },
{
field: "bagNo",
label: "琚嬪簭鍙�",
--
Gitblit v1.9.3