87 lines
2.5 KiB
JavaScript
87 lines
2.5 KiB
JavaScript
import { apiFetch } from "./api.js";
|
|
import { dom } from "./dom.js";
|
|
import { state } from "./state.js";
|
|
|
|
const PAGE_SIZE = 10;
|
|
|
|
let _page = 1;
|
|
let _hasMore = false;
|
|
let _loading = false;
|
|
|
|
function formatTime(value) {
|
|
return value || "--";
|
|
}
|
|
|
|
function makeCard(item) {
|
|
const row = document.createElement("div");
|
|
const level = (item.level || "info").toLowerCase();
|
|
row.className = "event-card";
|
|
row.innerHTML = `<span class="badge event-badge level-${level}">${level.toUpperCase()}</span><span class="muted event-time">${formatTime(item.created_at)}</span><span class="event-type">${item.event_type}</span><span class="event-message">${item.message}</span>`;
|
|
return row;
|
|
}
|
|
|
|
async function loadMore() {
|
|
if (_loading || !_hasMore) return;
|
|
_loading = true;
|
|
|
|
const params = new URLSearchParams({ page: String(_page), page_size: String(PAGE_SIZE) });
|
|
if (state.selectedUnitId) params.set("unit_id", state.selectedUnitId);
|
|
|
|
try {
|
|
const response = await apiFetch(`/api/event?${params.toString()}`);
|
|
const items = response.data || [];
|
|
items.forEach((item) => dom.eventList.appendChild(makeCard(item)));
|
|
_hasMore = items.length === PAGE_SIZE;
|
|
_page += 1;
|
|
} finally {
|
|
_loading = false;
|
|
}
|
|
}
|
|
|
|
export async function loadEvents() {
|
|
_page = 1;
|
|
_hasMore = false;
|
|
_loading = false;
|
|
dom.eventList.innerHTML = "";
|
|
|
|
const params = new URLSearchParams({ page: "1", page_size: String(PAGE_SIZE) });
|
|
if (state.selectedUnitId) params.set("unit_id", state.selectedUnitId);
|
|
|
|
_loading = true;
|
|
try {
|
|
const response = await apiFetch(`/api/event?${params.toString()}`);
|
|
const items = response.data || [];
|
|
|
|
if (!items.length) {
|
|
dom.eventList.innerHTML = '<div class="list-item"><div class="muted">暂无事件</div></div>';
|
|
return;
|
|
}
|
|
|
|
items.forEach((item) => dom.eventList.appendChild(makeCard(item)));
|
|
_hasMore = items.length === PAGE_SIZE;
|
|
_page = 2;
|
|
} finally {
|
|
_loading = false;
|
|
}
|
|
}
|
|
|
|
export function prependEvent(item) {
|
|
if (state.selectedUnitId && item.unit_id !== state.selectedUnitId) return;
|
|
|
|
const placeholder = dom.eventList.querySelector(".list-item");
|
|
if (placeholder) placeholder.remove();
|
|
|
|
dom.eventList.insertBefore(makeCard(item), dom.eventList.firstChild);
|
|
|
|
// Keep DOM bounded to prevent unbounded growth
|
|
const cards = dom.eventList.querySelectorAll(".event-card");
|
|
if (cards.length > 100) cards[cards.length - 1].remove();
|
|
}
|
|
|
|
dom.eventList.addEventListener("scroll", () => {
|
|
const el = dom.eventList;
|
|
if (el.scrollTop + el.clientHeight >= el.scrollHeight - 40) {
|
|
loadMore();
|
|
}
|
|
});
|