From 5cd08b551a7d6a42205c8fec344e3c12b30f2c54 Mon Sep 17 00:00:00 2001 From: duxingchen Date: Tue, 15 Sep 2026 15:52:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=89=AB=E7=A0=81=E5=8F=96=E7=A0=81?= =?UTF-8?q?=E5=85=BC=E5=AE=B9=E5=B8=A6=E5=9F=9F=E5=90=8D=E7=9A=84=E5=AE=8C?= =?UTF-8?q?=E6=95=B4=20URL=20=E4=BA=8C=E7=BB=B4=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 二维码内容有两种可能,旧逻辑只做「去掉非字母数字后截前 16 位」,扫到带域名 的 URL 时会把 "https"、主机名一起当成 SN 的前半段,截出来是个完全不存在的 号,永远提示「未找到该产品」。 - 先把 "协议://主机名" 整段剥掉,否则域名会被当成候选 SN (如 trackbackirisrscn 这类 17 位串,恰好能通过长度校验) - 在剩余内容里找长度 >= 8 的连续字母数字串,取最长的一段; 等长时取靠后的 —— URL 里 SN 通常在路径末尾 --- track-uniapp/src/pages/scan/index.vue | 33 ++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/track-uniapp/src/pages/scan/index.vue b/track-uniapp/src/pages/scan/index.vue index 44640ab..46c5c67 100644 --- a/track-uniapp/src/pages/scan/index.vue +++ b/track-uniapp/src/pages/scan/index.vue @@ -75,13 +75,44 @@ export default { }, handleSearch() { this.doQuery(this.serialNumber.trim()); }, + // 📷 从扫码原始文本中提取设备身份证(SN) + // 二维码内容有两种可能,必须都兼容: + // ① 裸 SN → ABC1234567890DEF + // ② 带域名的完整 URL → https://track.iris-rs.cn/sn/ABC1234567890DEF?from=label + // 旧逻辑只是「去掉非字母数字后截前 16 位」,扫到 ② 时会把 "https"、域名 + // 一起当成 SN 的前半段,截出来是个完全不存在的号,永远提示"未找到该产品"。 + extractSerial(raw) { + const text = String(raw || "").trim(); + if (!text) return ""; + + // 关键一步:先把 "协议://主机名" 整段剥掉,否则域名会被当成候选 SN + // (如 trackbackirisrscn 这种 17 位串,恰好能通过长度校验)。 + let body = text; + const origin = text.match(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i); + if (origin) body = text.slice(origin[0].length); + + // 在剩余内容里找长度 >= 8 的连续字母数字串(身份证至少 8 位)。 + // 取最长的一段;等长时取靠后的 —— URL 里 SN 通常在路径末尾。 + const runs = body.match(/[a-zA-Z0-9]{8,}/g) || []; + if (!runs.length) return ""; + let best = runs[0]; + for (const run of runs) { + if (run.length >= best.length) best = run; + } + return best.slice(0, 16); + }, + // 📷 全屏相机扫码 handleScanCamera() { uni.scanCode({ onlyFromCamera: true, scanType: ["qrCode", "barCode"], success: (res) => { - const sn = (res.result || "").replace(/[^a-zA-Z0-9]/g, "").slice(0, 16); + const sn = this.extractSerial(res.result); + if (!sn) { + uni.showToast({ title: "无法识别二维码内容,请确认扫的是设备标签", icon: "none", duration: 2500 }); + return; + } this.doQuery(sn); }, fail: (err) => {