diff --git a/web/html/logs-panel.html b/web/html/logs-panel.html index 578dfa0..82af729 100644 --- a/web/html/logs-panel.html +++ b/web/html/logs-panel.html @@ -1,18 +1,7 @@
-
-
-
-

系统事件

- -
-
-
- -
-
-

实时日志

-
-
-
+
+

系统事件

+
+
diff --git a/web/js/app.js b/web/js/app.js index 7c41cb5..84b3d0f 100644 --- a/web/js/app.js +++ b/web/js/app.js @@ -14,7 +14,7 @@ import { resetEquipmentForm, saveEquipment, } from "./equipment.js"; -import { startLogs, startPointSocket } from "./logs.js"; +import { startPointSocket } from "./logs.js"; import { clearBatchBinding, browseAndLoadTree, @@ -136,7 +136,6 @@ async function bootstrap() { updateSelectedPointSummary(); updatePointFilterSummary(); renderChart(); - startLogs(); startPointSocket(); await withStatus(loadUnits()); diff --git a/web/js/dom.js b/web/js/dom.js index 32292de..c55418f 100644 --- a/web/js/dom.js +++ b/web/js/dom.js @@ -15,7 +15,6 @@ export const dom = { pointSourceSelect: byId("pointSourceSelect"), pointSourceNodeCount: byId("pointSourceNodeCount"), openPointModalBtn: byId("openPointModal"), - logView: byId("logView"), chartCanvas: byId("chartCanvas"), chartTitle: byId("chartTitle"), chartSummary: byId("chartSummary"), diff --git a/web/js/events.js b/web/js/events.js index e4aa0a4..f796808 100644 --- a/web/js/events.js +++ b/web/js/events.js @@ -19,15 +19,8 @@ export function renderEvents() { state.events.forEach((item) => { const row = document.createElement("div"); - row.className = "list-item event-card"; - row.innerHTML = ` -
- ${item.event_type} - ${(item.level || "info").toUpperCase()} -
-
${item.message}
-
${formatTime(item.created_at)}
- `; + row.className = "event-card"; + row.innerHTML = `${(item.level || "info").toUpperCase()}${item.event_type}${item.message}${formatTime(item.created_at)}`; dom.eventList.appendChild(row); }); } diff --git a/web/js/logs.js b/web/js/logs.js index d87f846..f2caeea 100644 --- a/web/js/logs.js +++ b/web/js/logs.js @@ -1,73 +1,9 @@ import { appendChartPoint } from "./chart.js"; -import { dom } from "./dom.js"; import { prependEvent } from "./events.js"; import { formatValue } from "./points.js"; import { state } from "./state.js"; import { renderUnits } from "./units.js"; -function escapeHtml(text) { - return text - .replaceAll("&", "&") - .replaceAll("<", "<") - .replaceAll(">", ">"); -} - -function parseLogLine(line) { - const trimmed = line.trim(); - if (!trimmed.startsWith("{") || !trimmed.endsWith("}")) { - return null; - } - - try { - return JSON.parse(trimmed); - } catch { - return null; - } -} - -export function appendLog(line) { - const atBottom = dom.logView.scrollTop + dom.logView.clientHeight >= dom.logView.scrollHeight - 10; - const div = document.createElement("div"); - const parsed = parseLogLine(line); - - if (!parsed) { - div.className = "log-line"; - div.textContent = line; - } else { - const levelRaw = (parsed.level || "").toString(); - const level = levelRaw.toLowerCase(); - div.className = `log-line${level ? ` level-${level}` : ""}`; - div.innerHTML = [ - `${escapeHtml(levelRaw || "LOG")}`, - parsed.timestamp ? ` ${escapeHtml(parsed.timestamp)}` : "", - parsed.target ? ` ${escapeHtml(parsed.target)}` : "", - `${escapeHtml( - parsed.fields?.message || parsed.message || parsed.msg || line, - )}`, - ].join(""); - } - - dom.logView.appendChild(div); - if (atBottom) { - dom.logView.scrollTop = dom.logView.scrollHeight; - } -} - -export function startLogs() { - if (state.logSource) { - state.logSource.close(); - } - - state.logSource = new EventSource("/api/logs/stream"); - state.logSource.addEventListener("log", (event) => { - const data = JSON.parse(event.data); - (data.lines || []).forEach(appendLog); - }); - state.logSource.addEventListener("error", () => { - appendLog("[log stream error]"); - }); -} - export function startPointSocket() { const protocol = location.protocol === "https:" ? "wss" : "ws"; const ws = new WebSocket(`${protocol}://${location.host}/ws/public`); diff --git a/web/js/state.js b/web/js/state.js index 5692ffc..ae317e7 100644 --- a/web/js/state.js +++ b/web/js/state.js @@ -18,7 +18,6 @@ export const state = { chartPointId: null, chartPointName: "", chartData: [], - logSource: null, pointSocket: null, apiDocLoaded: false, runtimes: new Map(), // unit_id -> UnitRuntime diff --git a/web/styles.css b/web/styles.css index 62b6583..e6b475f 100644 --- a/web/styles.css +++ b/web/styles.css @@ -660,8 +660,7 @@ button.danger:hover { background: var(--danger-hover); } max-height: 50vh; } -.unit-list, -.event-list { +.unit-list { padding-top: 6px; } @@ -670,20 +669,32 @@ button.danger:hover { background: var(--danger-hover); } } .event-card { - cursor: default; + display: flex; + align-items: baseline; + gap: 8px; + padding: 3px 8px; + font-size: 12px; + border-bottom: 1px solid var(--border); + white-space: nowrap; } .event-card:hover { - background: var(--surface); - border-color: var(--border); + background: var(--surface-hover, var(--surface)); } -.event-section { - flex-basis: 42%; +.event-type { + flex-shrink: 0; } -.log-section { - flex-basis: 58%; +.event-message { + flex: 1; + overflow: hidden; + text-overflow: ellipsis; +} + +.event-time { + flex-shrink: 0; + font-size: 11px; } .equipment-select-row {