From 9955498e2415731034c00c2ecc8fbbd5e8112ae9 Mon Sep 17 00:00:00 2001 From: caoqianming Date: Fri, 17 Apr 2026 13:34:18 +0800 Subject: [PATCH] feat(feeder): add three-tab UI (ops / app-config / platform-config) Co-Authored-By: Claude Opus 4.6 --- web/core/styles.css | 15 +++++++++++++++ web/feeder/html/topbar.html | 5 +++-- web/feeder/html/unit-panel.html | 10 ++++++++++ web/feeder/index.html | 3 ++- web/feeder/js/app.js | 33 ++++++++++++++++++++++++++------- web/feeder/js/dom.js | 4 ++++ 6 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 web/feeder/html/unit-panel.html diff --git a/web/core/styles.css b/web/core/styles.css index 0e63918..caa41d7 100644 --- a/web/core/styles.css +++ b/web/core/styles.css @@ -133,6 +133,16 @@ body { grid-template-rows: 1fr 260px; } +.grid-app-config { + display: grid; + gap: 1px; + height: calc(100vh - var(--topbar-h)); + grid-template-columns: 1fr; + grid-template-rows: 1fr; +} + +.grid-app-config .panel.app-config-main { grid-column: 1; grid-row: 1; } + /* config view slot assignments */ .grid-config .panel.top-left { grid-column: 1; grid-row: 1; } .grid-config .panel.top-right { grid-column: 2 / 4; grid-row: 1; } @@ -1315,6 +1325,11 @@ button.danger:hover { background: var(--danger-hover); } grid-template-rows: auto auto auto auto; height: auto; } + .grid-app-config { + grid-template-columns: 1fr; + grid-template-rows: auto; + height: auto; + } body { height: auto; overflow: auto; } .panel.top-left { min-height: 200px; } .panel.top-right { min-height: 300px; } diff --git a/web/feeder/html/topbar.html b/web/feeder/html/topbar.html index 5169ac8..b36defc 100644 --- a/web/feeder/html/topbar.html +++ b/web/feeder/html/topbar.html @@ -1,8 +1,9 @@
-
PLC Control
+
投煤器布料机控制系统
- + +
diff --git a/web/feeder/html/unit-panel.html b/web/feeder/html/unit-panel.html new file mode 100644 index 0000000..7b64ca9 --- /dev/null +++ b/web/feeder/html/unit-panel.html @@ -0,0 +1,10 @@ +
+
+

控制单元配置

+
+ + +
+
+
+
diff --git a/web/feeder/index.html b/web/feeder/index.html index db1e4d2..0412de8 100644 --- a/web/feeder/index.html +++ b/web/feeder/index.html @@ -15,8 +15,9 @@
-
+
+
diff --git a/web/feeder/js/app.js b/web/feeder/js/app.js index c7e36a0..11daa1b 100644 --- a/web/feeder/js/app.js +++ b/web/feeder/js/app.js @@ -35,29 +35,37 @@ import { loadSources, saveSource } from "./sources.js"; import { closeUnitModal, loadUnits, openCreateUnitModal, resetUnitForm, renderUnits, saveUnit } from "./units.js"; let _configLoaded = false; +let _appConfigLoaded = false; function switchView(view) { state.activeView = view; const main = document.querySelector("main"); - main.className = view === "ops" ? "grid-ops" : "grid-config"; + main.className = + view === "ops" ? "grid-ops" : + view === "app-config" ? "grid-app-config" : + "grid-config"; dom.tabOps.classList.toggle("active", view === "ops"); + dom.tabAppConfig.classList.toggle("active", view === "app-config"); dom.tabConfig.classList.toggle("active", view === "config"); - // config-only panels + // config-only panels (platform config view) ["top-left", "top-right", "bottom-left", "bottom-right"].forEach((cls) => { const el = main.querySelector(`.panel.${cls}`); - if (el) el.classList.toggle("hidden", view === "ops"); + if (el) el.classList.toggle("hidden", view !== "config"); }); - // bottom-mid is log-stream in config, hidden in ops const logStreamPanel = main.querySelector(".panel.bottom-mid"); - if (logStreamPanel) logStreamPanel.classList.toggle("hidden", view === "ops"); + if (logStreamPanel) logStreamPanel.classList.toggle("hidden", view !== "config"); // ops-only panels const opsMain = main.querySelector(".panel.ops-main"); const opsBottom = main.querySelector(".panel.ops-bottom"); - if (opsMain) opsMain.classList.toggle("hidden", view === "config"); - if (opsBottom) opsBottom.classList.toggle("hidden", view === "config"); + if (opsMain) opsMain.classList.toggle("hidden", view !== "ops"); + if (opsBottom) opsBottom.classList.toggle("hidden", view !== "ops"); + + // app-config-only panels + const appConfigMain = main.querySelector(".panel.app-config-main"); + if (appConfigMain) appConfigMain.classList.toggle("hidden", view !== "app-config"); if (view === "config") { startLogs(); @@ -71,6 +79,13 @@ function switchView(view) { } else { stopLogs(); } + + if (view === "app-config") { + if (!_appConfigLoaded) { + _appConfigLoaded = true; + withStatus(loadUnits()); + } + } } function bindEvents() { @@ -165,8 +180,12 @@ function bindEvents() { }); dom.tabOps.addEventListener("click", () => switchView("ops")); + dom.tabAppConfig.addEventListener("click", () => switchView("app-config")); dom.tabConfig.addEventListener("click", () => switchView("config")); + dom.refreshUnitBtn2.addEventListener("click", () => withStatus(loadUnits())); + dom.newUnitBtn2.addEventListener("click", openCreateUnitModal); + document.addEventListener("equipments-updated", () => { renderUnits(); // Re-fetch units so embedded equipment data stays in sync with config changes. diff --git a/web/feeder/js/dom.js b/web/feeder/js/dom.js index 4636cf4..633f5ed 100644 --- a/web/feeder/js/dom.js +++ b/web/feeder/js/dom.js @@ -7,6 +7,7 @@ export const dom = { batchStartAutoBtn: byId("batchStartAutoBtn"), batchStopAutoBtn: byId("batchStopAutoBtn"), tabOps: byId("tabOps"), + tabAppConfig: byId("tabAppConfig"), tabConfig: byId("tabConfig"), opsUnitList: byId("opsUnitList"), opsEquipmentArea: byId("opsEquipmentArea"), @@ -65,6 +66,9 @@ export const dom = { equipmentList: byId("equipmentList"), refreshUnitBtn: byId("refreshUnitBtn"), newUnitBtn: byId("newUnitBtn"), + refreshUnitBtn2: byId("refreshUnitBtn2"), + newUnitBtn2: byId("newUnitBtn2"), + unitConfigList: byId("unitConfigList"), closeUnitModalBtn: byId("closeUnitModal"), closeEquipmentModalBtn: byId("closeEquipmentModal"), refreshEventBtn: byId("refreshEventBtn"),