From 66958ca7242928b76795d98124e1d012665e8782 Mon Sep 17 00:00:00 2001
From: 云 <2163098428@qq.com>
Date: 星期五, 16 十月 2026 17:41:59 +0800
Subject: [PATCH] feat(mes): 增加托盘容量配置与追溯定位功能

---
 yudao-server/src/main/resources/static/trace.html |  114 ++++++++++++++++++++++++++++++++++++++------------------
 1 files changed, 77 insertions(+), 37 deletions(-)

diff --git a/yudao-server/src/main/resources/static/trace.html b/yudao-server/src/main/resources/static/trace.html
index 7579fb3..98a45ff 100644
--- a/yudao-server/src/main/resources/static/trace.html
+++ b/yudao-server/src/main/resources/static/trace.html
@@ -372,14 +372,6 @@
   var CODE_INPUT = document.getElementById('codeInput');
   var SEARCH_BTN = document.getElementById('searchBtn');
 
-  var FLOW_DIRECTION = { 1: ['鍏ュ簱', 'green'], 2: ['鍑哄簱', 'blue'] };
-  var FLOW_BIZ_TYPE = {
-    110: '閲囪喘鍏ュ簱', 111: '閲囪喘鍏ュ簱鍙栨秷', 112: '璋冩嫧鍑哄簱', 113: '璋冩嫧鍏ュ簱',
-    114: '鍏朵粬鍑哄簱', 115: '鍏朵粬鍏ュ簱', 116: '鐢熶骇棰嗘枡', 117: '鐢熶骇閫�鏂�',
-    118: '鐢熶骇鍏ュ簱', 119: '閿�鍞嚭搴�', 120: '閿�鍞��璐у叆搴�', 121: '澶栧崗鍙戞枡',
-    122: '澶栧崗鍏ュ簱', 123: '鐢熶骇娑堣��', 124: '浜у搧浜у嚭', 125: '渚涘簲鍟嗛��璐у嚭搴�',
-    126: '搴撳瓨璋冩暣鍏ュ簱', 127: '搴撳瓨璋冩暣鍑哄簱'
-  };
   var SOURCE_TYPE = { BAG: '琚嬬爜', PALLET: '鎵樼洏鐮�', BATCH: '鎵规鐮�' };
 
   // ========== 宸ュ叿鍑芥暟 ==========
@@ -411,12 +403,6 @@
   // 琛ㄦ牸绐勫垪锛堟暟閲� / 鏃ユ湡锛変笉鎹㈣锛岄伩鍏嶆暟瀛楄鎷嗚
   function nw(html) {
     return '<span style="white-space:nowrap">' + html + '</span>';
-  }
-
-  function statusBadge(map, key) {
-    var item = map[key];
-    if (!item) return '<span class="badge gray">' + (key === null || key === undefined ? '' : esc(key)) + '</span>';
-    return '<span class="badge ' + item[1] + '">' + esc(item[0]) + '</span>';
   }
 
   function kv(k, v, dim) {
@@ -499,14 +485,89 @@
       return;
     }
     var html = '';
+    if (new URLSearchParams(location.search).get('view') === 'location') {
+      html += locationSections(d);
+      html += sec('浜у搧杩芥函鏍囪瘑', null, tracePanel(d), null);
+      STATE.innerHTML = html;
+      window.scrollTo({ top: 0, behavior: 'smooth' });
+      return;
+    }
     html += sec('闃蹭吉鏌ヨ', null, fakePanel(d), null);
     html += sec('杩芥函鏌ヨ', null, tracePanel(d), null);
-    // 鐢熶骇鏄庣粏鎶樺彔鍖猴細瀵瑰灞曠ず绉嶅瓙娴佸悜銆佸姞宸ユ祦杞紝鐢熶骇鎵规淇℃伅涓嶅睍绀恒��
+    // 鐢熶骇鏄庣粏鎶樺彔鍖猴細瀵瑰灞曠ず鍔犲伐娴佽浆锛岀敓浜ф壒娆′俊鎭笉灞曠ず銆�
     // 璐ㄦ/浜哄憳/鎵樼洏/琚嬬爜/閲囪喘鏉ユ簮绛夊唴閮ㄦ槑缁嗕笉瀵瑰灞曠ず锛�
     // 濡傞渶涓�骞跺睍绀猴紝鏀逛负 detailSections(d, true) 鍗冲彲銆�
     html += detailSections(d, false);
     STATE.innerHTML = html || '<div class="empty-tip">鏆傛棤杩芥函鏁版嵁</div>';
     window.scrollTo({ top: 0, behavior: 'smooth' });
