change to web visualizer

This commit is contained in:
admin committed 2026-09-11 20:14:37 +07:00
1 parent 87be72b52b
commit 417ced90fa
9 files changed
+2580 -680

No files matched your search

+197
View File
@@ -0,0 +1,197 @@
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title data-i18n="page_title">ESP32 LD2453 — Radar Web Visualizer</title>
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Ccircle cx='50' cy='70' r='8' fill='%23f38ba8'/%3E%3Cpath d='M20 70 A30 30 0 0 1 80 70' fill='none' stroke='%2389b4fa' stroke-width='3'/%3E%3Ccircle cx='50' cy='70' r='22' fill='none' stroke='%2389b4fa' stroke-width='1.5' opacity='0.4'/%3E%3C/svg%3E" />
<link rel="stylesheet" href="/static/style.css" />
</head>
<body data-theme="dark" data-lang="vi">
<!-- ============================================================= -->
<!-- HEADER -->
<!-- ============================================================= -->
<header class="app-header">
<div class="header-left">
<div class="logo">
<svg viewBox="0 0 100 100" width="34" height="34" aria-hidden="true">
<circle cx="50" cy="70" r="9" class="logo-radar-dot" />
<path d="M20 70 A30 30 0 0 1 80 70" class="logo-arc" />
<circle cx="50" cy="70" r="22" class="logo-ring" />
</svg>
<div class="logo-text">
<h1 data-i18n="app_title">Radar LD2453</h1>
<span class="subtitle" data-i18n="app_subtitle">ESP32-S3 — Zone Presence Detection</span>
</div>
</div>
</div>
<div class="header-right">
<!-- Connection status -->
<div class="status-chip" id="statusEsp32">
<span class="status-dot status-warn"></span>
<span data-i18n="esp32_connecting">ESP32: Đang kết nối…</span>
</div>
<div class="status-chip" id="statusWs">
<span class="status-dot status-warn"></span>
<span data-i18n="ws_connecting">WS: Đang kết nối…</span>
</div>
<!-- Theme toggle -->
<button class="icon-btn" id="btnTheme" title="Toggle theme" data-i18n-title="toggle_theme">
<svg class="icon-sun" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
<circle cx="12" cy="12" r="4" />
<path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M4.93 19.07l1.41-1.41M17.66 6.34l1.41-1.41"/>
</svg>
<svg class="icon-moon" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
</button>
<!-- Language toggle -->
<button class="lang-btn" id="btnLang" title="Change language">
<span class="lang-vi">VI</span>
<span class="lang-sep">/</span>
<span class="lang-en">EN</span>
</button>
</div>
</header>
<!-- ============================================================= -->
<!-- MAIN LAYOUT -->
<!-- ============================================================= -->
<main class="app-main">
<!-- ======= LEFT / TOP: RADAR CANVAS ======= -->
<section class="panel panel-canvas">
<div class="panel-header">
<h2 data-i18n="radar_view">Radar View</h2>
<div class="panel-tools">
<label class="chip-toggle">
<input type="checkbox" id="chkSweep" checked />
<span data-i18n="sweep_effect">Hiệu ứng quét</span>
</label>
<label class="chip-toggle">
<input type="checkbox" id="chkTrails" checked />
<span data-i18n="target_trails">Đường dẫn target</span>
</label>
<label class="chip-toggle">
<input type="checkbox" id="chkLabels" checked />
<span data-i18n="show_labels">Hiển thị label</span>
</label>
</div>
</div>
<div class="canvas-wrap">
<canvas id="radarCanvas"></canvas>
<!-- Legend overlay -->
<div class="legend">
<div class="legend-title" data-i18n="legend">Chú thích</div>
<div class="legend-item">
<span class="swatch swatch-t1"></span>
<span data-i18n="target_1">Target 1 (Slot 1)</span>
</div>
<div class="legend-item">
<span class="swatch swatch-t2"></span>
<span data-i18n="target_2">Target 2 (Slot 2)</span>
</div>
<div class="legend-item">
<span class="swatch swatch-t3"></span>
<span data-i18n="target_3">Target 3 (Slot 3)</span>
</div>
<div class="legend-divider"></div>
<div class="legend-item">
<span class="swatch-zone z1"></span>
<span data-i18n="zone_1">Zone 1</span>
</div>
<div class="legend-item">
<span class="swatch-zone z2"></span>
<span data-i18n="zone_2">Zone 2</span>
</div>
<div class="legend-item">
<span class="swatch-zone z3"></span>
<span data-i18n="zone_3">Zone 3</span>
</div>
</div>
<!-- Node info overlay -->
<div class="node-info" id="nodeInfo">
<span class="node-id" id="nodeId">RADAR_A</span>
<span class="sep">|</span>
<span data-i18n="seq">Seq</span>: <span id="seqNum">0</span>
<span class="sep">|</span>
<span data-i18n="targets">Targets</span>: <span id="tgtCount">0/3</span>
</div>
</div>
</section>
<!-- ======= RIGHT / BOTTOM: INFO PANELS ======= -->
<section class="panel panel-side">
<!-- Stats card -->
<div class="card stats-card">
<h3 data-i18n="statistics">Thống kê</h3>
<div class="stats-grid">
<div class="stat">
<div class="stat-label" data-i18n="frames_received">Frames nhận</div>
<div class="stat-value" id="statFrames">0</div>
</div>
<div class="stat">
<div class="stat-label" data-i18n="last_update">Cập nhật cách đây</div>
<div class="stat-value"><span id="statLastUpdate">—</span><small>s</small></div>
</div>
<div class="stat">
<div class="stat-label" data-i18n="valid_targets">Target hợp lệ</div>
<div class="stat-value" id="statValid">0 / 3</div>
</div>
<div class="stat">
<div class="stat-label" data-i18n="zones_occupied">Vùng có người</div>
<div class="stat-value" id="statZones">0 / 3</div>
</div>
</div>
</div>
<!-- Targets list -->
<div class="card targets-card">
<h3 data-i18n="targets_detail">Chi tiết Target</h3>
<div class="targets-list" id="targetsList">
<!-- Populated by JS -->
</div>
</div>
<!-- Zones list + editor -->
<div class="card zones-card">
<div class="card-header-row">
<h3 data-i18n="zones">Zones</h3>
<button class="btn-link" id="btnEditZones" data-i18n="edit_zones">Sửa zones</button>
</div>
<div class="zones-list" id="zonesList"></div>
<!-- Zone editor (hidden by default) -->
<form class="zone-editor" id="zoneEditor" hidden>
<div class="editor-title" data-i18n="zone_editor_title">Chỉnh sửa tọa độ zone (mm)</div>
<div class="editor-grid" id="editorGrid"></div>
<div class="editor-actions">
<button type="button" class="btn btn-ghost" id="btnCancelZones" data-i18n="cancel">Hủy</button>
<button type="button" class="btn btn-ghost" id="btnResetZones" data-i18n="reset_default">Mặc định</button>
<button type="submit" class="btn btn-primary" data-i18n="save_and_apply">Lưu & Áp dụng</button>
</div>
</form>
</div>
</section>
</main>
<!-- ============================================================= -->
<!-- TOAST -->
<!-- ============================================================= -->
<div id="toastContainer" class="toast-container"></div>
<!-- ============================================================= -->
<!-- SCRIPTS -->
<!-- ============================================================= -->
<script src="/static/app.js"></script>
</body>
</html>