import { apiFetch } from "./api.js";
import { dom } from "./dom.js";
import { loadPoints, loadTree, renderSelectedNodes } from "./points.js";
import { state } from "./state.js";
export function renderSources() {
dom.sourceList.innerHTML = "";
state.sources.forEach((source) => {
const item = document.createElement("div");
item.className = `list-item ${state.selectedSourceId === source.id ? "selected" : ""}`;
item.innerHTML = `
${source.name}
${source.is_connected ? "在线" : "离线"}
${source.endpoint}
`;
item.addEventListener("click", () => {
selectSource(source.id).catch((error) => {
dom.statusText.textContent = error.message;
});
});
const actions = document.createElement("div");
actions.className = "row";
const selectBtn = document.createElement("button");
selectBtn.textContent = "选入点位";
selectBtn.addEventListener("click", (event) => {
event.stopPropagation();
selectSource(source.id)
.then(() => {
dom.pointModal.classList.remove("hidden");
return loadTree();
})
.catch((error) => {
dom.statusText.textContent = error.message;
});
});
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;
});
});
actions.append(selectBtn, editBtn, reconnectBtn, deleteBtn);
item.appendChild(actions);
dom.sourceList.appendChild(item);
});
}
export async function loadSources() {
state.sources = await apiFetch("/api/source");
renderSources();
}
export async function selectSource(sourceId) {
state.selectedSourceId = sourceId;
state.selectedNodeIds.clear();
state.pointsPage = 1;
renderSources();
renderSelectedNodes();
await loadPoints();
await loadTree();
}
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 deleteSource(sourceId) {
if (!window.confirm("确认删除该 Source?")) {
return;
}
await apiFetch(`/api/source/${sourceId}`, { method: "DELETE" });
await loadSources();
}
export async function reconnectSource(sourceId, name) {
dom.statusText.textContent = `正在重连 ${name || "Source"}...`;
await apiFetch(`/api/source/${sourceId}/reconnect`, { method: "POST" });
await loadSources();
dom.statusText.textContent = "Ready";
}
export async function browseNodes() {
if (!state.selectedSourceId) {
throw new Error("请先选择数据源");
}
await apiFetch(`/api/source/${state.selectedSourceId}/browse`, { method: "POST" });
await loadTree();
}