+  }
+
+  // 瀹氫綅鎺堟潈鍏ュ彛娌跨敤鏈〉鐨勫搧鐗岃儗鏅笌鍖哄潡鏍峰紡锛屾寜鐢熶骇銆佷粨鍌ㄣ�佺墿娴佺粍缁囧凡鏈夌湡瀹炴暟鎹��
+  function groupOutboundOrders(rows, codeOf, dateField) {
+    var grouped = [];
+    var byCode = new Map();
+    rows.forEach(function (item) {
+      var code = String(codeOf(item) || '').trim();
+      var quantity = Number(item.quantity);
+      var validQuantity = item.quantity !== null && item.quantity !== undefined && Number.isFinite(quantity);
+      var existing = code ? byCode.get(code) : null;
+      if (!existing) {
+        var order = Object.assign({}, item, { quantity: validQuantity ? Math.abs(quantity) : null });
+        grouped.push(order);
+        if (code) byCode.set(code, order);
+      } else {
+        if (validQuantity) existing.quantity = (existing.quantity || 0) + Math.abs(quantity);
+        if (!existing.contactName && item.contactName) existing.contactName = item.contactName;
+        if (item[dateField] && (!existing[dateField] || item[dateField] > existing[dateField])) {
+          existing[dateField] = item[dateField];
+        }
+      }
+    });
+    return grouped;
+  }
+
+  function locationSections(d) {
+    var production = kv('浜у搧鍚嶇О', text(d.itemName)) +
+      kv('瑙勬牸', text(d.itemSpecification || d.itemUnitMeasureName)) +
+      kv('鍔犲伐鎵规', text(d.batchCode || d.tempCode));
+    if (d.produceDate) production = kv('鐢熶骇鏃ユ湡', fmtDay(d.produceDate)) + production;
+    var html = sec('鐢熶骇淇℃伅', null, production, null);
+
+    var salesFlows = groupOutboundOrders((d.seedFlows || []).filter(function (item) { return item.bizType === 119; }),
+      function (item) { return item.bizCode; }, 'transactionTime');
+    var salesTargets = groupOutboundOrders(d.salesTargets || [],
+      function (item) { return item.salesCode || item.salesOrderCode; }, 'salesDate');
+    var flow = (d.seedFlows || []).find(function (item) { return item.warehouseName; });
+    var storage = '';
+    if (d.inboundTime) storage += kv('鍏ュ簱鏃ユ湡', fmtDay(d.inboundTime));
+    var outboundDates = salesFlows.map(function (item) { return item.transactionTime; })
+      .concat(salesTargets.map(function (item) { return item.salesDate; })).filter(Boolean).sort();
+    if (outboundDates.length) storage += kv('鏈�杩戝嚭搴撴棩鏈�', fmtDay(outboundDates[outboundDates.length - 1]));
+    if (flow) storage += kv('浠撳簱', text(flow.warehouseName));
+    html += sec('浠撳偍淇℃伅', null, storage || '<div class="empty-tip">鏆傛棤浠撳偍淇℃伅</div>', null);
+
+    var logistics = salesFlows.map(function (item) {
+      var route = [item.warehouseName, item.clientName].filter(Boolean).join(' 鈫� ');
+      var description = '璇ユ壒娆�' + (item.transactionTime ? '浜� ' + String(item.transactionTime).slice(0, 10) + ' ' : '') +
+        (item.warehouseName ? '浠�' + item.warehouseName + '鍑哄簱' : '瀹屾垚閿�鍞嚭搴�') +
+        (item.clientName ? '锛屽彂寰�' + item.clientName : '') + '銆�';
+      return li('<span class="li-ttl">' + text(route || '閿�鍞嚭搴�') + '</span>', fmtDay(item.transactionTime),
+        kv('鍑哄簱鍗曞彿', text(item.bizCode)) + kv('鏁伴噺', fmtNum(item.quantity)) +
+        kv('娴佽浆璇存槑', text(description)) +
+        (item.contactName ? kv('鑱旂郴浜�', text(item.contactName)) : ''));
+    }).join('');
+    if (!logistics && !isEmptyList(salesTargets)) {
+      logistics = salesTargets.map(function (item) {
+        var description = '璇ユ壒娆�' + (item.salesDate ? '浜� ' + String(item.salesDate).slice(0, 10) + ' ' : '') +
+          '瀹屾垚閿�鍞嚭搴�' + (item.clientName ? '锛屽幓鍚�' + item.clientName : '') + '銆�';
+        return li('<span class="li-ttl">' + text(item.clientName || '閿�鍞幓鍚�') + '</span>', fmtDay(item.salesDate),
+          kv('鍑哄簱鍗曞彿', text(item.salesCode || item.salesOrderCode)) + kv('鏁伴噺', fmtNum(item.quantity)) +
+          kv('娴佽浆璇存槑', text(description)) +
+          (item.contactName ? kv('鑱旂郴浜�', text(item.contactName)) : ''));
+      }).join('');
+    }
+    html += sec('鐗╂祦淇℃伅', null, logistics || '<div class="empty-tip">鏆傛棤鐗╂祦淇℃伅</div>', null);
+    return html;
   }
 
   function stripUrl(v) {
@@ -583,7 +644,7 @@
       kv(operatorLabel, text(operatorName)) +
       kv(codeLabel, text(code || '-')) +
       kv('杩芥函缃戝潃', traceUrl
-        ? '<a class="link" href="' + esc(traceUrl) + '">' + esc(traceUrl) + '</a>'
+        ? '<a class="link" target="_top" href="' + esc(location.pathname.replace(/trace\.html$/, 'trace-location.html') + '?code=' + encodeURIComponent(code || '')) + '">' + esc(traceUrl) + '</a>'
         : '-') +
       kv('璁¢噺鍗曚綅', text(d.itemUnitMeasureName)) +
       kv('杩芥函绫诲瀷', esc(SOURCE_TYPE[d.sourceType] || '杩芥函鐮�')) +
@@ -662,27 +723,6 @@
         return [text(s.receiptCode), text(s.vendorName), nw(fmtNum(s.receivedQuantity)), nw(fmtDay(s.receiptDate))];
       });
       html += sec('閲囪喘鏉ユ簮', null, table(['閲囪喘鍏ュ簱鍗�', '渚涘簲鍟�', '鏁伴噺', '鏃ユ湡'], psRows), { collapsible: true, open: false });
-    }
-
-    // 绉嶅瓙娴佸悜淇℃伅锛堜粎閿�鍞嚭搴� bizType=119锛�
-    var salesFlows = (d.seedFlows || []).filter(function (f) { return f.bizType === 119; });
-    if (!isEmptyList(salesFlows)) {
-      var sfBody = salesFlows.map(function (f) {
-        var qty = (f.quantity === null || f.quantity === undefined) ? '-' : fmtNum(Math.abs(Number(f.quantity)));
-        var wh = [f.warehouseName, f.locationName].filter(Boolean).join(' / ') || '-';
-        return li(statusBadge(FLOW_DIRECTION, f.type) + '<span class="li-ttl">' + esc(FLOW_BIZ_TYPE[f.bizType] || '') + '</span>',
-          fmtDate(f.transactionTime),
-          kv('鏉ユ簮鍗曞彿', text(f.bizCode)) +
-          kv('瀹㈡埛', text(f.clientName)) +
-          kv('鏁伴噺', qty) +
-          kv('浠撳簱/搴撳尯', text(wh)));
-      }).join('');
-      html += sec('绉嶅瓙娴佸悜淇℃伅', null, '<div class="scroll-list">' + sfBody + '</div>', { collapsible: true, open: false });
-    } else if (!isEmptyList(d.salesTargets)) {
-      var stRows = d.salesTargets.map(function (s) {
-        return [text(s.salesCode || s.salesOrderCode || ''), text(s.clientName), nw(fmtNum(s.quantity)), nw(fmtDay(s.salesDate))];
-      });
-      html += sec('绉嶅瓙娴佸悜淇℃伅', null, table(['閿�鍞嚭搴撳崟', '瀹㈡埛', '鏁伴噺', '鏃ユ湡'], stRows), { collapsible: true, open: false });
     }
 
     // 鍔犲伐娴佽浆

--
Gitblit v1.9.3