feat(frontend): show runtime state and auto/ack buttons on unit cards
This commit is contained in:
parent
31ccf49b75
commit
89023e867b
|
|
@ -74,6 +74,27 @@ async function selectUnit(unitId) {
|
|||
await loadEvents();
|
||||
}
|
||||
|
||||
function runtimeBadge(runtime) {
|
||||
if (!runtime) return '<span class="badge offline">OFFLINE</span>';
|
||||
const stateLabels = {
|
||||
stopped: 'STOPPED',
|
||||
running: 'RUNNING',
|
||||
distributor_running: 'DIST RUN',
|
||||
fault_locked: 'FAULT',
|
||||
comm_locked: 'COMM ERR',
|
||||
};
|
||||
const stateCls = {
|
||||
stopped: '',
|
||||
running: 'online',
|
||||
distributor_running: 'online',
|
||||
fault_locked: 'danger',
|
||||
comm_locked: 'offline',
|
||||
};
|
||||
const label = stateLabels[runtime.state] ?? runtime.state;
|
||||
const cls = stateCls[runtime.state] ?? '';
|
||||
return `<span class="badge ${cls}">${label}</span>`;
|
||||
}
|
||||
|
||||
export function renderUnits() {
|
||||
dom.unitList.innerHTML = "";
|
||||
|
||||
|
|
@ -86,13 +107,15 @@ export function renderUnits() {
|
|||
const card = document.createElement("div");
|
||||
const selected = state.selectedUnitId === unit.id;
|
||||
card.className = `list-item unit-card ${selected ? "selected" : ""}`;
|
||||
const runtime = state.runtimes.get(unit.id);
|
||||
card.innerHTML = `
|
||||
<div class="row">
|
||||
<strong>${unit.code}</strong>
|
||||
<span class="badge ${unit.enabled ? "" : "offline"}">${unit.enabled ? "ENABLED" : "DISABLED"}</span>
|
||||
${runtimeBadge(runtime)}
|
||||
<span class="badge ${unit.enabled ? "" : "offline"}">${unit.enabled ? "EN" : "DIS"}</span>
|
||||
</div>
|
||||
<div>${unit.name}</div>
|
||||
<div class="muted">设备 ${equipmentCount(unit.id)} 台</div>
|
||||
<div class="muted">设备 ${equipmentCount(unit.id)} 台 | Acc ${runtime ? Math.floor(runtime.accumulated_run_sec / 1000) : 0}s</div>
|
||||
<div class="muted">Run ${unit.run_time_sec}s / Stop ${unit.stop_time_sec}s / Acc ${unit.acc_time_sec}s / BL ${unit.bl_time_sec}s</div>
|
||||
<div class="row unit-card-actions"></div>
|
||||
`;
|
||||
|
|
@ -124,6 +147,32 @@ export function renderUnits() {
|
|||
});
|
||||
|
||||
actions.append(editBtn, deleteBtn);
|
||||
|
||||
const isAutoOn = runtime?.auto_enabled;
|
||||
const autoBtn = document.createElement("button");
|
||||
autoBtn.className = isAutoOn ? "danger" : "secondary";
|
||||
autoBtn.textContent = isAutoOn ? "Stop Auto" : "Start Auto";
|
||||
autoBtn.title = isAutoOn ? "停止自动控制" : "启动自动控制";
|
||||
autoBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
const url = `/api/control/unit/${unit.id}/${isAutoOn ? "stop-auto" : "start-auto"}`;
|
||||
apiFetch(url, { method: "POST" }).then(() => loadUnits()).catch(() => {});
|
||||
});
|
||||
actions.append(autoBtn);
|
||||
|
||||
if (runtime?.manual_ack_required) {
|
||||
const ackBtn = document.createElement("button");
|
||||
ackBtn.className = "danger";
|
||||
ackBtn.textContent = "Ack Fault";
|
||||
ackBtn.title = "人工确认解除故障锁定";
|
||||
ackBtn.addEventListener("click", (e) => {
|
||||
e.stopPropagation();
|
||||
apiFetch(`/api/control/unit/${unit.id}/ack-fault`, { method: "POST" })
|
||||
.then(() => loadUnits()).catch(() => {});
|
||||
});
|
||||
actions.append(ackBtn);
|
||||
}
|
||||
|
||||
dom.unitList.appendChild(card);
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue