From 1083d0bee1070ec65713836d8fe7d01ce8085d57 Mon Sep 17 00:00:00 2001 From: dongjin kim Date: Wed, 12 Nov 2025 16:01:16 +0900 Subject: [PATCH] Change AI Models list. --- public/app.js | 140 +++++++++++++++++++++++------------------- public/dashboard.html | 101 ++++++------------------------ public/style.css | 42 ++++++++++--- server.js | 13 ++-- 4 files changed, 137 insertions(+), 159 deletions(-) diff --git a/public/app.js b/public/app.js index d786ac7..a01a49f 100644 --- a/public/app.js +++ b/public/app.js @@ -36,75 +36,86 @@ document.addEventListener('DOMContentLoaded', () => { }); } - // ========== AI 모델 업로드 로직 시작 ========== + // ========== [수정됨] AI 모델 업로드 로직 시작 ========== if (contentModels) { - const modelTable = contentModels.querySelector('.model-table'); - - if (modelTable) { - modelTable.addEventListener('click', (event) => { - // '시작'(업로드) 버튼이 클릭되었는지 확인 - if (event.target.classList.contains('btn-action')) { - event.preventDefault(); // 기본 동작 방지 - - const startButton = event.target; - // 클릭된 버튼이 속한 테이블 행(tr)을 찾음 - const row = startButton.closest('tr'); - - // 해당 행에서 파일 입력(input) 요소를 찾음 - const fileInput = row.querySelector('.hidden-file-input'); - // 해당 행의 모델 번호와 역할을 가져옴 - const modelId = row.querySelector('td:first-child').textContent; - const modelRole = row.querySelector('td:nth-child(2)').textContent; - - // 파일이 선택되었는지 확인 - if (fileInput.files.length === 0) { - alert('먼저 .aiwbin 파일을 선택해주세요.'); - return; + // 전역 업로드 관련 요소 가져오기 + const globalFileInput = document.getElementById('global-file-input'); + const fileNameDisplay = document.getElementById('file-name-display'); + const globalUploadButton = document.getElementById('global-upload-button'); + + // '찾아보기'로 파일 선택 시 + if (globalFileInput && fileNameDisplay) { + globalFileInput.addEventListener('change', () => { + if (globalFileInput.files.length > 0) { + const file = globalFileInput.files[0]; + + // 파일 확장자 확인 + if (!file.name.endsWith('.aiwbin')) { + alert('잘못된 파일 형식입니다. .aiwbin 파일만 선택할 수 있습니다.'); + globalFileInput.value = ''; // 파일 선택 초기화 + fileNameDisplay.textContent = '선택된 파일 없음'; + } else { + // 파일명 표시 + fileNameDisplay.textContent = file.name; } + } else { + fileNameDisplay.textContent = '선택된 파일 없음'; + } + }); + } - const file = fileInput.files[0]; + // '업로드' 버튼 클릭 시 + if (globalUploadButton && globalFileInput) { + globalUploadButton.addEventListener('click', () => { + // 파일이 선택되었는지 확인 + if (globalFileInput.files.length === 0) { + alert('먼저 .aiwbin 파일을 선택해주세요.'); + return; + } - // 파일 확장자 확인 (클라이언트 측) - if (!file.name.endsWith('.aiwbin')) { - alert('잘못된 파일 형식입니다. .aiwbin 파일만 업로드할 수 있습니다.'); - fileInput.value = ''; // 파일 선택 초기화 - return; - } + const file = globalFileInput.files[0]; - // FormData 객체 생성 - const formData = new FormData(); - formData.append('modelFile', file); // 'modelFile'은 server.js와 일치해야 함 - formData.append('modelId', modelId); - formData.append('modelRole', modelRole); - - // 업로드 중 버튼 비활성화 - startButton.disabled = true; - startButton.textContent = '업로드 중...'; - - // Fetch API를 사용하여 파일 업로드 - fetch('/upload-model', { - method: 'POST', - body: formData - }) - .then(response => response.json()) - .then(data => { - if (data.status === 'success') { - alert(`업로드 성공!\n모델: ${modelRole}\n파일: ${file.name}`); - fileInput.value = ''; // 파일 선택 초기화 - } else { - alert(`업로드 실패: ${data.message}`); - } - }) - .catch(error => { - console.error('Upload error:', error); - alert('업로드 중 오류가 발생했습니다.'); - }) - .finally(() => { - // 버튼 다시 활성화 - startButton.disabled = false; - startButton.textContent = '시작'; - }); + // (이중 확인) 파일 확장자 확인 + if (!file.name.endsWith('.aiwbin')) { + alert('잘못된 파일 형식입니다. .aiwbin 파일만 업로드할 수 있습니다.'); + globalFileInput.value = ''; + fileNameDisplay.textContent = '선택된 파일 없음'; + return; } + + // FormData 객체 생성 + const formData = new FormData(); + formData.append('modelFile', file); // 'modelFile'은 server.js와 일치해야 함 + // [제거됨] modelId, modelRole 전송 로직 + + // 업로드 중 버튼 비활성화 + globalUploadButton.disabled = true; + globalUploadButton.textContent = '업로드 중...'; + + // Fetch API를 사용하여 파일 업로드 + fetch('/upload-model', { + method: 'POST', + body: formData + }) + .then(response => response.json()) + .then(data => { + if (data.status === 'success') { + alert(`업로드 성공!\n파일: ${file.name}`); + globalFileInput.value = ''; // 파일 선택 초기화 + fileNameDisplay.textContent = '선택된 파일 없음'; + } else { + alert(`업로드 실패: ${data.message}`); + } + }) + .catch(error => { + console.error('Upload error:', error); + alert('업로드 중 오류가 발생했습니다.'); + }) + .finally(() => { + // 버튼 다시 활성화 + globalUploadButton.disabled = false; + globalUploadButton.textContent = '업로드'; + }); }); } } @@ -317,4 +328,5 @@ document.addEventListener('DOMContentLoaded', () => { } // if (요소 확인) 끝 // ========== video-test.html 스크립트 추가 끝 ========== -}); \ No newline at end of file +}); +// \ No newline at end of file diff --git a/public/dashboard.html b/public/dashboard.html index c299fb8..d3aa821 100644 --- a/public/dashboard.html +++ b/public/dashboard.html @@ -67,121 +67,57 @@
- + + + + 선택된 파일 없음 + +
- - - + - - - - - - + + - - - - - - - - - - - + - + - - - + - + - - - - - - - - - - - + - - - - - + + + @@ -193,4 +129,5 @@ - \ No newline at end of file + + \ No newline at end of file diff --git a/public/style.css b/public/style.css index 2ff9f04..e18b991 100644 --- a/public/style.css +++ b/public/style.css @@ -278,12 +278,39 @@ main { } /* 2-2. AI Models 탭 (PDF 3페이지) */ -/* ... (기존 AI Models 탭 스타일 동일) ... */ + +/* [수정됨] .toolbar 스타일 */ .toolbar { + /* [수정] flexbox로 변경 */ + display: flex; + justify-content: flex-end; /* 기존 text-align: right와 동일한 효과 */ + align-items: center; + gap: 10px; /* 요소 간 간격 */ margin-bottom: 1rem; - text-align: right; + /* text-align: right; -- 제거 */ +} + +/* [추가됨] 새로고침 버튼을 맨 오른쪽으로 밀기 */ +.toolbar .refresh-button { + margin-left: auto; } +/* [추가됨] 파일명 표시 레이블 */ +#file-name-display { + font-size: 0.9rem; + color: #555; + background-color: #f9f9f9; + border: 1px solid #ddd; + padding: 5px 10px; + border-radius: 4px; + min-width: 350px; + text-align: left; + font-style: italic; + /* 버튼과 높이를 맞추기 위한 line-height */ + line-height: 1.4; +} + + .hidden-file-input { display: none; } @@ -306,13 +333,13 @@ main { background-color: #f9f9f9; } +/* [수정됨] nth-child 선택자 수정 (컬럼 1, 4 중앙 정렬) */ .model-table td:nth-child(1), -.model-table td:nth-child(3) { +.model-table td:nth-child(4) { text-align: center; } -.model-table td:nth-child(4), -.model-table td:nth-child(5), -.model-table td:nth-child(6) { +/* [수정됨] nth-child 선택자 수정 (컬럼 5 '삭제' 중앙 정렬) */ +.model-table td:nth-child(5) { text-align: center; } @@ -348,4 +375,5 @@ main { position: absolute; border: 2px solid red; /* 요청된 빨간색 테두리 */ box-sizing: border-box; /* 테두리 포함 크기 계산 */ -} \ No newline at end of file +} +/**/ \ No newline at end of file diff --git a/server.js b/server.js index dedd5cc..2039db3 100644 --- a/server.js +++ b/server.js @@ -123,7 +123,7 @@ app.post('/set-model', (req, res) => { // --- 스크립트 실행 끝 --- }); -// [추가] 7. 모델 파일 업로드 엔드포인트 +// [수정됨] 7. 모델 파일 업로드 엔드포인트 // 'modelFile'은 app.js의 FormData.append('modelFile', ...)와 일치해야 합니다. app.post('/upload-model', (req, res) => { @@ -146,12 +146,12 @@ app.post('/upload-model', (req, res) => { return res.status(400).json({ status: 'error', message: '업로드할 파일을 찾을 수 없습니다.' }); } - // 폼 데이터로 함께 전송된 모델 정보 (modelId, modelRole) - const modelId = req.body.modelId; - const modelRole = req.body.modelRole; + // [제거됨] 폼 데이터로 함께 전송된 모델 정보 (modelId, modelRole) + // const modelId = req.body.modelId; + // const modelRole = req.body.modelRole; console.log(`[서버] 파일 업로드 성공:`); - console.log(` - 모델 ID: ${modelId} (${modelRole})`); + // [제거됨] console.log(` - 모델 ID: ${modelId} (${modelRole})`); console.log(` - 원본 파일명: ${req.file.originalname}`); console.log(` - 저장 경로: ${req.file.path}`); @@ -168,4 +168,5 @@ app.post('/upload-model', (req, res) => { // 8. (번호 수정) 설정한 3000번 포트에서 서버가 요청을 기다리도록 실행합니다. app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); -}); \ No newline at end of file +}); + \ No newline at end of file
번호 Al Model 역할현재 버전변경업데이트파일명 현재 버전 삭제
1객체 탐지/분류0.1 - - - - - 객체 탐지/ 분류- v1.0
2사람 얼굴/인상착의 인식0.1 - - - - - - -
3 이상행동(쓰러짐, 폭행) 감지0.1 - - - - - - v1.0
43 집합 군중 위험 인식0.1 - - - - - - v1.0
54 화재(불꽃, 연기) 감지 - - - - - - -
6차량 번호판/차종 인식 - - - - - - -
7영상내 얼굴 비식별화 - - - - - 5차량 번호판/ 차종 인식- -