feat(feeder): add three-tab UI (ops / app-config / platform-config)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c961fc0298
commit
9955498e24
|
|
@ -133,6 +133,16 @@ body {
|
||||||
grid-template-rows: 1fr 260px;
|
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 */
|
/* config view slot assignments */
|
||||||
.grid-config .panel.top-left { grid-column: 1; grid-row: 1; }
|
.grid-config .panel.top-left { grid-column: 1; grid-row: 1; }
|
||||||
.grid-config .panel.top-right { grid-column: 2 / 4; 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;
|
grid-template-rows: auto auto auto auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
}
|
}
|
||||||
|
.grid-app-config {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
body { height: auto; overflow: auto; }
|
body { height: auto; overflow: auto; }
|
||||||
.panel.top-left { min-height: 200px; }
|
.panel.top-left { min-height: 200px; }
|
||||||
.panel.top-right { min-height: 300px; }
|
.panel.top-right { min-height: 300px; }
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
<header class="topbar">
|
<header class="topbar">
|
||||||
<div class="title">PLC Control</div>
|
<div class="title">投煤器布料机控制系统</div>
|
||||||
<div class="tab-bar">
|
<div class="tab-bar">
|
||||||
<button type="button" class="tab-btn active" id="tabOps">运维</button>
|
<button type="button" class="tab-btn active" id="tabOps">运维</button>
|
||||||
<button type="button" class="tab-btn" id="tabConfig">配置</button>
|
<button type="button" class="tab-btn" id="tabAppConfig">应用配置</button>
|
||||||
|
<button type="button" class="tab-btn" id="tabConfig">平台配置</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="topbar-actions">
|
<div class="topbar-actions">
|
||||||
<button type="button" class="secondary" id="openReadmeDoc">README.md</button>
|
<button type="button" class="secondary" id="openReadmeDoc">README.md</button>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
<section class="panel app-config-main">
|
||||||
|
<div class="panel-head">
|
||||||
|
<h2>控制单元配置</h2>
|
||||||
|
<div class="toolbar">
|
||||||
|
<button type="button" class="secondary" id="refreshUnitBtn2">刷新</button>
|
||||||
|
<button type="button" id="newUnitBtn2">+ 新增</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list unit-config-list" id="unitConfigList"></div>
|
||||||
|
</section>
|
||||||
|
|
@ -15,8 +15,9 @@
|
||||||
<div data-partial="/ui/html/points-panel.html"></div>
|
<div data-partial="/ui/html/points-panel.html"></div>
|
||||||
<div data-partial="/ui/html/source-panel.html"></div>
|
<div data-partial="/ui/html/source-panel.html"></div>
|
||||||
<div data-partial="/ui/html/log-stream-panel.html"></div>
|
<div data-partial="/ui/html/log-stream-panel.html"></div>
|
||||||
<div data-partial="/ui/html/logs-panel.html"></div>
|
|
||||||
<div data-partial="/ui/html/chart-panel.html"></div>
|
<div data-partial="/ui/html/chart-panel.html"></div>
|
||||||
|
<div data-partial="/ui/html/unit-panel.html"></div>
|
||||||
|
<div data-partial="/ui/html/logs-panel.html"></div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<div data-partial="/ui/html/modals.html"></div>
|
<div data-partial="/ui/html/modals.html"></div>
|
||||||
|
|
|
||||||
|
|
@ -35,29 +35,37 @@ import { loadSources, saveSource } from "./sources.js";
|
||||||
import { closeUnitModal, loadUnits, openCreateUnitModal, resetUnitForm, renderUnits, saveUnit } from "./units.js";
|
import { closeUnitModal, loadUnits, openCreateUnitModal, resetUnitForm, renderUnits, saveUnit } from "./units.js";
|
||||||
|
|
||||||
let _configLoaded = false;
|
let _configLoaded = false;
|
||||||
|
let _appConfigLoaded = false;
|
||||||
|
|
||||||
function switchView(view) {
|
function switchView(view) {
|
||||||
state.activeView = view;
|
state.activeView = view;
|
||||||
const main = document.querySelector("main");
|
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.tabOps.classList.toggle("active", view === "ops");
|
||||||
|
dom.tabAppConfig.classList.toggle("active", view === "app-config");
|
||||||
dom.tabConfig.classList.toggle("active", view === "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) => {
|
["top-left", "top-right", "bottom-left", "bottom-right"].forEach((cls) => {
|
||||||
const el = main.querySelector(`.panel.${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");
|
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
|
// ops-only panels
|
||||||
const opsMain = main.querySelector(".panel.ops-main");
|
const opsMain = main.querySelector(".panel.ops-main");
|
||||||
const opsBottom = main.querySelector(".panel.ops-bottom");
|
const opsBottom = main.querySelector(".panel.ops-bottom");
|
||||||
if (opsMain) opsMain.classList.toggle("hidden", view === "config");
|
if (opsMain) opsMain.classList.toggle("hidden", view !== "ops");
|
||||||
if (opsBottom) opsBottom.classList.toggle("hidden", view === "config");
|
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") {
|
if (view === "config") {
|
||||||
startLogs();
|
startLogs();
|
||||||
|
|
@ -71,6 +79,13 @@ function switchView(view) {
|
||||||
} else {
|
} else {
|
||||||
stopLogs();
|
stopLogs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (view === "app-config") {
|
||||||
|
if (!_appConfigLoaded) {
|
||||||
|
_appConfigLoaded = true;
|
||||||
|
withStatus(loadUnits());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function bindEvents() {
|
function bindEvents() {
|
||||||
|
|
@ -165,8 +180,12 @@ function bindEvents() {
|
||||||
});
|
});
|
||||||
|
|
||||||
dom.tabOps.addEventListener("click", () => switchView("ops"));
|
dom.tabOps.addEventListener("click", () => switchView("ops"));
|
||||||
|
dom.tabAppConfig.addEventListener("click", () => switchView("app-config"));
|
||||||
dom.tabConfig.addEventListener("click", () => switchView("config"));
|
dom.tabConfig.addEventListener("click", () => switchView("config"));
|
||||||
|
|
||||||
|
dom.refreshUnitBtn2.addEventListener("click", () => withStatus(loadUnits()));
|
||||||
|
dom.newUnitBtn2.addEventListener("click", openCreateUnitModal);
|
||||||
|
|
||||||
document.addEventListener("equipments-updated", () => {
|
document.addEventListener("equipments-updated", () => {
|
||||||
renderUnits();
|
renderUnits();
|
||||||
// Re-fetch units so embedded equipment data stays in sync with config changes.
|
// Re-fetch units so embedded equipment data stays in sync with config changes.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ export const dom = {
|
||||||
batchStartAutoBtn: byId("batchStartAutoBtn"),
|
batchStartAutoBtn: byId("batchStartAutoBtn"),
|
||||||
batchStopAutoBtn: byId("batchStopAutoBtn"),
|
batchStopAutoBtn: byId("batchStopAutoBtn"),
|
||||||
tabOps: byId("tabOps"),
|
tabOps: byId("tabOps"),
|
||||||
|
tabAppConfig: byId("tabAppConfig"),
|
||||||
tabConfig: byId("tabConfig"),
|
tabConfig: byId("tabConfig"),
|
||||||
opsUnitList: byId("opsUnitList"),
|
opsUnitList: byId("opsUnitList"),
|
||||||
opsEquipmentArea: byId("opsEquipmentArea"),
|
opsEquipmentArea: byId("opsEquipmentArea"),
|
||||||
|
|
@ -65,6 +66,9 @@ export const dom = {
|
||||||
equipmentList: byId("equipmentList"),
|
equipmentList: byId("equipmentList"),
|
||||||
refreshUnitBtn: byId("refreshUnitBtn"),
|
refreshUnitBtn: byId("refreshUnitBtn"),
|
||||||
newUnitBtn: byId("newUnitBtn"),
|
newUnitBtn: byId("newUnitBtn"),
|
||||||
|
refreshUnitBtn2: byId("refreshUnitBtn2"),
|
||||||
|
newUnitBtn2: byId("newUnitBtn2"),
|
||||||
|
unitConfigList: byId("unitConfigList"),
|
||||||
closeUnitModalBtn: byId("closeUnitModal"),
|
closeUnitModalBtn: byId("closeUnitModal"),
|
||||||
closeEquipmentModalBtn: byId("closeEquipmentModal"),
|
closeEquipmentModalBtn: byId("closeEquipmentModal"),
|
||||||
refreshEventBtn: byId("refreshEventBtn"),
|
refreshEventBtn: byId("refreshEventBtn"),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue