plc_control/web/js/sources.js

140 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 = `
<div class="row">
<strong>${source.name}</strong>
<span class="badge ${source.is_connected ? "" : "offline"}">${source.is_connected ? "在线" : "离线"}</span>
</div>
<div class="muted">${source.endpoint}</div>
`;
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();
}