const PageRecord = { _el: null, init() { this._el = document.getElementById('page-record'); }, async render() { this._el.innerHTML = this._template(); this._bindEvents(); this._loadRecordings(); }, async _loadRecordings() { try { const res = await fetch('/api/recordings'); const list = await res.json(); const el = document.getElementById('rec-file-list'); if (!el) return; if (!list.length) { el.innerHTML = '
暂无录制文件
'; return; } el.innerHTML = list.map(f => { const size = f.size > 1048576 ? (f.size/1048576).toFixed(1)+'MB' : (f.size/1024).toFixed(1)+'KB'; return ''; }).join(''); } catch (e) {} }, _bindEvents() { document.getElementById('btn-rec-start')?.addEventListener('click', async () => { await fetch('/api/record/start', { method: 'POST' }); this._updateRecUI(true); }); document.getElementById('btn-rec-stop')?.addEventListener('click', async () => { await fetch('/api/record/stop', { method: 'POST' }); this._updateRecUI(false); this._loadRecordings(); }); document.getElementById('rec-auto-mode')?.addEventListener('change', async (e) => { await fetch('/api/record/auto', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ enabled: e.target.checked }) }); }); document.getElementById('btn-import-rec')?.addEventListener('click', () => { const input = document.createElement('input'); input.type = 'file'; input.accept = '.tsr'; input.onchange = async (e) => { const file = e.target.files[0]; if (!file) return; const fd = new FormData(); fd.append('file', file); await fetch('/api/recording/import', { method: 'POST', body: fd }); Toast.show('导入成功', 'success'); this._loadRecordings(); }; input.click(); }); document.getElementById('rec-file-list')?.addEventListener('click', async (e) => { const playBtn = e.target.closest('.btn-play-rec'); const delBtn = e.target.closest('.btn-del-rec'); if (playBtn) this._playRecording(playBtn.dataset.file); if (delBtn && confirm('删除?')) { await fetch('/api/recording/' + delBtn.dataset.file + '/delete', { method: 'DELETE' }); this._loadRecordings(); } }); document.getElementById('btn-playback-stop')?.addEventListener('click', async () => { await fetch('/api/playback/stop', { method: 'POST' }); document.getElementById('playback-bar').style.display = 'none'; }); }, _updateRecUI(recording) { document.getElementById('btn-rec-start').style.display = recording ? 'none' : ''; document.getElementById('btn-rec-stop').style.display = recording ? '' : 'none'; document.getElementById('rec-status').textContent = recording ? '录制中...' : '就绪'; }, async _playRecording(filename) { document.getElementById('playback-file').textContent = filename; document.getElementById('playback-bar').style.display = 'flex'; await fetch('/api/playback/start', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filename }) }); Toast.show('回放已开始,打开仪表盘查看数据', 'info'); }, _template() { return '录制原始 UDP 流到 .tsr 文件,回放调试仪表盘
' + '