Files
yolo/frontend/modules/ui.js
Kunpeng 25fa0c5825 feat: SQLite persistence, non-blocking inference, modular frontend
Backend:
- Persist alert events and robot delivery counters in SQLite (data/app.db,
  YOLO_DB_PATH override); EventStore keeps its interface, DeliveryStatsStore
  uses read/write-through UPSERT; in-memory fallback remains for standalone
  AlertManager use
- Serve /api/detect from a sync endpoint and serialize YOLO inference with a
  lock, so concurrent requests no longer block the event loop
- Unify single-image and session detection: requests without session_id
  share the fixed single-image session and run full frame confirmation
- Store UTC Z-suffixed timestamps for sortable string comparison; close
  executor and database on shutdown via FastAPI lifespan

Frontend:
- Split app.js into ES modules (main.js + modules/{dom,api,ui,charts,store}
  + views/{dashboard,inspection,events,robots,robotCards}), no build step
- Escape all server data interpolated into innerHTML; guard missing
  event.classes; replace lazy element ID list with memoized qs()
- Remove hardcoded fake stats (trend badge, device donut segment)

Docs:
- Rewrite README: accurate weight policy (only trained best.pt committed,
  no Git LFS), SQLite persistence, single-worker note, data asset inventory
- Align models/pretrained/README.md with actual files; add YOLO_DB_PATH to
  .env.example; add persistence unit tests; ruff clean
2026-08-13 16:50:23 +08:00

37 lines
1.2 KiB
JavaScript

import { qs } from "./dom.js";
export function showToast(message, type = "info") {
const toast = document.createElement("div");
toast.className = `toast ${type}`;
toast.textContent = message;
qs("#toastRegion").appendChild(toast);
setTimeout(() => toast.remove(), 3600);
}
export function setServiceStatus(online) {
const statusChip = qs("#globalStatus");
statusChip.textContent = online ? "服务运行正常" : "服务连接异常";
statusChip.className = `status-chip ${online ? "status-online" : "status-offline"}`;
qs("#sidebarStatus").textContent = online ? "服务在线" : "服务离线";
qs("#sidebarStatusDot").className = `status-dot ${online ? "is-online" : "is-offline"}`;
const readyApi = qs("#readyApi");
readyApi.textContent = online ? "正常" : "异常";
readyApi.className = online ? "ready" : "not-ready";
}
export function setChannelReady(element, enabled) {
element.textContent = enabled ? "已启用" : "未配置";
element.className = enabled ? "ready" : "optional";
}
export function updateClock() {
qs("#currentClock").textContent = new Date().toLocaleString("zh-CN", {
hour12: false,
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
});
}