新增通过箱号查询出货记录

This commit is contained in:
zzh 2025-11-24 11:11:13 +08:00
parent 80998f16ec
commit 3f45dc220c
2 changed files with 153 additions and 33 deletions

View File

@ -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 = '<div class="error">请输入 SN/MAC 号</div>';
const queryType = queryTypeSelect?.value || 'sn';
const queryValue = queryInput?.value?.trim();
if (!queryValue) {
resultDiv.innerHTML = `<div class="error">请输入${queryType === 'sn' ? 'SN/MAC 号' : '箱号'}</div>`;
return;
}
try {
resultDiv.innerHTML = '<div>查询中...</div>';
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 = `
<div class="result-card success">
<div class="result-title"> 找到出货记录</div>
<div class="result-item"><span class="label">SN/MAC:</span> ${data.sn}</div>
<div class="result-item"><span class="label">机种:</span> <span class="badge">${data.platform_name || ''}</span></div>
<div class="result-item"><span class="label">出货日期:</span> ${data.date}</div>
<div class="result-item"><span class="label">箱号:</span> ${data.box}</div>
<div class="result-item"><span class="label">记录时间:</span> ${data.ts}</div>
</div>
`;
} else {
resultDiv.innerHTML = `
<div class="result-card error">
<div class="result-title"> 未找到记录</div>
<div class="result-item">SN/MAC: ${data.sn}</div>
<div class="result-item">${data.message || '该 SN 没有出货记录'}</div>
</div>
`;
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 = `
<div class="result-card success">
<div class="result-title"> 找到出货记录</div>
<div class="result-item"><span class="label">SN/MAC:</span> ${data.sn}</div>
<div class="result-item"><span class="label">机种:</span> <span class="badge">${data.platform_name || ''}</span></div>
<div class="result-item"><span class="label">出货日期:</span> ${data.date}</div>
<div class="result-item"><span class="label">箱号:</span> ${data.box}</div>
<div class="result-item"><span class="label">记录时间:</span> ${data.ts}</div>
</div>
`;
} else {
resultDiv.innerHTML = `
<div class="result-card error">
<div class="result-title"> 未找到记录</div>
<div class="result-item">SN/MAC: ${data.sn}</div>
<div class="result-item">${data.message || '该 SN 没有出货记录'}</div>
</div>
`;
}
} 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) => `
<div style="padding:12px;background:var(--bg);border:1px solid var(--border);border-radius:6px;margin-bottom:8px">
<div style="font-weight:600;margin-bottom:8px;color:var(--primary)">记录 ${index + 1}</div>
<div class="result-item"><span class="label">SN/MAC:</span> ${record.sn}</div>
<div class="result-item"><span class="label">机种:</span> <span class="badge">${record.platform_name || ''}</span></div>
<div class="result-item"><span class="label">出货日期:</span> ${record.date}</div>
<div class="result-item"><span class="label">记录时间:</span> ${record.ts}</div>
</div>
`).join('');
resultDiv.innerHTML = `
<div class="result-card success">
<div class="result-title"> 找到出货记录</div>
<div class="result-item"><span class="label">箱号:</span> ${data.box}</div>
<div class="result-item"><span class="label">记录数量:</span> <span style="font-weight:600;color:var(--primary)">${data.count}</span></div>
<div style="margin-top:16px;max-height:500px;overflow-y:auto">
${recordsHtml}
</div>
</div>
`;
} else {
resultDiv.innerHTML = `
<div class="result-card error">
<div class="result-title"> 未找到记录</div>
<div class="result-item">箱号: ${data.box}</div>
<div class="result-item">${data.message || '该箱号没有出货记录'}</div>
</div>
`;
}
}
} catch (e) {
resultDiv.innerHTML = `<div class="error">查询失败:${e.message}</div>`;
@ -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 `<div class="card">
<div style="font-weight:600;margin-bottom:16px">SN/MAC 出货查询</div>
<div style="font-weight:600;margin-bottom:16px">发货汇总信息查询</div>
<div style="margin-bottom:20px;padding:12px;background:var(--surface);border:1px solid var(--border);border-radius:8px">
<div id="redis-stats" style="display:flex;align-items:center;justify-content:space-between">
@ -139,16 +198,23 @@ Router.register('/shipments/query', async () => {
<div style="margin-bottom:16px">
<div class="field">
<label>输入 SN/MAC </label>
<label>查询类型</label>
<select id="query-type" class="input">
<option value="sn"> SN/MAC 查询</option>
<option value="box">按箱号查询</option>
</select>
</div>
<div class="field">
<label id="input-label">输入 SN/MAC </label>
<input
id="sn-input"
id="query-input"
class="input"
placeholder="输入 SN 或 MAC 地址"
style="font-family: monospace"
/>
</div>
<div style="display:flex;gap:8px">
<button class="btn" id="sn-query-btn">查询</button>
<button class="btn btn-primary" id="query-btn">查询</button>
${showClearButton ? '<button class="btn" id="clear-redis-btn" style="background:#dc2626">清空所有记录</button>' : ''}
</div>
</div>

View File

@ -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')