import { apiFetch } from "./api.js"; import { dom } from "./dom.js"; import { loadPoints, updatePointFilterSummary } from "./points.js"; import { state } from "./state.js"; function renderPointSourceOptions() { if (!dom.pointSourceSelect) { return; } const options = ['']; state.sources.forEach((source) => { const selected = source.id === state.selectedSourceId ? "selected" : ""; options.push(``); }); dom.pointSourceSelect.innerHTML = options.join(""); } export function renderSources() { dom.sourceList.innerHTML = ""; state.sources.forEach((source) => { const card = document.createElement("div"); card.className = `list-item source-card ${state.selectedSourceId === source.id ? "selected" : ""}`; card.innerHTML = `
${source.name} ${source.is_connected ? "ONLINE" : "OFFLINE"}
${source.endpoint}
`; card.addEventListener("click", () => { selectSource(source.id).catch((error) => { dom.statusText.textContent = error.message; }); }); const actionRow = card.querySelector(".source-card-actions"); const editBtn = document.createElement("button"); editBtn.className = "secondary"; editBtn.textContent = "编辑"; editBtn.addEventListener("click", (event) => { event.stopPropagation(); dom.sourceId.value = source.id; dom.sourceName.value = source.name || ""; dom.sourceEndpoint.value = source.endpoint || ""; dom.sourceEnabled.checked = !!source.enabled; dom.sourceModal.classList.remove("hidden"); }); const reconnectBtn = document.createElement("button"); reconnectBtn.className = "secondary"; reconnectBtn.textContent = "重连"; reconnectBtn.addEventListener("click", (event) => { event.stopPropagation(); reconnectSource(source.id, source.name).catch((error) => { dom.statusText.textContent = error.message; }); }); const deleteBtn = document.createElement("button"); deleteBtn.className = "danger"; deleteBtn.textContent = "删除"; deleteBtn.addEventListener("click", (event) => { event.stopPropagation(); deleteSource(source.id).catch((error) => { dom.statusText.textContent = error.message; }); }); actionRow.append(editBtn, reconnectBtn, deleteBtn); card.appendChild(actionRow); dom.sourceList.appendChild(card); }); renderPointSourceOptions(); } export async function loadSources() { state.sources = await apiFetch("/api/source"); if (state.selectedSourceId && !state.sources.some((item) => item.id === state.selectedSourceId)) { state.selectedSourceId = null; } renderSources(); updatePointFilterSummary(); } export async function selectSource(sourceId) { state.selectedSourceId = state.selectedSourceId === sourceId ? null : sourceId; state.selectedNodeIds.clear(); state.pointsPage = 1; renderSources(); updatePointFilterSummary(); await loadPoints(); } export async function saveSource(event) { event.preventDefault(); const payload = { name: dom.sourceName.value.trim(), endpoint: dom.sourceEndpoint.value.trim(), enabled: dom.sourceEnabled.checked, }; const id = dom.sourceId.value; await apiFetch(id ? `/api/source/${id}` : "/api/source", { method: id ? "PUT" : "POST", body: JSON.stringify(payload), }); dom.sourceModal.classList.add("hidden"); dom.sourceForm.reset(); await loadSources(); } export async function reconnectSource(sourceId, name) { dom.statusText.textContent = `正在重连 ${name || "数据源"}...`; await apiFetch(`/api/source/${sourceId}/reconnect`, { method: "POST" }); await loadSources(); dom.statusText.textContent = "就绪"; } export async function deleteSource(sourceId) { if (!window.confirm("确认删除该数据源?")) { return; } await apiFetch(`/api/source/${sourceId}`, { method: "DELETE" }); if (state.selectedSourceId === sourceId) { state.selectedSourceId = null; } await loadSources(); await loadPoints(); }