159 lines
5.3 KiB
JavaScript
159 lines
5.3 KiB
JavaScript
|
|
Router.register('/shipments/query', async () => {
|
||
|
|
// 获取当前用户信息
|
||
|
|
let userRole = null;
|
||
|
|
try {
|
||
|
|
const userRes = await fetch('/api/auth/me', { credentials: 'include' });
|
||
|
|
const userData = await userRes.json();
|
||
|
|
userRole = userData.role;
|
||
|
|
} catch (e) {
|
||
|
|
console.error('Failed to get user info:', e);
|
||
|
|
}
|
||
|
|
|
||
|
|
setTimeout(async () => {
|
||
|
|
const queryBtn = document.getElementById('sn-query-btn');
|
||
|
|
const snInput = document.getElementById('sn-input');
|
||
|
|
const resultDiv = document.getElementById('query-result');
|
||
|
|
const statsDiv = document.getElementById('redis-stats');
|
||
|
|
const clearBtn = document.getElementById('clear-redis-btn');
|
||
|
|
|
||
|
|
// 加载统计信息
|
||
|
|
const loadStats = async () => {
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/shipments/redis-stats', {
|
||
|
|
credentials: 'include'
|
||
|
|
});
|
||
|
|
const data = await res.json();
|
||
|
|
|
||
|
|
if (data.count !== undefined) {
|
||
|
|
statsDiv.innerHTML = `
|
||
|
|
<div style="display:flex;align-items:center;gap:12px">
|
||
|
|
<span style="color:var(--text-2)">数据库出货数量:</span>
|
||
|
|
<span style="font-weight:600;font-size:18px;color:var(--primary)">${data.count}</span>
|
||
|
|
</div>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
statsDiv.innerHTML = '<div style="color:var(--text-2)">无法获取统计信息</div>';
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 初始加载统计
|
||
|
|
await loadStats();
|
||
|
|
|
||
|
|
// 根据用户角色控制清空按钮的显示
|
||
|
|
if (clearBtn) {
|
||
|
|
if (userRole !== 'superadmin') {
|
||
|
|
clearBtn.style.display = 'none';
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
const performQuery = async () => {
|
||
|
|
const sn = snInput?.value?.trim();
|
||
|
|
if (!sn) {
|
||
|
|
resultDiv.innerHTML = '<div class="error">请输入 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();
|
||
|
|
|
||
|
|
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>
|
||
|
|
`;
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
resultDiv.innerHTML = `<div class="error">查询失败:${e.message}</div>`;
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
const clearRedis = async () => {
|
||
|
|
if (!confirm('确定要清空所有发货记录吗?此操作不可恢复!')) {
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
|
||
|
|
try {
|
||
|
|
const res = await fetch('/api/shipments/clear-redis', {
|
||
|
|
method: 'POST',
|
||
|
|
credentials: 'include'
|
||
|
|
});
|
||
|
|
const data = await res.json();
|
||
|
|
|
||
|
|
if (data.ok) {
|
||
|
|
alert(data.message || '清空成功');
|
||
|
|
await loadStats();
|
||
|
|
resultDiv.innerHTML = '';
|
||
|
|
} else {
|
||
|
|
alert('清空失败:' + (data.error || '未知错误'));
|
||
|
|
}
|
||
|
|
} catch (e) {
|
||
|
|
alert('清空失败:' + e.message);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
queryBtn?.addEventListener('click', performQuery);
|
||
|
|
|
||
|
|
// 只有超级管理员才绑定清空按钮事件
|
||
|
|
if (clearBtn && userRole === 'superadmin') {
|
||
|
|
clearBtn.addEventListener('click', clearRedis);
|
||
|
|
}
|
||
|
|
|
||
|
|
snInput?.addEventListener('keypress', (e) => {
|
||
|
|
if (e.key === 'Enter') {
|
||
|
|
performQuery();
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}, 0);
|
||
|
|
|
||
|
|
// 根据用户角色决定是否显示清空按钮
|
||
|
|
const showClearButton = userRole === 'superadmin';
|
||
|
|
|
||
|
|
return `<div class="card">
|
||
|
|
<div style="font-weight:600;margin-bottom:16px">SN/MAC 出货查询</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">
|
||
|
|
<div>加载中...</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div style="margin-bottom:16px">
|
||
|
|
<div class="field">
|
||
|
|
<label>输入 SN/MAC 号</label>
|
||
|
|
<input
|
||
|
|
id="sn-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>
|
||
|
|
${showClearButton ? '<button class="btn" id="clear-redis-btn" style="background:#dc2626">清空所有记录</button>' : ''}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
|
||
|
|
<div id="query-result"></div>
|
||
|
|
</div>`;
|
||
|
|
});
|