liu
昨天 4ca4444ad33a2a1a51f5c06e78ee9365dfb1eed6
yudao-server/src/main/resources/static/trace.html
@@ -347,11 +347,26 @@
(function () {
  'use strict';
  // ========== 页面可配置项 ==========
  // 生产经营者(追溯查询区块展示)
  var COMPANY_NAME = '新疆塔里木河种业股份有限公司';
  // 追溯网址(外网访问地址,与包装/二维码上印制的一致)
  var TRACE_URL = 'http://1.95.78.124:9008/';
  // ========== 页面配置 ==========
  // 生产经营者名称与追溯网址是种子标签四要素的组成部分,必须与二维码/标签印刷内容一致,
  // 因此统一由后端下发(/public/mes/trace/config),禁止在此硬编码。
  var COMPANY_NAME = '';
  var TRACE_URL = '';
  var IS_IMPORTED = false;
  // 拉取溯源页配置;失败时不阻断查询(查询结果本身也带生产经营者与追溯网址)
  function loadTraceConfig() {
    return fetch('/public/mes/trace/config')
      .then(function (resp) { return resp.json(); })
      .then(function (res) {
        if (res && res.code === 0 && res.data) {
          COMPANY_NAME = res.data.operatorName || '';
          TRACE_URL = res.data.traceUrl || '';
          IS_IMPORTED = !!res.data.imported;
        }
      })
      .catch(function () { /* 配置拉取失败:退回使用查询结果中的同名字段 */ });
  }
  var STATE = document.getElementById('state');
  var CODE_INPUT = document.getElementById('codeInput');
@@ -477,11 +492,19 @@
      renderState('<div class="empty-tip error">未查询到该追溯码,请核对二维码或联系官方</div>');
      return;
    }
    // 已作废的追溯码(破损替换后作废)不得作为有效产品流通,直接给出警示并停止展示溯源详情
    if (d.codeStatus === 'CANCELED') {
      renderState('<div class="empty-tip error">该追溯码已作废,非本公司有效产品,谨防假冒。<br>'
        + '如有疑问请联系官方核实。</div>');
      return;
    }
    var html = '';
    html += sec('防伪查询', null, fakePanel(d), null);
    html += sec('追溯查询', null, tracePanel(d), null);
    // 生产明细折叠区(批次/质检/人员/托盘/袋码/采购来源/种子流向/加工流转)按需求不展示,
    // detailSections 保留以便后续按需开启
    // 生产明细折叠区:国标要求追溯网址可查询「种子加工批次」及「物流销售信息」,故对外展示
    // (加工批次、种子流向、加工流转;折叠不展开)。质检/人员/托盘/袋码/采购来源等内部明细不对外展示,
    // 如需一并展示,改为 detailSections(d, true) 即可。
    html += detailSections(d, false);
    STATE.innerHTML = html || '<div class="empty-tip">暂无追溯数据</div>';
    window.scrollTo({ top: 0, behavior: 'smooth' });
  }
