From e7ad1f3b55c5c1b0df691bd3185ed02f0afe2b14 Mon Sep 17 00:00:00 2001 From: dongjin kim Date: Thu, 4 Dec 2025 16:38:30 +0900 Subject: [PATCH] =?UTF-8?q?log=ED=83=AD=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/app.js | 68 +++++++++++++++++++++++++++++++++++-------- public/dashboard.html | 9 +++--- public/style.css | 24 ++++++++++++--- 3 files changed, 80 insertions(+), 21 deletions(-) diff --git a/public/app.js b/public/app.js index 3572f51..9c2d75c 100644 --- a/public/app.js +++ b/public/app.js @@ -15,7 +15,7 @@ document.addEventListener('DOMContentLoaded', () => { } // ================================================= - // 1. 탭 전환 로직 + // 1. 탭 전환 로직 (상단 메인 탭) // ================================================= const tabVideo = document.getElementById('tab-video'); const tabModels = document.getElementById('tab-models'); @@ -41,6 +41,54 @@ document.addEventListener('DOMContentLoaded', () => { }); } + // ================================================= + // [신규] 오른쪽 사이드바 (Summary / Log) 탭 로직 + // ================================================= + const btnSummary = document.getElementById('btn-summary'); + const btnLog = document.getElementById('btn-log'); + const summaryListEl = document.getElementById('summary-list'); + const logListEl = document.getElementById('log-list'); + + if (btnSummary && btnLog) { + btnSummary.addEventListener('click', () => { + btnSummary.classList.add('active'); + btnLog.classList.remove('active'); + if(summaryListEl) summaryListEl.classList.remove('hidden'); + if(logListEl) logListEl.classList.add('hidden'); + }); + + btnLog.addEventListener('click', () => { + btnLog.classList.add('active'); + btnSummary.classList.remove('active'); + if(summaryListEl) summaryListEl.classList.add('hidden'); + if(logListEl) logListEl.classList.remove('hidden'); + }); + } + + // 로그 업데이트 함수 (최신 50개 유지) + function updateLogPanel(textData) { + if (!logListEl) return; + + const now = new Date(); + const timeStr = now.toTimeString().split(' ')[0]; // HH:MM:SS + + const row = document.createElement('div'); + row.className = 'log-entry'; + + // JSON 문자열이 너무 길 수 있으므로 적절히 자르거나 그대로 표시 + // 가독성을 위해 시간 + 데이터 표시 + row.innerHTML = `[${timeStr}] ${textData}`; + + // 최신 로그가 위로 오게 하거나 아래로 오게 할 수 있음 (여기선 위로 쌓음) + logListEl.prepend(row); + + // 메모리 관리를 위해 50개 넘어가면 삭제 + if (logListEl.children.length > 50) { + logListEl.removeChild(logListEl.lastChild); + } + } + + // ================================================= // [신규] Mission UI 로직 // ================================================= @@ -81,7 +129,7 @@ document.addEventListener('DOMContentLoaded', () => { .catch(e => console.error(e)); } -const filterBar = document.getElementById('filter-bar'); + const filterBar = document.getElementById('filter-bar'); function updateFilterBar(modelCode) { if(!filterBar) return; @@ -146,14 +194,11 @@ const filterBar = document.getElementById('filter-bar'); zoomInput.id = 'zoom-toggle'; zoomInput.checked = false; // 기본값: 선택 안 됨 - // 줌 기능 이벤트 리스너 (필요 시 로직 구현) zoomInput.addEventListener('change', (e) => { if(e.target.checked) { console.log("Zoom In Activated"); - // 여기에 줌 확대 로직 추가 } else { console.log("Zoom In Deactivated"); - // 여기에 줌 해제 로직 추가 } }); @@ -162,13 +207,11 @@ const filterBar = document.getElementById('filter-bar'); filterBar.appendChild(zoomLabel); } - // 초기 필터 상태 반영 updateActiveFilters(classInputs); } function updateActiveFilters(classInputs) { activeClassFilters.clear(); - // 체크된 항목들만 Set에 추가 classInputs.forEach(inp => { if(inp.checked) activeClassFilters.add(inp.dataset.cls); }); @@ -200,7 +243,7 @@ const filterBar = document.getElementById('filter-bar'); const fpsDisplayEl = document.getElementById("fps-display"); const resolutionEl = document.getElementById("resolution-display"); const connMsgEl = document.getElementById("connection-msg"); - const summaryListEl = document.getElementById("summary-list"); + // summaryListEl은 상단에서 정의됨 let ctx = null; if (canvasEl) ctx = canvasEl.getContext('2d'); @@ -222,6 +265,9 @@ const filterBar = document.getElementById('filter-bar'); ws.onmessage = (event) => { const data = event.data; if (typeof data === "string") { + // [Log 기능 연결] 문자열(JSON) 데이터 수신 시 로그 패널에 출력 + updateLogPanel(data); + try { const meta = JSON.parse(data); if (meta.type === "frame") { @@ -274,7 +320,7 @@ const filterBar = document.getElementById('filter-bar'); displayClassName = LABEL_MAP[tagId].classes[clsId]; } - // [수정] 필터링 로직 강화: Set에 없으면 절대 그리지 않음 (All 체크 로직과 연동) + // 필터링 if (!activeClassFilters.has(displayClassName)) { return; } @@ -499,6 +545,4 @@ const filterBar = document.getElementById('filter-bar'); } loadModelList(); -}); - -//2025-12-04 15:41 \ No newline at end of file +}); \ No newline at end of file diff --git a/public/dashboard.html b/public/dashboard.html index 23ff45d..3697658 100644 --- a/public/dashboard.html +++ b/public/dashboard.html @@ -96,8 +96,8 @@ @@ -214,6 +215,4 @@ - - - \ No newline at end of file + \ No newline at end of file diff --git a/public/style.css b/public/style.css index 6998dc0..30431cc 100644 --- a/public/style.css +++ b/public/style.css @@ -252,7 +252,7 @@ main { /* 5-3. 우측 사이드바 (정보 패널) */ .mission-right { - width: 200px; background-color: #444; + width: 300px; background-color: #444; border-left: 1px solid #666; display: flex; flex-direction: column; } @@ -274,6 +274,24 @@ main { .summary-row .label { color: #fff; } .summary-row .count { color: #fff; font-weight: bold; } +/* [신규] Log Content 스타일 */ +.log-content { + padding: 10px; + overflow-y: auto; + flex-grow: 1; + font-family: 'Consolas', 'Monaco', monospace; /* 코드 폰트 */ + font-size: 12px; + background-color: #222; /* 로그 배경은 더 어둡게 */ +} +.log-entry { + margin-bottom: 5px; + border-bottom: 1px solid #333; + word-break: break-all; /* 긴 JSON 줄바꿈 */ + color: #ccc; +} +.log-time { color: #888; font-weight: bold; margin-right: 5px; } +.log-msg { color: #0f0; } /* 메시지는 녹색 터미널 느낌 */ + /* ========================================================== */ /* 7. 설정 탭 - AI 모델 & 관심 인물 관리 (Settings) */ /* ========================================================== */ @@ -339,6 +357,4 @@ main { /* 이미지 뷰어 모달 */ .modal-image { margin: auto; display: block; max-width: 90%; max-height: 90%; border-radius: 5px; animation-name: zoom; animation-duration: 0.4s; } @keyframes zoom { from {transform:scale(0)} to {transform:scale(1)} } -.close-viewer { position: absolute; top: 20px; right: 35px; color: #f1f1f1; font-size: 40px; font-weight: bold; transition: 0.3s; cursor: pointer; z-index: 2001; } - -/*//2025-12-04 15:41*/ \ No newline at end of file +.close-viewer { position: absolute; top: 20px; right: 35px; color: #f1f1f1; font-size: 40px; font-weight: bold; transition: 0.3s; cursor: pointer; z-index: 2001; } \ No newline at end of file