125 lines
7.0 KiB
HTML
125 lines
7.0 KiB
HTML
<!doctype html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta http-equiv="Content-Security-Policy"
|
||
content="default-src 'self'; connect-src ws://127.0.0.1:* ws://localhost:*; script-src 'self'; style-src 'self'; img-src 'self' data:; object-src 'none'; base-uri 'none'">
|
||
<title>Renderive Web Receiver</title>
|
||
<link rel="stylesheet" href="styles.css">
|
||
</head>
|
||
<body>
|
||
<div class="app-shell">
|
||
<header class="topbar">
|
||
<div class="brand-block">
|
||
<div class="brand-mark" aria-hidden="true"><span></span><span></span><span></span></div>
|
||
<div>
|
||
<div class="brand-name">RENDERIVE</div>
|
||
<div class="brand-caption">WEB RECEIVER / KERNEL LINK</div>
|
||
</div>
|
||
</div>
|
||
<div class="transport-strip" aria-label="传输架构">
|
||
<span>CORE2</span><i></i><span>KERNEL</span><i></i><span>WEBSOCKET</span><i></i><span>RGBA</span>
|
||
</div>
|
||
<div class="connection-summary">
|
||
<span class="connection-dot" id="connection-dot"></span>
|
||
<div>
|
||
<strong id="connection-label">正在连接</strong>
|
||
<small id="connection-endpoint">ws://127.0.0.1:8848/renderive</small>
|
||
</div>
|
||
<button class="icon-button" id="reconnect-button" type="button" title="重新连接" aria-label="重新连接" data-testid="reconnect">↻</button>
|
||
</div>
|
||
</header>
|
||
|
||
<main class="workspace">
|
||
<aside class="control-deck" aria-label="接收机控制台">
|
||
<section class="frequency-card">
|
||
<div class="section-kicker">CENTER FREQUENCY</div>
|
||
<div class="frequency-readout">
|
||
<span id="frequency-value" data-value="102.5">102.500</span><em>MHz</em>
|
||
</div>
|
||
<div class="frequency-stepper">
|
||
<button type="button" id="tune-down" data-testid="tune-down" aria-label="中心频率降低 0.1 MHz">−</button>
|
||
<span>STEP <strong>100 kHz</strong></span>
|
||
<button type="button" id="tune-up" data-testid="tune-up" aria-label="中心频率提高 0.1 MHz">+</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="control-section">
|
||
<div class="section-heading"><span>DEMODULATION</span><small id="mode-label">FM WIDE</small></div>
|
||
<div class="mode-grid" role="group" aria-label="解调模式">
|
||
<button type="button" class="mode-button" data-mode="AM" data-testid="mode-am">AM</button>
|
||
<button type="button" class="mode-button active" data-mode="FM" data-testid="mode-fm">FM</button>
|
||
<button type="button" class="mode-button" data-mode="USB" data-testid="mode-usb">USB</button>
|
||
<button type="button" class="mode-button" data-mode="LSB" data-testid="mode-lsb">LSB</button>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="control-section range-section">
|
||
<div class="section-heading"><label for="bandwidth">BANDWIDTH</label><output id="bandwidth-value">1200 kHz</output></div>
|
||
<input id="bandwidth" data-testid="bandwidth" type="range" min="200" max="2400" step="100" value="1200">
|
||
<div class="range-scale"><span>200 k</span><span>1.2 M</span><span>2.4 M</span></div>
|
||
</section>
|
||
|
||
<section class="control-section range-section">
|
||
<div class="section-heading"><label for="gain">RF GAIN</label><output id="gain-value">+8 dB</output></div>
|
||
<input id="gain" data-testid="gain" type="range" min="-10" max="30" step="1" value="8">
|
||
<div class="range-scale"><span>−10</span><span>+10</span><span>+30</span></div>
|
||
</section>
|
||
|
||
<section class="control-section switch-list" aria-label="显示选项">
|
||
<button type="button" class="switch-row" id="max-hold" aria-pressed="false" data-testid="max-hold">
|
||
<span><b>MAX HOLD</b><small>峰值轨迹保持</small></span><i></i>
|
||
</button>
|
||
<button type="button" class="switch-row active" id="smoothing" aria-pressed="true" data-testid="smoothing">
|
||
<span><b>SMOOTHING</b><small>曲线与热图插值</small></span><i></i>
|
||
</button>
|
||
</section>
|
||
|
||
<div class="deck-actions">
|
||
<button type="button" class="secondary-action" id="clear-selection" data-testid="clear-selection">清除框选</button>
|
||
<button type="button" class="live-action" id="pause-button" aria-pressed="false" data-testid="pause">
|
||
<span class="live-pulse"></span><span id="pause-label">LIVE</span>
|
||
</button>
|
||
</div>
|
||
</aside>
|
||
|
||
<section class="receiver-panel">
|
||
<header class="receiver-header">
|
||
<div>
|
||
<div class="section-kicker">REAL-TIME PIXEL STREAM</div>
|
||
<h1>宽带频谱监视器</h1>
|
||
<div class="interaction-hint">滚轮缩放 · 拖动坐标轴 · 在频谱区拖拽框选</div>
|
||
</div>
|
||
<div class="metric-rack" aria-label="流状态">
|
||
<div><small>FRAME RATE</small><strong><span id="fps-value">0.0</span> fps</strong></div>
|
||
<div><small>FRAME RTT</small><strong><span id="latency-value">—</span> ms</strong></div>
|
||
<div><small>RESOLUTION</small><strong id="resolution-value">— × —</strong></div>
|
||
<div><small>EFFECTIVE PIXEL RATE</small><strong><span id="throughput-value">0.0</span> Mb/s</strong></div>
|
||
</div>
|
||
</header>
|
||
|
||
<div class="canvas-stage" id="canvas-stage">
|
||
<canvas id="render-canvas" tabindex="0" aria-label="Renderive 实时频谱与瀑布像素画布"></canvas>
|
||
<div class="stage-label spectrum-label"><span></span>SPECTRUM / dBm</div>
|
||
<div class="stage-label waterfall-label"><span></span>WATERFALL / UTC</div>
|
||
<div class="stream-overlay" id="stream-overlay">
|
||
<div class="loader-ring"></div>
|
||
<strong id="overlay-title">等待像素流</strong>
|
||
<span id="overlay-detail">请先启动 Renderive_Web_Server</span>
|
||
</div>
|
||
</div>
|
||
|
||
<footer class="receiver-footer">
|
||
<div><span class="footer-led"></span><strong>WS ONLY</strong><small>事件 ↑ / 像素 ↓</small></div>
|
||
<div><strong id="frame-counter">0</strong><small>PIXEL FRAMES</small></div>
|
||
<div class="signal-meter" aria-label="信号活动"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div>
|
||
<div class="footer-note">NO HTTP DATA PATH</div>
|
||
</footer>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
<script src="app.js"></script>
|
||
</body>
|
||
</html>
|