From ee1c29c34fa3f2bf01df46deff06f68497fc029f Mon Sep 17 00:00:00 2001 From: Maxim Date: Thu, 7 May 2026 14:17:12 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BF=D1=80=D0=BE=D0=BC=D0=B5=D0=B6=D1=83?= =?UTF-8?q?=D1=82=D0=BE=D1=87=D0=BD=D0=B0=D1=8F=20=D1=80=D0=B0=D0=B1=D0=BE?= =?UTF-8?q?=D1=82=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/server/web/css/style.css | 75 +++++++++++++++++++++++++++++++++++ cmd/server/web/dashboard.html | 26 +++++++----- cmd/server/web/js/app.js | 61 +++++++++++++++++----------- 3 files changed, 128 insertions(+), 34 deletions(-) diff --git a/cmd/server/web/css/style.css b/cmd/server/web/css/style.css index 961b1d4..bcbc77c 100644 --- a/cmd/server/web/css/style.css +++ b/cmd/server/web/css/style.css @@ -196,3 +196,78 @@ h1 { font-size: 15px; } } + +.accordion-header { + cursor: pointer; + user-select: none; +} + +.accordion-header:hover { + opacity: 0.7; +} + +.accordion-body { + max-height: 520px; + overflow: hidden; + transition: max-height 0.3s ease; +} + +.accordion-body.collapsed { + max-height: 0; +} + +.progress-with-signal { + display: flex; + align-items: center; + gap: 0; +} + +.progress-90 { + flex: 0 0 86%; + margin-right: 10px; +} + +/* ===== SIGNAL ICON ===== */ +.signal-icon { + display: flex; + align-items: flex-end; + gap: 4px; + width: 34px; + height: 34px; + flex-shrink: 0; +} + +.sig-bar { + flex: 1; + border-radius: 2px; + min-width: 5px; + border: 1.5px solid #00ff88; + background-color: transparent; + transition: background-color 0.3s, border-color 0.3s; +} + +.sig-bar-1 { height: 25%; } +.sig-bar-2 { height: 50%; } +.sig-bar-3 { height: 75%; } +.sig-bar-4 { height: 100%; } + +/* Активные — зелёная заливка */ +.sig-bar.active-1, +.sig-bar.active-2, +.sig-bar.active-3, +.sig-bar.active-4 { + background-color: #00ff88; + border-color: #00ff88; +} + +/* Неактивные — прозрачные, только контур */ +.sig-bar.dim { + background-color: transparent; + border-color: #1a3a1a; +} + +#last-byte { + font-size: 18px; + font-weight: bold; + color: #00ff88; +} \ No newline at end of file diff --git a/cmd/server/web/dashboard.html b/cmd/server/web/dashboard.html index 7c361f7..e1affb7 100644 --- a/cmd/server/web/dashboard.html +++ b/cmd/server/web/dashboard.html @@ -21,19 +21,21 @@
-
-

ПОСЛЕДНИЙ СИГНАЛ

-
--
-
-
-

УРОВНИ КАНАЛОВ

-
Канал 1
-
-
+
Канал 1 — 0
+
+
+
+
+
@@ -53,8 +55,10 @@
-

ПОТОК ДАННЫХ (последние 32)

-
+

▶ ПРИНЯТЫЕ ДАННЫЕ

+
+
+
diff --git a/cmd/server/web/js/app.js b/cmd/server/web/js/app.js index c82f79c..41fa28b 100644 --- a/cmd/server/web/js/app.js +++ b/cmd/server/web/js/app.js @@ -1,19 +1,14 @@ -// ===== BIT RENDER ===== -function renderBits(byte) { - const bits = document.getElementById("bits"); - bits.innerHTML = ""; +// ===== ACCORDION ===== +const historyHeader = document.getElementById("history-header"); +const historyBody = document.getElementById("history-body"); +let accordionOpen = false; +historyBody.classList.add("collapsed"); // изначально свёрнут - byte = Number(byte || 0); - - for (let i = 7; i >= 0; i--) { - const v = (byte >> i) & 1; - - const d = document.createElement("div"); - d.className = "bit" + (v ? " on" : ""); - d.textContent = v; - bits.appendChild(d); - } -} +historyHeader.addEventListener("click", () => { + accordionOpen = !accordionOpen; + historyHeader.textContent = (accordionOpen ? "▼" : "▶") + " ПРИНЯТЫЕ ДАННЫЕ"; + historyBody.classList.toggle("collapsed", !accordionOpen); +}); // ===== PROGRESS BAR ===== function setBar(id, value) { @@ -21,6 +16,31 @@ function setBar(id, value) { document.getElementById(id).style.width = value + "%"; } +// ===== SIGNAL ICON ===== +function setSignal(percent) { + const bars = document.querySelectorAll(".sig-bar"); + bars.forEach(b => { + b.classList.remove("active-1", "active-2", "active-3", "active-4"); + b.classList.add("dim"); + }); + + if (percent > 75) { + bars[0].classList.add("active-1"); bars[0].classList.remove("dim"); + bars[1].classList.add("active-2"); bars[1].classList.remove("dim"); + bars[2].classList.add("active-3"); bars[2].classList.remove("dim"); + bars[3].classList.add("active-4"); bars[3].classList.remove("dim"); + } else if (percent > 50) { + bars[0].classList.add("active-1"); bars[0].classList.remove("dim"); + bars[1].classList.add("active-2"); bars[1].classList.remove("dim"); + bars[2].classList.add("active-3"); bars[2].classList.remove("dim"); + } else if (percent > 25) { + bars[0].classList.add("active-1"); bars[0].classList.remove("dim"); + bars[1].classList.add("active-2"); bars[1].classList.remove("dim"); + } else if (percent > 0) { + bars[0].classList.add("active-1"); bars[0].classList.remove("dim"); + } +} + // ===== SMOOTHING ===== let lastValue = 0; @@ -60,12 +80,6 @@ async function update() { document.getElementById("meta").textContent = "аптайм: " + uptime + "s | буфер: " + filled; - // ===== LATEST ===== - const latest = Number(h.latest || 0); - document.getElementById("latest").textContent = latest; - - renderBits(latest); - // ===== HISTORY ===== const arr = Array.isArray(hist.bytes) ? hist.bytes : []; @@ -89,6 +103,8 @@ async function update() { // ===== ONLY CHANNEL 1 ===== setBar("bar1", smooth); + document.getElementById("last-byte").textContent = filtered; + setSignal(smooth); } catch (e) { console.error("UPDATE ERROR:", e); @@ -96,6 +112,5 @@ async function update() { } } -// быстрее и плавнее setInterval(update, 500); -update(); +update(); \ No newline at end of file