@@ -537,9 +560,19 @@
  }
  // 区块2:追溯查询(未录入批次时只展示品种信息 + 提示)
  // 四要素(品种名称 → 生产经营者 → 单元识别代码 → 追溯网址)按国标顺序排列,其余信息排在其后
  function tracePanel(d) {
    var code = resolveCode(d);
    var name = [d.itemName, d.itemSpecification].filter(Boolean).join(' ');
    // 生产经营者与追溯网址优先取查询结果(与标签印刷内容同源),退回页面配置
    var operatorName = d.operatorName || COMPANY_NAME;
    var traceUrl = d.traceUrl || TRACE_URL;
    var operatorLabel = IS_IMPORTED ? '进口商名称' : '生产经营者';
    // 只有袋码才是「最小销售单元」,其码值才称「单元识别代码」;
    // 托盘码/批次码不属于最小销售单元标识,按实际类型展示,避免误导消费者
    var codeLabel = d.sourceType === 'BAG'
      ? '单元识别代码'
      : (SOURCE_TYPE[d.sourceType] ? SOURCE_TYPE[d.sourceType] + '(非最小销售单元)' : '追溯码');
    var unbound = d.batchBound === false;
    var batchRows = unbound
      ? '<div class="notice">该追溯码尚未录入生产批次,批次号、生产日期、产线等信息待完善;当前展示该码对应的品种信息。</div>'
@@ -547,31 +580,40 @@
        kv('生产日期', fmtDate(d.produceDate)) +
        kv('产线', text(d.lineName || d.lineCode));
    return kv('品种名称', text(name)) +
      kv(operatorLabel, text(operatorName)) +
      kv(codeLabel, text(code || '-')) +
      kv('追溯网址', traceUrl
        ? '<a class="link" href="' + esc(traceUrl) + '">' + esc(traceUrl) + '</a>'
        : '-') +
      kv('计量单位', text(d.itemUnitMeasureName)) +
      kv('生产经营者', esc(COMPANY_NAME)) +
      kv('单元识别代码', text(code || '-')) +
      kv('追溯网址', '<a class="link" href="' + esc(TRACE_URL) + '">' + esc(TRACE_URL) + '</a>') +
      kv('追溯类型', esc(SOURCE_TYPE[d.sourceType] || '追溯码')) +
      batchRows;
  }
  // 区块3~:生产明细(折叠,有数据才展示)
  function detailSections(d) {
  // full=true 时展示全部明细(质检/人员/托盘/袋码/采购来源);
  // 默认只展示国标要求的「加工批次」与「物流销售(种子流向)」信息,其余区块不对外展示。
  function detailSections(d, full) {
    var html = '';
    // 生产批次信息
    // 生产批次信息(国标要求:追溯网址应可查询种子加工批次)
    // 未录入批次时不展示空区块,避免给出"无加工批次信息"的错误暗示
    if (d.batchBound !== false) {
    var batchBody =
        kv('批次号', text(d.batchCode)) +
      kv('批次状态', d.batchStatusName ? statusBadge({ v: [d.batchStatusName, 'blue'] }, 'v') : text(d.batchStatus)) +
        kv('生产日期', fmtDate(d.produceDate)) +
        kv('产线', text(d.lineName || d.lineCode)) +
      kv('计划数量', fmtNum(d.planQuantity)) +
      kv('已生成袋码', fmtNum(d.bagQuantity)) +
      kv('已生成托盘', fmtNum(d.palletQuantity)) +
      kv('入库时间', fmtDate(d.inboundTime)) +
      kv('临时批次码', text(d.tempCode)) +
      kv('备注', text(d.remark));
    html += sec('生产批次信息', null, batchBody, { collapsible: true, open: false });
    }
    // 质检信息
    if (d.quality) {
    // 质检信息(仅完整模式展示)
    if (full && d.quality) {
      var q = d.quality;
      var qBody =
        kv('质检结论', q.resultName ? '<span class="badge ' + (q.result === 1 ? 'green' : 'red') + '">' + esc(q.resultName) + '</span>' : '-') +
@@ -596,8 +638,8 @@
      html += sec('质检信息', null, qBody, { collapsible: true, open: false });
    }
    // 生产人员
    if (!isEmptyList(d.workers)) {
    // 生产人员(仅完整模式展示:涉及个人信息,不对外公开)
    if (full && !isEmptyList(d.workers)) {
      var wBody = d.workers.map(function (w) {
        return li('<span class="li-ttl">' + text(w.userName) + '</span>' +
          (w.workerTypeName ? '<span class="badge gray">' + esc(w.workerTypeName) + '</span>' : ''),
@@ -607,8 +649,8 @@
      html += sec('生产人员', d.workers.length + ' 人', '<div class="scroll-list">' + wBody + '</div>', { collapsible: true, open: false });
    }
    // 托盘信息
    if (!isEmptyList(d.pallets)) {
    // 托盘信息(仅完整模式展示)
    if (full && !isEmptyList(d.pallets)) {
      var pRows = d.pallets.map(function (p) {
        return [text(p.code), fmtNum(p.palletNo), fmtNum(p.bagCount), fmtNum(p.capacity)];
      });
@@ -617,8 +659,8 @@
        { collapsible: true, open: false });
    }
    // 袋码列表
    if (!isEmptyList(d.bags)) {
    // 袋码列表(仅完整模式展示)
    if (full && !isEmptyList(d.bags)) {
      var bBody = d.bags.map(function (b) {
        return li('<span class="li-ttl">' + text(b.code) + '</span>' +
          (b.statusName ? '<span class="badge gray">' + esc(b.statusName) + '</span>' : ''),
@@ -630,8 +672,8 @@
      html += sec('袋码列表', bagCountText, '<div class="scroll-list">' + bBody + '</div>', { collapsible: true, open: false });
    }
    // 采购来源
    if (!isEmptyList(d.purchaseSources)) {
    // 采购来源(仅完整模式展示)
    if (full && !isEmptyList(d.purchaseSources)) {
      var psRows = d.purchaseSources.map(function (s) {
        return [text(s.receiptCode), text(s.vendorName), nw(fmtNum(s.receivedQuantity)), nw(fmtDay(s.receiptDate))];
      });
@@ -697,6 +739,9 @@
    });
  })();
  // 先拉取页面配置(生产经营者名称、追溯网址),再执行查询;查询结果中同样带有这两项,互为兜底
  loadTraceConfig();
  var initialCode = new URLSearchParams(location.search).get('code') || '';
  CODE_INPUT.value = initialCode;
  if (initialCode) {