feat: edc-web 设备日志管理页 + 在线状态实时刷新
- 新增 /device-logs 设备事件日志管理页 (admin 权限) - 支持按设备序列号/事件类型筛选查询 - 支持 admin 按条件删除日志 - 不同事件类型彩色标识 (在线=绿, 离线=红, 通信不良=橙) - 新增 /api/devices/<id>/status 设备状态 API - 设备列表页:每 5s 异步刷新所有设备在线状态 - 测试操作页:顶部显示设备状态,每 5s 异步刷新 - dnt_info state 支持三态显示 (在线/离线/通信不良) - 导航栏增加「设备日志」入口 (admin only)
This commit is contained in:
@@ -23,6 +23,7 @@ tr:hover { background: #f8f9fa; }
|
||||
/* === Online Status === */
|
||||
.status-online { color: #27ae60; font-weight: 600; }
|
||||
.status-offline { color: #bdc3c7; }
|
||||
.status-poor { color: #f39c12; font-weight: 600; }
|
||||
|
||||
/* === Editable Name === */
|
||||
.editable-name { cursor: pointer; border-bottom: 1px dashed transparent; }
|
||||
|
||||
@@ -8,15 +8,18 @@ async function loadDevices() {
|
||||
|
||||
function renderTable(devices) {
|
||||
const tbody = document.querySelector("#device-table tbody");
|
||||
tbody.innerHTML = devices.map(d => `
|
||||
tbody.innerHTML = devices.map(d => {
|
||||
const stateLabel = getStateLabel(d.state);
|
||||
const stateClass = getStateClass(d.state);
|
||||
return `
|
||||
<tr>
|
||||
<td>${d.serial}</td>
|
||||
<td class="editable-name" onclick="editName(${d.id}, '${esc(d.name)}', this)">
|
||||
${d.name || '(点击编辑)'}
|
||||
</td>
|
||||
<td>${d.ip || '-'}</td>
|
||||
<td class="${d.state === 1 ? 'status-online' : 'status-offline'}">
|
||||
${d.state === 1 ? '在线' : '离线'}
|
||||
<td class="${stateClass} status-cell" data-device-id="${d.id}">
|
||||
${stateLabel}
|
||||
</td>
|
||||
<td>${d.version || '-'}</td>
|
||||
<td>${d.last_login || '-'}</td>
|
||||
@@ -24,8 +27,36 @@ function renderTable(devices) {
|
||||
<button class="btn-test" onclick="location.href='/test/${d.id}'">测试</button>
|
||||
${USER_ROLE === 'admin' ? `<button class="btn-config" onclick="location.href='/fixture/${d.id}'">配置</button>` : ''}
|
||||
</td>
|
||||
</tr>
|
||||
`).join("");
|
||||
</tr>`;
|
||||
}).join("");
|
||||
}
|
||||
|
||||
function getStateLabel(state) {
|
||||
return {0: '离线', 1: '在线', 2: '通信不良'}[state] || '未知';
|
||||
}
|
||||
|
||||
function getStateClass(state) {
|
||||
return {0: 'status-offline', 1: 'status-online', 2: 'status-poor'}[state] || '';
|
||||
}
|
||||
|
||||
// 异步刷新所有设备的在线状态
|
||||
async function refreshDeviceStatuses() {
|
||||
const cells = document.querySelectorAll(".status-cell");
|
||||
for (const cell of cells) {
|
||||
const deviceId = cell.dataset.deviceId;
|
||||
if (!deviceId) continue;
|
||||
try {
|
||||
const resp = await fetch(`/api/devices/${deviceId}/status`);
|
||||
const data = await resp.json();
|
||||
if (data.ok) {
|
||||
cell.textContent = data.state_name;
|
||||
cell.className = getStateClass(data.state) + " status-cell";
|
||||
cell.dataset.deviceId = deviceId;
|
||||
}
|
||||
} catch (e) {
|
||||
// 网络错误静默跳过
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function esc(s) { return s.replace(/'/g, "\\'").replace(/"/g, """); }
|
||||
@@ -52,3 +83,5 @@ async function editName(id, currentName, td) {
|
||||
}
|
||||
|
||||
loadDevices();
|
||||
// 每 5 秒异步刷新设备在线状态
|
||||
setInterval(refreshDeviceStatuses, 5000);
|
||||
|
||||
@@ -290,6 +290,7 @@ function updateTestModeUI(mode) {
|
||||
|
||||
async function loadInitialData() {
|
||||
await loadTestMode();
|
||||
refreshDeviceStatus();
|
||||
try {
|
||||
const resp = await fetch(`/api/automation/${DNT_ID}/progress`);
|
||||
const data = await resp.json();
|
||||
@@ -301,6 +302,33 @@ async function loadInitialData() {
|
||||
}
|
||||
loadInitialData();
|
||||
|
||||
// ─── 设备状态异步刷新 ──────────────────────────
|
||||
|
||||
async function refreshDeviceStatus() {
|
||||
try {
|
||||
const resp = await fetch(`/api/devices/${DNT_ID}/status`);
|
||||
const data = await resp.json();
|
||||
if (data.ok) {
|
||||
const el = document.getElementById("device-status-text");
|
||||
if (el) {
|
||||
el.textContent = data.state_name;
|
||||
if (data.state === 1) {
|
||||
el.className = "status-online";
|
||||
} else if (data.state === 2) {
|
||||
el.className = "status-poor";
|
||||
} else {
|
||||
el.className = "status-offline";
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
// 静默失败
|
||||
}
|
||||
}
|
||||
|
||||
// 每 5 秒刷新设备状态
|
||||
setInterval(refreshDeviceStatus, 5000);
|
||||
|
||||
// ─── UI ────────────────────────────────────────
|
||||
|
||||
function setStatus(msg) {
|
||||
|
||||
Reference in New Issue
Block a user