| | |
| | | import type { MesProBatchApi } from "#/api/mes/pro/batch"; |
| | | import type { MesProPalletApi } from "#/api/mes/pro/pallet"; |
| | | |
| | | import { ref } from "vue"; |
| | | import { computed, ref } from "vue"; |
| | | |
| | | import { Barcode, useVbenModal } from "@vben/common-ui"; |
| | | import { DICT_TYPE } from "@vben/constants"; |
| | |
| | | import { getBagCodeByCode } 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"; |
| | | import { useDescription } from "#/components/description"; |
| | | |
| | | defineOptions({ name: "MesProQrTraceModal" }); |
| | |
| | | const barcodeRef = ref<InstanceType<typeof Barcode>>(); |
| | | |
| | | const traceTypeLabel = ref(""); |
| | | |
| | | /** 溯源 H5 页面基础地址(会话内只拉取一次) */ |
| | | const traceBaseUrl = ref<string>(""); |
| | | |
| | | async function ensureTraceBaseUrl() { |
| | | if (traceBaseUrl.value) return; |
| | | try { |
| | | const res = await getQrConfig(); |
| | | traceBaseUrl.value = res.traceBaseUrl || ""; |
| | | } catch { |
| | | traceBaseUrl.value = ""; |
| | | } |
| | | } |
| | | |
| | | /** 二维码展示内容:配置了溯源地址则拼 H5 URL,否则回退纯码值(与后端 buildQrCodeContent 一致) */ |
| | | const qrContent = computed(() => { |
| | | if (!currentCode.value) return ""; |
| | | return traceBaseUrl.value |
| | | ? `${traceBaseUrl.value}?code=${encodeURIComponent(currentCode.value)}` |
| | | : currentCode.value; |
| | | }); |
| | | |
| | | /** 从完整 H5 链接中提取追溯码(兼容扫码枪扫描打印标签链接) */ |
| | | function extractCodeFromUrl(raw: string): string { |
| | | const trimmed = raw.trim(); |
| | | if (/^https?:\/\//i.test(trimmed)) { |
| | | try { |
| | | const url = new URL(trimmed); |
| | | const code = url.searchParams.get("code"); |
| | | if (code) return code; |
| | | } catch { |
| | | // 解析失败按原始输入处理 |
| | | } |
| | | } |
| | | return trimmed; |
| | | } |
| | | |
| | | /** 识别二维码内容类型:批次号(含临时批次码)/ 托盘码(含临时托盘码)/ 袋码 */ |
| | | function resolveCodeType(raw: string): TraceType | undefined { |
| | |
| | | |
| | | /** 扫码/输入二维码内容查询追溯信息 */ |
| | | async function handleSearch(raw?: string) { |
| | | const value = (raw ?? codeInput.value)?.trim().toUpperCase(); |
| | | const input = (raw ?? codeInput.value)?.trim() ?? ""; |
| | | const value = extractCodeFromUrl(input).toUpperCase(); |
| | | if (!value) { |
| | | message.warning("请扫描或输入二维码内容"); |
| | | return; |
| | |
| | | if (!isOpen) { |
| | | return; |
| | | } |
| | | ensureTraceBaseUrl(); |
| | | const data = modalApi.getData<{ code?: string }>() || {}; |
| | | codeInput.value = data.code ?? undefined; |
| | | resetState(); |
| | |
| | | class="mb-4 flex items-center gap-6 rounded bg-gray-100 p-5" |
| | | > |
| | | <div class="flex-shrink-0"> |
| | | <Barcode ref="barcodeRef" :content="currentCode" :width="200" /> |
| | | <Barcode ref="barcodeRef" :content="qrContent" :width="200" /> |
| | | </div> |
| | | <div class="min-w-0 flex-1"> |
| | | <p class="text-lg font-bold break-all">{{ currentCode }}</p> |