From 3f45dc220ca6e1085c2ad2bc375e2ed72066171e Mon Sep 17 00:00:00 2001 From: zzh Date: Mon, 24 Nov 2025 11:11:13 +0800 Subject: [PATCH] =?UTF-8?q?=20=E6=96=B0=E5=A2=9E=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E7=AE=B1=E5=8F=B7=E6=9F=A5=E8=AF=A2=E5=87=BA=E8=B4=A7=E8=AE=B0?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/js/components/shipment-query.js | 132 +++++++++++++++++------ server/app.py | 54 ++++++++++ 2 files changed, 153 insertions(+), 33 deletions(-) diff --git a/frontend/js/components/shipment-query.js b/frontend/js/components/shipment-query.js index fc90610..8ff7eff 100644 --- a/frontend/js/components/shipment-query.js +++ b/frontend/js/components/shipment-query.js @@ -10,8 +10,10 @@ Router.register('/shipments/query', async () => { } setTimeout(async () => { - const queryBtn = document.getElementById('sn-query-btn'); - const snInput = document.getElementById('sn-input'); + const queryTypeSelect = document.getElementById('query-type'); + const queryBtn = document.getElementById('query-btn'); + const queryInput = document.getElementById('query-input'); + const inputLabel = document.getElementById('input-label'); const resultDiv = document.getElementById('query-result'); const statsDiv = document.getElementById('redis-stats'); const clearBtn = document.getElementById('clear-redis-btn'); @@ -47,40 +49,97 @@ Router.register('/shipments/query', async () => { } } + // 切换查询类型时更新输入框提示 + queryTypeSelect?.addEventListener('change', (e) => { + const queryType = e.target.value; + if (queryType === 'sn') { + inputLabel.textContent = '输入 SN/MAC 号'; + queryInput.placeholder = '输入 SN 或 MAC 地址'; + } else if (queryType === 'box') { + inputLabel.textContent = '输入箱号'; + queryInput.placeholder = '输入箱号'; + } + resultDiv.innerHTML = ''; + }); + const performQuery = async () => { - const sn = snInput?.value?.trim(); - if (!sn) { - resultDiv.innerHTML = '
请输入 SN/MAC 号
'; + const queryType = queryTypeSelect?.value || 'sn'; + const queryValue = queryInput?.value?.trim(); + + if (!queryValue) { + resultDiv.innerHTML = `
请输入${queryType === 'sn' ? 'SN/MAC 号' : '箱号'}
`; return; } try { resultDiv.innerHTML = '
查询中...
'; - const res = await fetch(`/api/shipments/query-by-sn?sn=${encodeURIComponent(sn)}`, { - credentials: 'include' - }); - const data = await res.json(); + let res, data; - if (data.found) { - resultDiv.innerHTML = ` -
-
✓ 找到出货记录
-
SN/MAC: ${data.sn}
-
机种: ${data.platform_name || '未知'}
-
出货日期: ${data.date}
-
箱号: ${data.box}
-
记录时间: ${data.ts}
-
- `; - } else { - resultDiv.innerHTML = ` -
-
✗ 未找到记录
-
SN/MAC: ${data.sn}
-
${data.message || '该 SN 没有出货记录'}
-
- `; + if (queryType === 'sn') { + // 按 SN 查询 + res = await fetch(`/api/shipments/query-by-sn?sn=${encodeURIComponent(queryValue)}`, { + credentials: 'include' + }); + data = await res.json(); + + if (data.found) { + resultDiv.innerHTML = ` +
+
✓ 找到出货记录
+
SN/MAC: ${data.sn}
+
机种: ${data.platform_name || '未知'}
+
出货日期: ${data.date}
+
箱号: ${data.box}
+
记录时间: ${data.ts}
+
+ `; + } else { + resultDiv.innerHTML = ` +
+
✗ 未找到记录
+
SN/MAC: ${data.sn}
+
${data.message || '该 SN 没有出货记录'}
+
+ `; + } + } else if (queryType === 'box') { + // 按箱号查询 + res = await fetch(`/api/shipments/query-by-box?box=${encodeURIComponent(queryValue)}`, { + credentials: 'include' + }); + data = await res.json(); + + if (data.found) { + const recordsHtml = data.records.map((record, index) => ` +
+
记录 ${index + 1}
+
SN/MAC: ${record.sn}
+
机种: ${record.platform_name || '未知'}
+
出货日期: ${record.date}
+
记录时间: ${record.ts}
+
+ `).join(''); + + resultDiv.innerHTML = ` +
+
✓ 找到出货记录
+
箱号: ${data.box}
+
记录数量: ${data.count}
+
+ ${recordsHtml} +
+
+ `; + } else { + resultDiv.innerHTML = ` +
+
✗ 未找到记录
+
箱号: ${data.box}
+
${data.message || '该箱号没有出货记录'}
+
+ `; + } } } catch (e) { resultDiv.innerHTML = `
查询失败:${e.message}
`; @@ -118,7 +177,7 @@ Router.register('/shipments/query', async () => { clearBtn.addEventListener('click', clearRedis); } - snInput?.addEventListener('keypress', (e) => { + queryInput?.addEventListener('keypress', (e) => { if (e.key === 'Enter') { performQuery(); } @@ -129,7 +188,7 @@ Router.register('/shipments/query', async () => { const showClearButton = userRole === 'superadmin'; return `
-
SN/MAC 出货查询
+
发货汇总信息查询
@@ -139,16 +198,23 @@ Router.register('/shipments/query', async () => {
- + + +
+
+
- + ${showClearButton ? '' : ''}
diff --git a/server/app.py b/server/app.py index 2f1ba2f..8a20ade 100644 --- a/server/app.py +++ b/server/app.py @@ -2220,6 +2220,60 @@ def query_shipment_by_sn(): return jsonify({'error': f'查询失败:{str(e)}'}), 500 +@app.get('/api/shipments/query-by-box') +@require_login +def query_shipment_by_box(): + """通过箱号查询出货信息""" + box_no = request.args.get('box', '').strip() + + if not box_no: + return jsonify({'error': '请提供箱号'}), 400 + + try: + r = get_redis() + redis_key = 'shipment_sn_mapping' + + # 获取所有记录 + all_records = r.hgetall(redis_key) + + # 筛选出匹配箱号的记录 + matched_records = [] + for sn, data in all_records.items(): + try: + shipment_info = json.loads(data) + if shipment_info.get('box') == box_no: + platform = shipment_info.get('platform', 'pdd') + platform_name = {'pdd': '拼多多', 'yt': '圆通', 'tx': '兔喜'}.get(platform, platform) + matched_records.append({ + 'sn': sn.decode('utf-8') if isinstance(sn, bytes) else sn, + 'date': shipment_info.get('date'), + 'box': shipment_info.get('box'), + 'platform': platform, + 'platform_name': platform_name, + 'ts': shipment_info.get('ts') + }) + except: + continue + + if matched_records: + return jsonify({ + 'found': True, + 'box': box_no, + 'count': len(matched_records), + 'records': matched_records + }) + else: + return jsonify({ + 'found': False, + 'box': box_no, + 'message': '未找到该箱号的出货记录' + }) + + except Exception as e: + log('query_shipment_by_box_error', str(e)) + return jsonify({'error': f'查询失败:{str(e)}'}), 500 + + @app.post('/api/shipments/update-platform') @require_login @require_any_role('superadmin')