diff --git a/gateway/html/login.html b/gateway/html/login.html index af399cb..709e503 100644 --- a/gateway/html/login.html +++ b/gateway/html/login.html @@ -161,8 +161,8 @@ // redirect 파라미터가 있으면 해당 URL로, 없으면 포털로 var redirect = new URLSearchParams(location.search).get('redirect'); - // Open redirect 방지: 상대 경로 또는 같은 도메인만 허용 - if (redirect && (redirect.startsWith('/') && !redirect.startsWith('//')) && !redirect.includes('://')) { + // Open redirect 방지: 같은 origin의 상대 경로만 허용 + if (redirect && /^\/[a-zA-Z0-9]/.test(redirect) && !redirect.includes('://') && !redirect.includes('//')) { window.location.href = redirect; } else { window.location.href = '/'; diff --git a/gateway/html/portal.html b/gateway/html/portal.html index 3f54719..cc9286d 100644 --- a/gateway/html/portal.html +++ b/gateway/html/portal.html @@ -221,9 +221,9 @@ ssoCookie.remove('sso_token'); ssoCookie.remove('sso_user'); ssoCookie.remove('sso_refresh_token'); - localStorage.removeItem('sso_token'); - localStorage.removeItem('sso_user'); - localStorage.removeItem('sso_refresh_token'); + ['sso_token','sso_user','sso_refresh_token','token','user','access_token','currentUser','current_user','userInfo','userPageAccess'].forEach(function(k) { + localStorage.removeItem(k); + }); fetch('/auth/logout', { method: 'POST' }).catch(function(){}); location.reload(); } diff --git a/gateway/html/shared/nav-header.js b/gateway/html/shared/nav-header.js index aa71625..cd34e19 100644 --- a/gateway/html/shared/nav-header.js +++ b/gateway/html/shared/nav-header.js @@ -48,9 +48,9 @@ cookieRemove('sso_token'); cookieRemove('sso_user'); cookieRemove('sso_refresh_token'); - localStorage.removeItem('sso_token'); - localStorage.removeItem('sso_user'); - localStorage.removeItem('sso_refresh_token'); + ['sso_token','sso_user','sso_refresh_token','token','user','access_token','currentUser','current_user','userInfo','userPageAccess'].forEach(function(k) { + localStorage.removeItem(k); + }); window.location.href = this.getLoginUrl(); }, diff --git a/system1-factory/fastapi-bridge/static/js/api-config.js b/system1-factory/fastapi-bridge/static/js/api-config.js index 0db469c..3c7df40 100644 --- a/system1-factory/fastapi-bridge/static/js/api-config.js +++ b/system1-factory/fastapi-bridge/static/js/api-config.js @@ -5,7 +5,6 @@ function getApiBaseUrl() { const protocol = window.location.protocol; const port = window.location.port; - console.log('🌐 감지된 환경:', { hostname, protocol, port }); // 🔗 nginx 프록시를 통한 접근 (권장) // nginx가 /api/ 요청을 백엔드로 프록시하므로 포트 없이 접근 @@ -18,12 +17,11 @@ function getApiBaseUrl() { ? `${protocol}//${hostname}:${port}/api` : `${protocol}//${hostname}/api`; - console.log('✅ nginx 프록시 사용:', baseUrl); return baseUrl; } // 🚨 백업: 직접 접근 (nginx 프록시 실패시에만) - console.warn('⚠️ 직접 API 접근 (백업 모드)'); + console.warn(' 직접 API 접근 (백업 모드)'); return `${protocol}//${hostname}:8000/api`; } @@ -64,12 +62,11 @@ export async function apiCall(url, options = {}) { }; try { - console.log(`📡 API 호출: ${url}`); const response = await fetch(url, finalOptions); // 인증 만료 처리 if (response.status === 401) { - console.error('❌ 인증 만료'); + console.error(' 인증 만료'); localStorage.removeItem('sso_token'); alert('인증이 만료되었습니다. 다시 로그인해주세요.'); window.location.href = '/'; @@ -89,11 +86,10 @@ export async function apiCall(url, options = {}) { } const result = await response.json(); - console.log(`✅ API 성공: ${url}`); return result; } catch (error) { - console.error(`❌ API 오류 (${url}):`, error); + console.error(` API 오류 (${url}):`, error); // 네트워크 오류 vs 서버 오류 구분 if (error.name === 'TypeError' && error.message.includes('fetch')) { @@ -105,8 +101,6 @@ export async function apiCall(url, options = {}) { } // 디버깅 정보 -console.log('🔗 API Base URL:', API); -console.log('🌐 Current Location:', { hostname: window.location.hostname, protocol: window.location.protocol, port: window.location.port, @@ -116,21 +110,17 @@ console.log('🌐 Current Location:', { // 🧪 API 연결 테스트 함수 (개발용) export async function testApiConnection() { try { - console.log('🧪 API 연결 테스트 시작...'); const response = await fetch(`${API}/health`, { method: 'GET', headers: { 'Content-Type': 'application/json' } }); if (response.ok) { - console.log('✅ API 연결 성공!'); return true; } else { - console.log('❌ API 연결 실패:', response.status); return false; } } catch (error) { - console.log('❌ API 연결 오류:', error.message); return false; } } diff --git a/system1-factory/fastapi-bridge/static/js/attendance-validation.js b/system1-factory/fastapi-bridge/static/js/attendance-validation.js index a2f47e7..8cc4618 100644 --- a/system1-factory/fastapi-bridge/static/js/attendance-validation.js +++ b/system1-factory/fastapi-bridge/static/js/attendance-validation.js @@ -50,7 +50,6 @@ function getCacheStatus() { */ function clearCache() { dateStatusCache.clear(); - console.log('📦 캐시가 클리어되었습니다.'); } /** @@ -77,7 +76,6 @@ function updatePerformanceUI() { */ function logPerformanceStatus() { const status = getCacheStatus(); - console.log('📊 성능 상태:', status); updatePerformanceUI(); } @@ -118,7 +116,7 @@ function getCurrentUser() { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { return JSON.parse(userInfo); } @@ -391,18 +389,14 @@ async function calculateDateStatus(dateStr) { } try { - console.log(`📊 ${dateStr} 상태 계산 시작 - 순차 호출`); // 1단계: WorkReports 먼저 가져오기 - console.log(`📝 1단계: WorkReports 조회 중...`); const workReports = await fetchWorkReports(dateStr); // 2초 대기 (서버 부하 방지) - console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); await new Promise(resolve => setTimeout(resolve, 2000)); // 2단계: DailyWorkReports 가져오기 - console.log(`📊 2단계: DailyWorkReports 조회 중...`); const dailyReports = await fetchDailyWorkReports(dateStr); let status; @@ -423,7 +417,6 @@ async function calculateDateStatus(dateStr) { // 캐시에 저장 dateStatusCache.set(dateStr, status); - console.log(`✅ ${dateStr} 상태 계산 완료: ${status}`); return status; } catch (error) { console.error('날짜 상태 계산 오류:', error); @@ -564,10 +557,9 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) { }`; } - console.log(`✅ ${dateStr} 상태 로드 완료: ${status}`); } catch (error) { - console.error(`❌ ${dateStr} 상태 로드 실패:`, error); + console.error(` ${dateStr} 상태 로드 실패:`, error); buttonElement.classList.remove('loading-state'); buttonElement.classList.add('error-state'); buttonElement.title = `${dateStr} - 로드 실패: ${error.message}`; @@ -589,18 +581,14 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) { */ async function getWorkersForDate(dateStr) { try { - console.log(`👥 ${dateStr} 작업자 데이터 조합 시작 - 순차 호출`); // 1단계: WorkReports 먼저 가져오기 - console.log(`📝 1단계: WorkReports 조회 중...`); const workReports = await fetchWorkReports(dateStr); // 2초 대기 (서버 부하 방지) - console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); await new Promise(resolve => setTimeout(resolve, 2000)); // 2단계: DailyWorkReports 가져오기 - console.log(`📊 2단계: DailyWorkReports 조회 중...`); const dailyReports = await fetchDailyWorkReports(dateStr); const workerMap = new Map(); @@ -645,7 +633,6 @@ async function getWorkersForDate(dateStr) { validationStatus: getValidationStatus(worker) })); - console.log(`✅ ${dateStr} 작업자 데이터 조합 완료: ${result.length}명`); return result; } catch (error) { @@ -1022,11 +1009,6 @@ async function init() { window.saveEditedWork = saveEditedWork; window.deleteWorker = deleteWorker; - console.log('✅ 근태 검증 관리 시스템 초기화 완료 (API 통합)'); - console.log(`🔗 API 경로: ${API}`); - console.log(`📊 설정: 동시 최대 ${RATE_LIMIT.maxConcurrent}개 요청, ${RATE_LIMIT.delayBetweenRequests}ms 딜레이`); - console.log('🔄 API 호출 방식: 통합 설정 + 순차 호출'); - console.log('🚫 429 에러 방지: 각 날짜당 최소 5초 간격'); } catch (error) { console.error('초기화 오류:', error); diff --git a/system1-factory/fastapi-bridge/static/js/auth-check.js b/system1-factory/fastapi-bridge/static/js/auth-check.js index 5c2e2f5..5759d04 100644 --- a/system1-factory/fastapi-bridge/static/js/auth-check.js +++ b/system1-factory/fastapi-bridge/static/js/auth-check.js @@ -4,7 +4,6 @@ import { isLoggedIn, getUser, clearAuthData } from './auth.js'; // 즉시 실행 함수로 스코프를 보호하고 로직을 실행 (function() { if (!isLoggedIn()) { - console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); clearAuthData(); // 만약을 위해 한번 더 정리 window.location.href = '/login'; return; // 이후 코드 실행 방지 @@ -14,13 +13,12 @@ import { isLoggedIn, getUser, clearAuthData } from './auth.js'; // 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우) if (!currentUser || !currentUser.username || !currentUser.role) { - console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); + console.error(' 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); clearAuthData(); window.location.href = '/login'; return; } - console.log(`✅ ${currentUser.username}(${currentUser.role})님 인증 성공.`); // 역할 기반 메뉴 제어 로직은 각 컴포넌트 로더(load-navbar.js 등)로 이전함. // 전역 변수 할당(window.currentUser) 제거. diff --git a/system1-factory/fastapi-bridge/static/js/change-password.js b/system1-factory/fastapi-bridge/static/js/change-password.js index da68820..32ae0e7 100644 --- a/system1-factory/fastapi-bridge/static/js/change-password.js +++ b/system1-factory/fastapi-bridge/static/js/change-password.js @@ -206,6 +206,4 @@ form?.addEventListener('submit', async (e) => { // 페이지 로드 시 현재 사용자 정보 표시 document.addEventListener('DOMContentLoaded', () => { const user = JSON.parse(localStorage.getItem('sso_user') || '{}'); - console.log('🔐 비밀번호 변경 페이지 로드됨'); - console.log('👤 현재 사용자:', user.username || 'Unknown'); }); \ No newline at end of file diff --git a/system1-factory/fastapi-bridge/static/js/daily-work-report.js b/system1-factory/fastapi-bridge/static/js/daily-work-report.js index 52c143d..b9951ee 100644 --- a/system1-factory/fastapi-bridge/static/js/daily-work-report.js +++ b/system1-factory/fastapi-bridge/static/js/daily-work-report.js @@ -42,7 +42,7 @@ function getCurrentUser() { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { const parsed = JSON.parse(userInfo); console.log('localStorage에서 가져온 사용자 정보:', parsed); @@ -94,7 +94,6 @@ async function loadData() { try { showMessage('데이터를 불러오는 중...', 'loading'); - console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩 시작...'); await loadWorkers(); await loadProjects(); await loadWorkTypes(); @@ -119,7 +118,6 @@ async function loadWorkers() { console.log('Workers API 호출 중... (통합 API 사용)'); const data = await apiCall(`${API}/workers`); workers = Array.isArray(data) ? data : (data.workers || []); - console.log('✅ Workers 로드 성공:', workers.length); } catch (error) { console.error('작업자 로딩 오류:', error); throw error; @@ -131,7 +129,6 @@ async function loadProjects() { console.log('Projects API 호출 중... (통합 API 사용)'); const data = await apiCall(`${API}/projects`); projects = Array.isArray(data) ? data : (data.projects || []); - console.log('✅ Projects 로드 성공:', projects.length); } catch (error) { console.error('프로젝트 로딩 오류:', error); throw error; @@ -143,12 +140,10 @@ async function loadWorkTypes() { const data = await apiCall(`${API}/daily-work-reports/work-types`); if (Array.isArray(data) && data.length > 0) { workTypes = data; - console.log('✅ 작업 유형 API 사용 (통합 설정)'); return; } throw new Error('API 실패'); } catch (error) { - console.log('⚠️ 작업 유형 API 사용 불가, 기본값 사용'); workTypes = [ {id: 1, name: 'Base'}, {id: 2, name: 'Vessel'}, @@ -162,12 +157,10 @@ async function loadWorkStatusTypes() { const data = await apiCall(`${API}/daily-work-reports/work-status-types`); if (Array.isArray(data) && data.length > 0) { workStatusTypes = data; - console.log('✅ 업무 상태 유형 API 사용 (통합 설정)'); return; } throw new Error('API 실패'); } catch (error) { - console.log('⚠️ 업무 상태 유형 API 사용 불가, 기본값 사용'); workStatusTypes = [ {id: 1, name: '정규'}, {id: 2, name: '에러'} @@ -180,12 +173,10 @@ async function loadErrorTypes() { const data = await apiCall(`${API}/daily-work-reports/error-types`); if (Array.isArray(data) && data.length > 0) { errorTypes = data; - console.log('✅ 에러 유형 API 사용 (통합 설정)'); return; } throw new Error('API 실패'); } catch (error) { - console.log('⚠️ 에러 유형 API 사용 불가, 기본값 사용'); errorTypes = [ {id: 1, name: '설계미스'}, {id: 2, name: '외주작업 불량'}, @@ -429,10 +420,9 @@ async function saveWorkReport() { body: JSON.stringify(requestData) }); - console.log('✅ 저장 성공 (통합 API):', result); totalSaved++; } catch (error) { - console.error('❌ 저장 실패:', error); + console.error(' 저장 실패:', error); totalFailed++; const workerName = workers.find(w => w.worker_id == workerId)?.worker_name || '알 수 없음'; @@ -508,10 +498,8 @@ async function loadTodayWorkers() { queryParams += `&created_by=${currentUser.id}`; } - console.log(`🔒 본인 입력분만 조회 (통합 API): ${API}/daily-work-reports?${queryParams}`); const rawData = await apiCall(`${API}/daily-work-reports?${queryParams}`); - console.log('📊 당일 작업 데이터 (통합 API):', rawData); let data = []; if (Array.isArray(rawData)) { @@ -789,14 +777,13 @@ async function saveEditedWork() { body: JSON.stringify(updateData) }); - console.log('✅ 수정 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); closeEditModal(); refreshTodayWorkers(); } catch (error) { - console.error('❌ 수정 실패:', error); + console.error(' 수정 실패:', error); showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -817,14 +804,13 @@ async function deleteWorkItem(workId) { method: 'DELETE' }); - console.log('✅ 삭제 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); // 화면 새로고침 refreshTodayWorkers(); } catch (error) { - console.error('❌ 삭제 실패:', error); + console.error(' 삭제 실패:', error); showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -877,7 +863,6 @@ async function init() { setupEventListeners(); loadTodayWorkers(); - console.log('✅ 시스템 초기화 완료 (통합 API 설정 적용)'); } catch (error) { console.error('초기화 오류:', error); diff --git a/system1-factory/fastapi-bridge/static/js/group-leader-dashboard.js b/system1-factory/fastapi-bridge/static/js/group-leader-dashboard.js index a075540..f73f235 100644 --- a/system1-factory/fastapi-bridge/static/js/group-leader-dashboard.js +++ b/system1-factory/fastapi-bridge/static/js/group-leader-dashboard.js @@ -1,11 +1,9 @@ // /js/group-leader-dashboard.js // 그룹장 전용 대시보드 기능 -console.log('📊 그룹장 대시보드 스크립트 로딩'); // 팀 현황 새로고침 async function refreshTeamStatus() { - console.log('🔄 팀 현황 새로고침 시작'); try { // 로딩 상태 표시 @@ -24,7 +22,7 @@ async function refreshTeamStatus() { }, 1000); } catch (error) { - console.error('❌ 팀 현황 로딩 실패:', error); + console.error(' 팀 현황 로딩 실패:', error); const teamList = document.getElementById('team-list'); if (teamList) { teamList.innerHTML = '
❌ 로딩 실패
'; @@ -64,7 +62,6 @@ function updateTeamStatusUI() { if (presentEl) presentEl.textContent = presentCount; if (absentEl) absentEl.textContent = absentCount; - console.log('✅ 팀 현황 업데이트 완료'); } // 환영 메시지 개인화 @@ -74,21 +71,18 @@ function personalizeWelcome() { if (user && user.name && welcomeMsg) { welcomeMsg.textContent = `${user.name}님의 실시간 팀 현황 및 작업 모니터링`; - console.log('✅ 환영 메시지 개인화 완료'); } } // 페이지 초기화 document.addEventListener('DOMContentLoaded', function() { - console.log('🚀 그룹장 대시보드 초기화 시작'); // 사용자 정보 확인 const user = JSON.parse(localStorage.getItem('sso_user') || '{}'); - console.log('👤 현재 사용자:', user); // 권한 확인 if (user.access_level !== 'group_leader') { - console.warn('⚠️ 그룹장 권한 없음:', user.access_level); + console.warn(' 그룹장 권한 없음:', user.access_level); // 필요시 다른 페이지로 리다이렉트 } @@ -96,7 +90,6 @@ document.addEventListener('DOMContentLoaded', function() { personalizeWelcome(); updateTeamStatusUI(); - console.log('✅ 그룹장 대시보드 초기화 완료'); }); // 전역 함수로 내보내기 (HTML에서 사용) diff --git a/system1-factory/fastapi-bridge/static/js/load-navbar.js b/system1-factory/fastapi-bridge/static/js/load-navbar.js index bad72d9..878b8ea 100644 --- a/system1-factory/fastapi-bridge/static/js/load-navbar.js +++ b/system1-factory/fastapi-bridge/static/js/load-navbar.js @@ -135,10 +135,9 @@ document.addEventListener('DOMContentLoaded', async () => { updateTime(); setInterval(updateTime, 1000); - console.log('✅ 네비게이션 바 로딩 완료'); } catch (error) { - console.error('🔴 네비게이션 바 로딩 중 오류 발생:', error); + console.error(' 네비게이션 바 로딩 중 오류 발생:', error); navbarContainer.innerHTML = '

네비게이션 바를 불러오는 데 실패했습니다.

'; } }); \ No newline at end of file diff --git a/system1-factory/fastapi-bridge/static/js/load-sections.js b/system1-factory/fastapi-bridge/static/js/load-sections.js index 6b735ff..de7fda4 100644 --- a/system1-factory/fastapi-bridge/static/js/load-sections.js +++ b/system1-factory/fastapi-bridge/static/js/load-sections.js @@ -92,7 +92,6 @@ async function initializeSections() { // 5. 모든 수정이 완료된 HTML을 실제 DOM에 한 번에 삽입 mainContainer.innerHTML = doc.body.innerHTML; - console.log(`✅ ${currentUser.role} 역할의 섹션 로딩 완료.`); } catch (error) { console.error('섹션 로딩 중 오류 발생:', error); diff --git a/system1-factory/fastapi-bridge/static/js/load-sidebar.js b/system1-factory/fastapi-bridge/static/js/load-sidebar.js index 5f912a2..bc0f250 100644 --- a/system1-factory/fastapi-bridge/static/js/load-sidebar.js +++ b/system1-factory/fastapi-bridge/static/js/load-sidebar.js @@ -58,10 +58,9 @@ document.addEventListener('DOMContentLoaded', async () => { // 3. 수정 완료된 HTML을 실제 DOM에 삽입 sidebarContainer.innerHTML = doc.body.innerHTML; - console.log('✅ 사이드바 로딩 및 필터링 완료'); } catch (error) { - console.error('🔴 사이드바 로딩 실패:', error); + console.error(' 사이드바 로딩 실패:', error); sidebarContainer.innerHTML = '

메뉴 로딩 실패

'; } }); \ No newline at end of file diff --git a/system1-factory/fastapi-bridge/static/js/management-dashboard.js b/system1-factory/fastapi-bridge/static/js/management-dashboard.js index b83e25f..f131d76 100644 --- a/system1-factory/fastapi-bridge/static/js/management-dashboard.js +++ b/system1-factory/fastapi-bridge/static/js/management-dashboard.js @@ -47,7 +47,7 @@ function getCurrentUser() { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { const parsed = JSON.parse(userInfo); console.log('localStorage에서 가져온 사용자 정보:', parsed); @@ -128,7 +128,6 @@ async function loadWorkers() { console.log('작업자 데이터 로딩 중... (통합 API)'); const data = await apiCall(`${API}/workers`); workers = Array.isArray(data) ? data : (data.workers || []); - console.log('✅ 작업자 로드 성공:', workers.length); } catch (error) { console.error('작업자 로딩 오류:', error); throw error; @@ -142,32 +141,27 @@ async function loadWorkData(date) { // 1차: view_all=true로 전체 데이터 시도 let queryParams = `date=${date}&view_all=true`; - console.log(`🔍 1차 시도: ${API}/daily-work-reports?${queryParams}`); let data = await apiCall(`${API}/daily-work-reports?${queryParams}`); workData = Array.isArray(data) ? data : (data.data || []); // 데이터가 없으면 다른 방법들 시도 if (workData.length === 0) { - console.log('⚠️ view_all로 데이터 없음, 다른 방법 시도...'); // 2차: admin=true로 시도 queryParams = `date=${date}&admin=true`; - console.log(`🔍 2차 시도: ${API}/daily-work-reports?${queryParams}`); data = await apiCall(`${API}/daily-work-reports?${queryParams}`); workData = Array.isArray(data) ? data : (data.data || []); if (workData.length === 0) { // 3차: 날짜 경로 파라미터로 시도 - console.log(`🔍 3차 시도: ${API}/daily-work-reports/date/${date}`); data = await apiCall(`${API}/daily-work-reports/date/${date}`); workData = Array.isArray(data) ? data : (data.data || []); if (workData.length === 0) { // 4차: 기본 파라미터만으로 시도 - console.log(`🔍 4차 시도: ${API}/daily-work-reports?date=${date}`); data = await apiCall(`${API}/daily-work-reports?date=${date}`); workData = Array.isArray(data) ? data : (data.data || []); @@ -175,15 +169,11 @@ async function loadWorkData(date) { } } - console.log(`✅ 최종 작업 데이터 로드 결과: ${workData.length}개`); // 디버깅을 위한 상세 로그 if (workData.length > 0) { - console.log('📊 로드된 데이터 샘플:', workData.slice(0, 3)); const uniqueWorkers = [...new Set(workData.map(w => w.worker_name))]; - console.log('👥 데이터에 포함된 작업자들:', uniqueWorkers); } else { - console.log('❌ 해당 날짜에 작업 데이터가 없거나 접근 권한이 없습니다.'); } return workData; @@ -195,10 +185,8 @@ async function loadWorkData(date) { // 구체적인 에러 정보 표시 if (error.message.includes('403')) { - console.log('🔒 권한 부족으로 인한 접근 제한'); throw new Error('해당 날짜의 데이터에 접근할 권한이 없습니다.'); } else if (error.message.includes('404')) { - console.log('📭 해당 날짜에 데이터 없음'); throw new Error('해당 날짜에 입력된 작업 데이터가 없습니다.'); } else { throw error; @@ -339,7 +327,6 @@ function displayDashboard(data) { filteredWorkData = data.workers; setupFiltering(); - console.log('✅ 대시보드 표시 완료'); } // 요약 섹션 표시 @@ -767,7 +754,6 @@ async function saveEditedWork(workId) { body: JSON.stringify(updateData) }); - console.log('✅ 수정 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); closeEditModal(); @@ -777,7 +763,7 @@ async function saveEditedWork(workId) { await loadDashboardData(); } catch (error) { - console.error('❌ 수정 실패:', error); + console.error(' 수정 실패:', error); showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -798,7 +784,6 @@ async function deleteWorkItem(workId) { method: 'DELETE' }); - console.log('✅ 삭제 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); closeWorkerDetailModal(); @@ -807,7 +792,7 @@ async function deleteWorkItem(workId) { await loadDashboardData(); } catch (error) { - console.error('❌ 삭제 실패:', error); + console.error(' 삭제 실패:', error); showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -912,7 +897,6 @@ async function init() { // 이벤트 리스너 설정 setupEventListeners(); - console.log('✅ 관리자 대시보드 초기화 완료 (통합 API 설정 적용)'); // 자동으로 오늘 데이터 로드 loadDashboardData(); diff --git a/system1-factory/fastapi-bridge/static/js/my-profile.js b/system1-factory/fastapi-bridge/static/js/my-profile.js index 201d3c3..4d8ce2a 100644 --- a/system1-factory/fastapi-bridge/static/js/my-profile.js +++ b/system1-factory/fastapi-bridge/static/js/my-profile.js @@ -117,6 +117,5 @@ function showError(message) { // 페이지 로드 시 실행 document.addEventListener('DOMContentLoaded', () => { - console.log('👤 프로필 페이지 로드됨'); loadProfile(); }); \ No newline at end of file diff --git a/system1-factory/fastapi-bridge/static/js/work-report-review.js b/system1-factory/fastapi-bridge/static/js/work-report-review.js index 702cf3d..51a5694 100644 --- a/system1-factory/fastapi-bridge/static/js/work-report-review.js +++ b/system1-factory/fastapi-bridge/static/js/work-report-review.js @@ -71,7 +71,6 @@ class WorkReportReviewManager { {id: 3, name: '입고지연'}, {id: 4, name: '작업 불량'} ]; } catch (error) { - console.log('⚠️ 일부 API 사용 불가, 기본값 사용'); } // 휴가 정보 로드 @@ -101,13 +100,11 @@ class WorkReportReviewManager { this.attendanceData = await response.json(); console.log('휴가 정보 로드 완료:', this.attendanceData.length); } else if (response.status === 404) { - console.log('⚠️ 휴가 API 없음, 더미 데이터 생성'); this.attendanceData = this.generateDummyAttendance(); } else { throw new Error(`휴가 정보 로드 실패: ${response.status}`); } } catch (error) { - console.log('⚠️ 휴가 정보 로드 오류, 더미 데이터 사용:', error.message); this.attendanceData = this.generateDummyAttendance(); } } @@ -204,7 +201,6 @@ class WorkReportReviewManager { if (response.status === 404 || response.status === 500) { // API가 아직 준비되지 않은 경우 더미 데이터 사용 this.reports = this.generateDummyData(); - console.log('⚠️ API 응답 오류, 더미 데이터 사용:', response.status); if (response.status === 404) { this.showMessage('⚠️ 검토 API가 준비되지 않아 더미 데이터를 표시합니다.', 'warning'); } else { @@ -227,7 +223,6 @@ class WorkReportReviewManager { this.updateTable(); } catch (error) { - console.log('⚠️ 네트워크 오류로 더미 데이터 사용:', error.message); // 더미 데이터로 대체 this.reports = this.generateDummyData(); this.validateWorkHours(); diff --git a/system1-factory/fastapi-bridge/static/js/work-review.js b/system1-factory/fastapi-bridge/static/js/work-review.js index b8f2380..163fe8b 100644 --- a/system1-factory/fastapi-bridge/static/js/work-review.js +++ b/system1-factory/fastapi-bridge/static/js/work-review.js @@ -499,14 +499,13 @@ async function saveEditedWork(workId) { body: JSON.stringify(updateData) }); - console.log('✅ 수정 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); closeEditModal(); refreshCurrentDay(); // 현재 날짜 데이터 새로고침 } catch (error) { - console.error('❌ 수정 실패:', error); + console.error(' 수정 실패:', error); showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); // 버튼 복원 @@ -538,13 +537,12 @@ async function deleteWorkItem(workId) { method: 'DELETE' }); - console.log('✅ 삭제 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); refreshCurrentDay(); // 현재 날짜 데이터 새로고침 } catch (error) { - console.error('❌ 삭제 실패:', error); + console.error(' 삭제 실패:', error); showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -597,7 +595,7 @@ async function deleteWorkerAllWorks(date, workerName) { refreshCurrentDay(); // 현재 날짜 데이터 새로고침 } catch (error) { - console.error('❌ 전체 삭제 실패:', error); + console.error(' 전체 삭제 실패:', error); showMessage('작업 삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -638,7 +636,6 @@ function showConfirmDialog(title, message, warning) { // 기본 데이터 로드 (통합 API 사용) async function loadBasicData() { try { - console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩...'); const promises = [ // 프로젝트 로드 @@ -695,7 +692,6 @@ async function loadBasicData() { errorTypes }; - console.log('✅ 기본 데이터 로드 완료 (통합 API):', basicData); } catch (error) { console.error('기본 데이터 로드 실패:', error); } @@ -764,7 +760,6 @@ async function init() { // 기본 데이터 미리 로드 await loadBasicData(); - console.log('✅ 검토 페이지 초기화 완료 (통합 API 설정 적용)'); } catch (error) { console.error('초기화 오류:', error); diff --git a/system1-factory/web/js/_deprecated/index.js b/system1-factory/web/js/_deprecated/index.js deleted file mode 100644 index c51fc59..0000000 --- a/system1-factory/web/js/_deprecated/index.js +++ /dev/null @@ -1,318 +0,0 @@ -/** - * Daily Work Report - Module Loader - * 작업보고서 모듈을 초기화하고 연결하는 메인 진입점 - * - * 로드 순서: - * 1. state.js - 전역 상태 관리 - * 2. utils.js - 유틸리티 함수 - * 3. api.js - API 클라이언트 - * 4. index.js - 이 파일 (메인 컨트롤러) - */ - -class DailyWorkReportController { - constructor() { - this.state = window.DailyWorkReportState; - this.api = window.DailyWorkReportAPI; - this.utils = window.DailyWorkReportUtils; - this.initialized = false; - - console.log('[Controller] DailyWorkReportController 생성'); - } - - /** - * 초기화 - */ - async init() { - if (this.initialized) { - console.log('[Controller] 이미 초기화됨'); - return; - } - - console.log('[Controller] 초기화 시작...'); - - try { - // 이벤트 리스너 설정 - this.setupEventListeners(); - - // 기본 데이터 로드 - await this.api.loadAllData(); - - // TBM 탭이 기본 - await this.switchTab('tbm'); - - this.initialized = true; - console.log('[Controller] 초기화 완료'); - - } catch (error) { - console.error('[Controller] 초기화 실패:', error); - window.showMessage?.('초기화 중 오류가 발생했습니다: ' + error.message, 'error'); - } - } - - /** - * 이벤트 리스너 설정 - */ - setupEventListeners() { - // 탭 버튼 - const tbmBtn = document.getElementById('tbmReportTab'); - const completedBtn = document.getElementById('completedReportTab'); - - if (tbmBtn) { - tbmBtn.addEventListener('click', () => this.switchTab('tbm')); - } - if (completedBtn) { - completedBtn.addEventListener('click', () => this.switchTab('completed')); - } - - // 완료 보고서 날짜 변경 - const completedDateInput = document.getElementById('completedReportDate'); - if (completedDateInput) { - completedDateInput.addEventListener('change', () => this.loadCompletedReports()); - } - - console.log('[Controller] 이벤트 리스너 설정 완료'); - } - - /** - * 탭 전환 - */ - async switchTab(tab) { - this.state.setCurrentTab(tab); - - const tbmBtn = document.getElementById('tbmReportTab'); - const completedBtn = document.getElementById('completedReportTab'); - const tbmSection = document.getElementById('tbmReportSection'); - const completedSection = document.getElementById('completedReportSection'); - - // 모든 탭 버튼 비활성화 - tbmBtn?.classList.remove('active'); - completedBtn?.classList.remove('active'); - - // 모든 섹션 숨기기 - if (tbmSection) tbmSection.style.display = 'none'; - if (completedSection) completedSection.style.display = 'none'; - - // 선택된 탭 활성화 - if (tab === 'tbm') { - tbmBtn?.classList.add('active'); - if (tbmSection) tbmSection.style.display = 'block'; - await this.loadTbmData(); - } else if (tab === 'completed') { - completedBtn?.classList.add('active'); - if (completedSection) completedSection.style.display = 'block'; - - // 오늘 날짜로 초기화 - const dateInput = document.getElementById('completedReportDate'); - if (dateInput) { - dateInput.value = this.utils.getKoreaToday(); - } - await this.loadCompletedReports(); - } - } - - /** - * TBM 데이터 로드 - */ - async loadTbmData() { - try { - await this.api.loadIncompleteTbms(); - await this.api.loadDailyIssuesForTbms(); - - // 렌더링은 기존 함수 사용 (점진적 마이그레이션) - if (typeof window.renderTbmWorkList === 'function') { - window.renderTbmWorkList(); - } - } catch (error) { - console.error('[Controller] TBM 데이터 로드 오류:', error); - window.showMessage?.('TBM 데이터를 불러오는 중 오류가 발생했습니다.', 'error'); - } - } - - /** - * 완료 보고서 로드 - */ - async loadCompletedReports() { - try { - const dateInput = document.getElementById('completedReportDate'); - const date = dateInput?.value || this.utils.getKoreaToday(); - - const reports = await this.api.loadCompletedReports(date); - - // 렌더링은 기존 함수 사용 - if (typeof window.renderCompletedReports === 'function') { - window.renderCompletedReports(reports); - } - } catch (error) { - console.error('[Controller] 완료 보고서 로드 오류:', error); - window.showMessage?.('완료 보고서를 불러오는 중 오류가 발생했습니다.', 'error'); - } - } - - /** - * TBM 작업보고서 제출 - */ - async submitTbmWorkReport(index) { - try { - const tbm = this.state.incompleteTbms[index]; - if (!tbm) { - throw new Error('TBM 데이터를 찾을 수 없습니다.'); - } - - // 유효성 검사 - const totalHoursInput = document.getElementById(`totalHours_${index}`); - const totalHours = parseFloat(totalHoursInput?.value); - - if (!totalHours || totalHours <= 0) { - window.showMessage?.('작업시간을 입력해주세요.', 'warning'); - return; - } - - // 부적합 시간 계산 - const defects = this.state.tempDefects[index] || []; - const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); - const regularHours = totalHours - errorHours; - - if (regularHours < 0) { - window.showMessage?.('부적합 시간이 총 작업시간을 초과할 수 없습니다.', 'warning'); - return; - } - - // API 데이터 구성 - const user = this.state.getCurrentUser(); - const reportData = { - tbm_session_id: tbm.session_id, - tbm_assignment_id: tbm.assignment_id, - user_id: tbm.user_id, - project_id: tbm.project_id, - work_type_id: tbm.work_type_id, - report_date: this.utils.formatDateForApi(tbm.session_date), - total_hours: totalHours, - regular_hours: regularHours, - error_hours: errorHours, - work_status_id: errorHours > 0 ? 2 : 1, - created_by: user?.user_id || user?.id, - defects: defects.map(d => ({ - category_id: d.category_id, - item_id: d.item_id, - issue_report_id: d.issue_report_id, - defect_hours: d.defect_hours, - note: d.note - })) - }; - - const result = await this.api.submitTbmWorkReport(reportData); - - window.showSaveResultModal?.( - 'success', - '제출 완료', - `${tbm.worker_name}의 작업보고서가 제출되었습니다.` - ); - - // 목록 새로고침 - await this.loadTbmData(); - - } catch (error) { - console.error('[Controller] 제출 오류:', error); - window.showSaveResultModal?.( - 'error', - '제출 실패', - error.message || '작업보고서 제출 중 오류가 발생했습니다.' - ); - } - } - - /** - * 세션 일괄 제출 - */ - async batchSubmitSession(sessionKey) { - const rows = document.querySelectorAll(`tr[data-session-key="${sessionKey}"][data-type="tbm"]`); - const indices = []; - - rows.forEach(row => { - const index = parseInt(row.dataset.index); - const totalHoursInput = document.getElementById(`totalHours_${index}`); - if (totalHoursInput?.value && parseFloat(totalHoursInput.value) > 0) { - indices.push(index); - } - }); - - if (indices.length === 0) { - window.showMessage?.('제출할 항목이 없습니다. 작업시간을 입력해주세요.', 'warning'); - return; - } - - const confirmed = confirm(`${indices.length}건의 작업보고서를 일괄 제출하시겠습니까?`); - if (!confirmed) return; - - let successCount = 0; - let failCount = 0; - - for (const index of indices) { - try { - await this.submitTbmWorkReport(index); - successCount++; - } catch (error) { - failCount++; - console.error(`[Controller] 일괄 제출 오류 (index: ${index}):`, error); - } - } - - if (failCount === 0) { - window.showSaveResultModal?.('success', '일괄 제출 완료', `${successCount}건이 성공적으로 제출되었습니다.`); - } else { - window.showSaveResultModal?.('warning', '일괄 제출 부분 완료', `성공: ${successCount}건, 실패: ${failCount}건`); - } - } - - /** - * 상태 디버그 - */ - debug() { - console.log('[Controller] 상태 디버그:'); - this.state.debug(); - } -} - -// 전역 인스턴스 생성 -window.DailyWorkReportController = new DailyWorkReportController(); - -// 하위 호환성: 기존 전역 함수들 -window.switchTab = (tab) => window.DailyWorkReportController.switchTab(tab); -window.submitTbmWorkReport = (index) => window.DailyWorkReportController.submitTbmWorkReport(index); -window.batchSubmitTbmSession = (sessionKey) => window.DailyWorkReportController.batchSubmitSession(sessionKey); - -// 사용자 정보 함수 -window.getUser = () => window.DailyWorkReportState.getUser(); -window.getCurrentUser = () => window.DailyWorkReportState.getCurrentUser(); - -// 날짜 그룹 토글 (UI 함수) -window.toggleDateGroup = function(dateStr) { - const group = document.querySelector(`.date-group[data-date="${dateStr}"]`); - if (!group) return; - - const isExpanded = group.classList.contains('expanded'); - const content = group.querySelector('.date-group-content'); - const icon = group.querySelector('.date-toggle-icon'); - - if (isExpanded) { - group.classList.remove('expanded'); - group.classList.add('collapsed'); - if (content) content.style.display = 'none'; - if (icon) icon.textContent = '▶'; - } else { - group.classList.remove('collapsed'); - group.classList.add('expanded'); - if (content) content.style.display = 'block'; - if (icon) icon.textContent = '▼'; - } -}; - -// DOMContentLoaded 이벤트에서 초기화 -document.addEventListener('DOMContentLoaded', () => { - // 약간의 지연 후 초기화 (다른 스크립트 로드 대기) - setTimeout(() => { - window.DailyWorkReportController.init(); - }, 100); -}); - -console.log('[Module] daily-work-report/index.js 로드 완료'); diff --git a/system1-factory/web/js/_deprecated/work-report-api.js b/system1-factory/web/js/_deprecated/work-report-api.js deleted file mode 100644 index 3b23ec9..0000000 --- a/system1-factory/web/js/_deprecated/work-report-api.js +++ /dev/null @@ -1,51 +0,0 @@ -// /js/work-report-api.js -import { apiGet, apiPost } from './api-helper.js'; - -/** - * 작업 보고서 작성을 위해 필요한 초기 데이터(작업자, 프로젝트, 태스크)를 가져옵니다. - * Promise.all을 사용하여 병렬로 API를 호출합니다. - * @returns {Promise<{workers: Array, projects: Array, tasks: Array}>} - */ -export async function getInitialData() { - try { - const [allWorkers, projects, tasks] = await Promise.all([ - apiGet('/workers'), - apiGet('/projects'), - apiGet('/tasks') - ]); - - // 활성화된 작업자만 필터링 - const workers = allWorkers.filter(worker => { - return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; - }); - - // 데이터 형식 검증 - if (!Array.isArray(workers) || !Array.isArray(projects) || !Array.isArray(tasks)) { - throw new Error('서버에서 받은 데이터 형식이 올바르지 않습니다.'); - } - - // 작업자 목록은 ID 기준으로 정렬 - workers.sort((a, b) => a.user_id - b.user_id); - - return { workers, projects, tasks }; - } catch (error) { - console.error('초기 데이터 로딩 중 오류 발생:', error); - // 에러를 다시 던져서 호출한 쪽에서 처리할 수 있도록 함 - throw error; - } -} - -/** - * 작성된 작업 보고서 데이터를 서버에 전송합니다. - * @param {Array} reportData - 전송할 작업 보고서 데이터 배열 - * @returns {Promise} - 서버의 응답 결과 - */ -export async function createWorkReport(reportData) { - try { - const result = await apiPost('/workreports', reportData); - return result; - } catch (error) { - console.error('작업 보고서 생성 요청 실패:', error); - throw error; - } -} \ No newline at end of file diff --git a/system1-factory/web/js/_deprecated/work-report-create.js b/system1-factory/web/js/_deprecated/work-report-create.js deleted file mode 100644 index d61ed79..0000000 --- a/system1-factory/web/js/_deprecated/work-report-create.js +++ /dev/null @@ -1,79 +0,0 @@ -// /js/work-report-create.js -import { renderCalendar } from './calendar.js'; -import { getInitialData, createWorkReport } from './work-report-api.js'; -import { initializeReportTable, getReportData } from './work-report-ui.js'; - -// 전역 상태 변수 -let selectedDate = ''; - -/** - * 날짜가 선택되었을 때 실행되는 콜백 함수. - * 초기 데이터를 로드하고 테이블을 렌더링합니다. - * @param {string} date - 선택된 날짜 (YYYY-MM-DD 형식) - */ -async function onDateSelect(date) { - selectedDate = date; - const tableBody = document.getElementById('reportBody'); - tableBody.innerHTML = '데이터를 불러오는 중...'; - - try { - const initialData = await getInitialData(); - initializeReportTable(initialData); - } catch (error) { - alert('데이터를 불러오는 데 실패했습니다: ' + error.message); - tableBody.innerHTML = '오류 발생! 데이터를 불러올 수 없습니다.'; - } -} - -/** - * '전체 등록' 버튼 클릭 시 실행되는 이벤트 핸들러. - * 폼 데이터를 서버에 전송합니다. - */ -async function handleSubmit() { - if (!selectedDate) { - alert('먼저 달력에서 날짜를 선택해주세요.'); - return; - } - - const reportData = getReportData(); - if (!reportData) { - // getReportData 내부에서 이미 alert으로 사용자에게 알림 - return; - } - - // 각 항목에 선택된 날짜 추가 - const payload = reportData.map(item => ({ ...item, date: selectedDate })); - - const submitBtn = document.getElementById('submitBtn'); - submitBtn.disabled = true; - submitBtn.textContent = '등록 중...'; - - try { - const result = await createWorkReport(payload); - if (result.success) { - alert('✅ 작업 보고서가 성공적으로 등록되었습니다!'); - // 성공 후 폼을 다시 로드하거나, 다른 페이지로 이동 등의 로직 추가 가능 - onDateSelect(selectedDate); // 현재 날짜의 폼을 다시 로드 - } else { - throw new Error(result.error || '알 수 없는 오류로 등록에 실패했습니다.'); - } - } catch (error) { - alert('❌ 등록 실패: ' + error.message); - } finally { - submitBtn.disabled = false; - submitBtn.textContent = '전체 등록'; - } -} - -/** - * 페이지 초기화 함수 - */ -function initializePage() { - renderCalendar('calendar', onDateSelect); - - const submitBtn = document.getElementById('submitBtn'); - submitBtn.addEventListener('click', handleSubmit); -} - -// DOM이 로드되면 페이지 초기화를 시작합니다. -document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/system1-factory/web/js/_deprecated/work-report-ui.js b/system1-factory/web/js/_deprecated/work-report-ui.js deleted file mode 100644 index e4eba20..0000000 --- a/system1-factory/web/js/_deprecated/work-report-ui.js +++ /dev/null @@ -1,141 +0,0 @@ -// /js/work-report-ui.js - -const DEFAULT_PROJECT_ID = '13'; // 나중에는 API나 설정에서 받아오는 것이 좋음 -const DEFAULT_TASK_ID = '15'; - -/** - * 주어진 데이터를 바탕으로 - ${worker.worker_name} - - - - - - - - - - - - `; - - // 이벤트 리스너 설정 - const workTypeSelect = tr.querySelector('[name="work_type"]'); - const projectSelect = tr.querySelector('[name="project_id"]'); - const taskSelect = tr.querySelector('[name="task_id"]'); - - workTypeSelect.addEventListener('change', () => { - const isDisabled = ['연차', '휴무', '유급'].includes(workTypeSelect.value); - projectSelect.disabled = isDisabled; - taskSelect.disabled = isDisabled; - if (isDisabled) { - projectSelect.value = DEFAULT_PROJECT_ID; - taskSelect.value = DEFAULT_TASK_ID; - } - }); - - tr.querySelector('.remove-btn').addEventListener('click', () => { - tr.remove(); - updateRowNumbers(tr.parentElement); - }); - - return tr; -} - -/** - * 작업 보고서 테이블을 초기화하고 데이터를 채웁니다. - * @param {{workers: Array, projects: Array, tasks: Array}} initialData - 초기 데이터 - */ -export function initializeReportTable(initialData) { - const tableBody = document.getElementById('reportBody'); - if (!tableBody) return; - - tableBody.innerHTML = ''; // 기존 내용 초기화 - const { workers, projects, tasks } = initialData; - - if (!workers || workers.length === 0) { - tableBody.innerHTML = '등록할 작업자 정보가 없습니다.'; - return; - } - - workers.forEach((worker, index) => { - const row = createReportRow(worker, projects, tasks, index); - tableBody.appendChild(row); - }); -} - -/** - * 테이블에서 폼 데이터를 추출하여 배열로 반환합니다. - * @returns {Array|null} - 추출된 데이터 배열 또는 유효성 검사 실패 시 null - */ -export function getReportData() { - const tableBody = document.getElementById('reportBody'); - const rows = tableBody.querySelectorAll('tr'); - - if (rows.length === 0 || (rows.length === 1 && rows[0].cells.length < 2)) { - alert('등록할 내용이 없습니다.'); - return null; - } - - const reportData = []; - const workerIds = new Set(); - - for (const tr of rows) { - const workerId = tr.querySelector('[name="user_id"]').value; - if (workerIds.has(workerId)) { - alert(`오류: 작업자 '${tr.cells[1].textContent.trim()}'가 중복 등록되었습니다.`); - return null; - } - workerIds.add(workerId); - - reportData.push({ - user_id: workerId, - project_id: tr.querySelector('[name="project_id"]').value, - task_id: tr.querySelector('[name="task_id"]').value, - overtime_hours: tr.querySelector('[name="overtime"]').value || 0, - work_details: tr.querySelector('[name="work_type"]').value, - memo: tr.querySelector('[name="memo"]').value - }); - } - - return reportData; -} \ No newline at end of file diff --git a/system1-factory/web/js/admin-settings.js b/system1-factory/web/js/admin-settings.js index e802cc6..4c87cce 100644 --- a/system1-factory/web/js/admin-settings.js +++ b/system1-factory/web/js/admin-settings.js @@ -50,13 +50,11 @@ const elements = { // ========== 초기화 ========== // document.addEventListener('DOMContentLoaded', async () => { - console.log('🔧 관리자 설정 페이지 초기화 시작'); try { await initializePage(); - console.log('✅ 관리자 설정 페이지 초기화 완료'); } catch (error) { - console.error('❌ 페이지 초기화 오류:', error); + console.error(' 페이지 초기화 오류:', error); showToast('페이지를 불러오는 중 오류가 발생했습니다.', 'error'); } }); @@ -75,7 +73,6 @@ function setupUserInfo() { const authData = getAuthData(); if (authData && authData.user) { currentUser = authData.user; - console.log('👤 사용자 정보 로드 완료:', currentUser.name, currentUser.role); } } @@ -150,13 +147,11 @@ function setupEventListeners() { // ========== 사용자 관리 ========== // async function loadUsers() { try { - console.log('👥 사용자 목록 로딩...'); // 실제 API에서 사용자 데이터 가져오기 const response = await window.apiCall('/users'); users = Array.isArray(response) ? response : (response.data || []); - console.log(`✅ 사용자 ${users.length}명 로드 완료`); // 필터링된 사용자 목록 초기화 filteredUsers = [...users]; @@ -165,7 +160,7 @@ async function loadUsers() { renderUsersTable(); } catch (error) { - console.error('❌ 사용자 목록 로딩 오류:', error); + console.error(' 사용자 목록 로딩 오류:', error); showToast('사용자 목록을 불러오는 중 오류가 발생했습니다.', 'error'); users = []; filteredUsers = []; @@ -556,9 +551,8 @@ async function loadAllPages() { try { const response = await apiCall('/pages'); allPages = response.data || response || []; - console.log('📄 페이지 목록 로드:', allPages.length, '개'); } catch (error) { - console.error('❌ 페이지 목록 로드 오류:', error); + console.error(' 페이지 목록 로드 오류:', error); allPages = []; } } @@ -568,9 +562,8 @@ async function loadUserPageAccess(userId) { try { const response = await apiCall(`/users/${userId}/page-access`); userPageAccess = response.data?.pageAccess || []; - console.log(`👤 사용자 ${userId} 페이지 권한 로드:`, userPageAccess.length, '개'); } catch (error) { - console.error('❌ 사용자 페이지 권한 로드 오류:', error); + console.error(' 사용자 페이지 권한 로드 오류:', error); userPageAccess = []; } } @@ -595,15 +588,13 @@ async function savePageAccess(userId, containerId = null) { const pageAccessData = Array.from(pageAccessMap.values()); - console.log('📤 페이지 권한 저장:', userId, pageAccessData); await apiCall(`/users/${userId}/page-access`, 'PUT', { pageAccess: pageAccessData }); - console.log('✅ 페이지 권한 저장 완료'); } catch (error) { - console.error('❌ 페이지 권한 저장 오류:', error); + console.error(' 페이지 권한 저장 오류:', error); throw error; } } @@ -647,7 +638,7 @@ async function managePageAccess(userId) { // 모달 표시 document.getElementById('pageAccessModal').style.display = 'flex'; } catch (error) { - console.error('❌ 페이지 권한 관리 모달 오류:', error); + console.error(' 페이지 권한 관리 모달 오류:', error); showToast('페이지 권한 관리를 열 수 없습니다.', 'error'); } } @@ -775,7 +766,7 @@ async function savePageAccessFromModal() { closePageAccessModal(); } catch (error) { - console.error('❌ 페이지 권한 저장 오류:', error); + console.error(' 페이지 권한 저장 오류:', error); showToast('페이지 권한 저장에 실패했습니다.', 'error'); } } diff --git a/system1-factory/web/js/api-base.js b/system1-factory/web/js/api-base.js index 8c1299d..322ec5a 100644 --- a/system1-factory/web/js/api-base.js +++ b/system1-factory/web/js/api-base.js @@ -35,7 +35,7 @@ if ('caches' in window) { * sso_token이 없으면 기존 token도 확인 (하위 호환) */ window.getSSOToken = function() { - return cookieGet('sso_token') || localStorage.getItem('sso_token') || localStorage.getItem('token'); + return cookieGet('sso_token') || localStorage.getItem('sso_token'); }; /** @@ -43,10 +43,6 @@ if ('caches' in window) { */ window.getSSOUser = function() { var raw = cookieGet('sso_user') || localStorage.getItem('sso_user'); - if (!raw) { - // 기존 user 키도 확인 (하위 호환) - raw = localStorage.getItem('user'); - } try { return raw ? JSON.parse(raw) : null; } catch(e) { return null; } }; @@ -69,13 +65,9 @@ if ('caches' in window) { cookieRemove('sso_token'); cookieRemove('sso_user'); cookieRemove('sso_refresh_token'); - localStorage.removeItem('sso_token'); - localStorage.removeItem('sso_user'); - localStorage.removeItem('sso_refresh_token'); - // 기존 키도 삭제 (하위 호환) - localStorage.removeItem('token'); - localStorage.removeItem('user'); - localStorage.removeItem('userPageAccess'); + ['sso_token','sso_user','sso_refresh_token','token','user','access_token','currentUser','current_user','userInfo','userPageAccess'].forEach(function(k) { + localStorage.removeItem(k); + }); }; // ==================== 보안 유틸리티 (XSS 방지) ==================== diff --git a/system1-factory/web/js/api-config.js b/system1-factory/web/js/api-config.js index e2cbc56..7f0675a 100644 --- a/system1-factory/web/js/api-config.js +++ b/system1-factory/web/js/api-config.js @@ -7,12 +7,10 @@ function getApiBaseUrl() { const protocol = window.location.protocol; const port = window.location.port; - console.log('🌐 감지된 환경:', { hostname, protocol, port }); // 🔗 외부 도메인 (Cloudflare Tunnel) - Gateway nginx가 /api/를 프록시 if (hostname.includes('technicalkorea.net')) { const baseUrl = `${protocol}//${hostname}${config.api.path}`; - console.log('✅ Gateway 프록시 사용:', baseUrl); return baseUrl; } @@ -21,27 +19,24 @@ function getApiBaseUrl() { hostname === 'localhost' || hostname === '127.0.0.1' || hostname.includes('.local') || hostname.includes('hyungi')) { const baseUrl = `${protocol}//${hostname}:${config.api.port}${config.api.path}`; - console.log('✅ 로컬 직접 접근:', baseUrl); return baseUrl; } // 🚨 기타: 포트 없이 상대 경로 const baseUrl = `${protocol}//${hostname}${config.api.path}`; - console.log('✅ 기본 프록시 사용:', baseUrl); return baseUrl; } // API 설정 const API_URL = getApiBaseUrl(); -// 전역 변수로 설정 -window.API = API_URL; -window.API_BASE_URL = API_URL; +// 전역 변수로 설정 (api-base.js가 이미 설정한 경우 유지) +if (!window.API) window.API = API_URL; +if (!window.API_BASE_URL) window.API_BASE_URL = API_URL; function ensureAuthenticated() { const token = localStorage.getItem('sso_token'); if (!token || token === 'undefined' || token === 'null') { - console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); clearAuthData(); // 만약을 위해 한번 더 정리 redirectToLogin(); return false; // 이후 코드 실행 방지 @@ -49,7 +44,6 @@ function ensureAuthenticated() { // 토큰 만료 확인 if (isTokenExpired(token)) { - console.log('🚨 토큰이 만료되었습니다. 로그인 페이지로 이동합니다.'); clearAuthData(); alert('세션이 만료되었습니다. 다시 로그인해주세요.'); redirectToLogin(); @@ -75,8 +69,6 @@ function isTokenExpired(token) { function clearAuthData() { localStorage.removeItem('sso_token'); localStorage.removeItem('sso_user'); - localStorage.removeItem('userInfo'); - localStorage.removeItem('currentUser'); // SSO 쿠키도 삭제 (로그인 페이지 자동 리다이렉트 방지) var cookieDomain = window.location.hostname.includes('technicalkorea.net') ? '; domain=.technicalkorea.net' : ''; @@ -112,12 +104,10 @@ async function apiCall(url, method = 'GET', data = null) { } try { - console.log(`📡 API 호출: ${fullUrl} (${method})`); const response = await fetch(fullUrl, options); // 인증 만료 처리 if (response.status === 401) { - console.error('🚨 인증 실패: 토큰이 만료되었거나 유효하지 않습니다.'); clearAuthData(); alert('세션이 만료되었습니다. 다시 로그인해주세요.'); redirectToLogin(); @@ -132,8 +122,7 @@ async function apiCall(url, method = 'GET', data = null) { if (contentType && contentType.includes('application/json')) { const errorData = await response.json(); - console.error('📋 서버 에러 상세:', errorData); - + // 에러 메시지 추출 (여러 형식 지원) if (typeof errorData === 'string') { errorMessage = errorData; @@ -150,23 +139,18 @@ async function apiCall(url, method = 'GET', data = null) { } } else { const errorText = await response.text(); - console.error('📋 서버 에러 텍스트:', errorText); - errorMessage = errorText || errorMessage; + errorMessage = errorText || errorMessage; } } catch (e) { - console.error('📋 에러 파싱 중 예외 발생:', e.message); // 파싱 실패해도 HTTP 상태 코드는 전달 } throw new Error(errorMessage); } const result = await response.json(); - console.log(`✅ API 성공: ${fullUrl}`); return result; } catch (error) { - console.error(`❌ API 오류 (${fullUrl}):`, error); - console.error('❌ 에러 전체 내용:', JSON.stringify(error, null, 2)); // 네트워크 오류 vs 서버 오류 구분 if (error.name === 'TypeError' && error.message.includes('fetch')) { @@ -177,36 +161,6 @@ async function apiCall(url, method = 'GET', data = null) { } } -// 디버깅 정보 -console.log('🔗 API Base URL:', API); -console.log('🌐 Current Location:', { - hostname: window.location.hostname, - protocol: window.location.protocol, - port: window.location.port, - href: window.location.href -}); - -// 🧪 API 연결 테스트 함수 (개발용) -async function testApiConnection() { - try { - console.log('🧪 API 연결 테스트 시작...'); - const response = await fetch(`${API}/health`, { - method: 'GET', - headers: { 'Content-Type': 'application/json' } - }); - - if (response.ok) { - console.log('✅ API 연결 성공!'); - return true; - } else { - console.log('❌ API 연결 실패:', response.status); - return false; - } - } catch (error) { - console.log('❌ API 연결 오류:', error.message); - return false; - } -} // API 헬퍼 함수들 async function apiGet(url) { @@ -225,35 +179,26 @@ async function apiDelete(url) { return apiCall(url, 'DELETE'); } -// 전역 함수로 설정 +// 전역 함수로 설정 (api-base.js가 이미 등록한 것은 덮어쓰지 않음) window.ensureAuthenticated = ensureAuthenticated; -window.getAuthHeaders = getAuthHeaders; -window.apiCall = apiCall; +if (!window.getAuthHeaders) window.getAuthHeaders = getAuthHeaders; +if (!window.apiCall) window.apiCall = apiCall; window.apiGet = apiGet; window.apiPost = apiPost; window.apiPut = apiPut; window.apiDelete = apiDelete; -window.testApiConnection = testApiConnection; window.isTokenExpired = isTokenExpired; -window.clearAuthData = clearAuthData; - -// 개발 모드에서 자동 테스트 -if (window.location.hostname === 'localhost' || window.location.hostname.startsWith('192.168.')) { - setTimeout(() => { - testApiConnection(); - }, 1000); -} +if (!window.clearAuthData) window.clearAuthData = clearAuthData; // 주기적으로 토큰 만료 확인 (5분마다) setInterval(() => { const token = localStorage.getItem('sso_token'); if (token && isTokenExpired(token)) { - console.log('🚨 주기적 확인: 토큰이 만료되었습니다.'); clearAuthData(); alert('세션이 만료되었습니다. 다시 로그인해주세요.'); redirectToLogin(); } -}, config.app.tokenRefreshInterval); // 5분마다 확인 +}, config.app.tokenRefreshInterval); // ES6 모듈 export export { API_URL as API_BASE_URL, API_URL as API, apiCall, getAuthHeaders }; \ No newline at end of file diff --git a/system1-factory/web/js/api-helper.js b/system1-factory/web/js/api-helper.js index 3987901..b5acf6f 100644 --- a/system1-factory/web/js/api-helper.js +++ b/system1-factory/web/js/api-helper.js @@ -8,7 +8,7 @@ const API_BASE_URL = window.API_BASE_URL || 'http://localhost:30005/api'; function getToken() { // SSO 토큰 우선, 기존 token 폴백 if (window.getSSOToken) return window.getSSOToken(); - const token = localStorage.getItem('sso_token') || localStorage.getItem('token'); + const token = localStorage.getItem('sso_token'); return token && token !== 'undefined' && token !== 'null' ? token : null; } @@ -16,8 +16,6 @@ function clearAuthData() { if (window.clearSSOAuth) { window.clearSSOAuth(); return; } localStorage.removeItem('sso_token'); localStorage.removeItem('sso_user'); - localStorage.removeItem('token'); - localStorage.removeItem('user'); } /** diff --git a/system1-factory/web/js/app-init.js b/system1-factory/web/js/app-init.js index f07c54a..caf7b6f 100644 --- a/system1-factory/web/js/app-init.js +++ b/system1-factory/web/js/app-init.js @@ -12,26 +12,24 @@ // ===== 인증 함수 (api-base.js의 SSO 함수 활용) ===== function isLoggedIn() { - const token = window.getSSOToken ? window.getSSOToken() : (localStorage.getItem('sso_token') || localStorage.getItem('token')); + const token = window.getSSOToken ? window.getSSOToken() : localStorage.getItem('sso_token'); return token && token !== 'undefined' && token !== 'null'; } function getUser() { if (window.getSSOUser) return window.getSSOUser(); - const user = localStorage.getItem('sso_user') || localStorage.getItem('user'); + const user = localStorage.getItem('sso_user'); try { return user ? JSON.parse(user) : null; } catch(e) { return null; } } function getToken() { - return window.getSSOToken ? window.getSSOToken() : (localStorage.getItem('sso_token') || localStorage.getItem('token')); + return window.getSSOToken ? window.getSSOToken() : localStorage.getItem('sso_token'); } function clearAuthData() { if (window.clearSSOAuth) { window.clearSSOAuth(); return; } localStorage.removeItem('sso_token'); localStorage.removeItem('sso_user'); - localStorage.removeItem('token'); - localStorage.removeItem('user'); localStorage.removeItem('userPageAccess'); } diff --git a/system1-factory/web/js/attendance-validation.js b/system1-factory/web/js/attendance-validation.js index b9f5244..076b753 100644 --- a/system1-factory/web/js/attendance-validation.js +++ b/system1-factory/web/js/attendance-validation.js @@ -50,7 +50,6 @@ function getCacheStatus() { */ function clearCache() { dateStatusCache.clear(); - console.log('📦 캐시가 클리어되었습니다.'); } /** @@ -77,7 +76,6 @@ function updatePerformanceUI() { */ function logPerformanceStatus() { const status = getCacheStatus(); - console.log('📊 성능 상태:', status); updatePerformanceUI(); } @@ -118,7 +116,7 @@ function getCurrentUser() { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { return JSON.parse(userInfo); } @@ -391,18 +389,14 @@ async function calculateDateStatus(dateStr) { } try { - console.log(`📊 ${dateStr} 상태 계산 시작 - 순차 호출`); // 1단계: WorkReports 먼저 가져오기 - console.log(`📝 1단계: WorkReports 조회 중...`); const workReports = await fetchWorkReports(dateStr); // 2초 대기 (서버 부하 방지) - console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); await new Promise(resolve => setTimeout(resolve, 2000)); // 2단계: DailyWorkReports 가져오기 - console.log(`📊 2단계: DailyWorkReports 조회 중...`); const dailyReports = await fetchDailyWorkReports(dateStr); let status; @@ -423,7 +417,6 @@ async function calculateDateStatus(dateStr) { // 캐시에 저장 dateStatusCache.set(dateStr, status); - console.log(`✅ ${dateStr} 상태 계산 완료: ${status}`); return status; } catch (error) { console.error('날짜 상태 계산 오류:', error); @@ -564,10 +557,9 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) { }`; } - console.log(`✅ ${dateStr} 상태 로드 완료: ${status}`); } catch (error) { - console.error(`❌ ${dateStr} 상태 로드 실패:`, error); + console.error(` ${dateStr} 상태 로드 실패:`, error); buttonElement.classList.remove('loading-state'); buttonElement.classList.add('error-state'); buttonElement.title = `${dateStr} - 로드 실패: ${error.message}`; @@ -589,18 +581,14 @@ async function loadAndUpdateDateStatus(dateStr, buttonElement) { */ async function getWorkersForDate(dateStr) { try { - console.log(`👥 ${dateStr} 작업자 데이터 조합 시작 - 순차 호출`); // 1단계: WorkReports 먼저 가져오기 - console.log(`📝 1단계: WorkReports 조회 중...`); const workReports = await fetchWorkReports(dateStr); // 2초 대기 (서버 부하 방지) - console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); await new Promise(resolve => setTimeout(resolve, 2000)); // 2단계: DailyWorkReports 가져오기 - console.log(`📊 2단계: DailyWorkReports 조회 중...`); const dailyReports = await fetchDailyWorkReports(dateStr); const workerMap = new Map(); @@ -645,7 +633,6 @@ async function getWorkersForDate(dateStr) { validationStatus: getValidationStatus(worker) })); - console.log(`✅ ${dateStr} 작업자 데이터 조합 완료: ${result.length}명`); return result; } catch (error) { @@ -1022,11 +1009,6 @@ async function init() { window.saveEditedWork = saveEditedWork; window.deleteWorker = deleteWorker; - console.log('✅ 근태 검증 관리 시스템 초기화 완료 (API 통합)'); - console.log(`🔗 API 경로: ${API}`); - console.log(`📊 설정: 동시 최대 ${RATE_LIMIT.maxConcurrent}개 요청, ${RATE_LIMIT.delayBetweenRequests}ms 딜레이`); - console.log('🔄 API 호출 방식: 통합 설정 + 순차 호출'); - console.log('🚫 429 에러 방지: 각 날짜당 최소 5초 간격'); } catch (error) { console.error('초기화 오류:', error); diff --git a/system1-factory/web/js/auth-check.js b/system1-factory/web/js/auth-check.js index 85b64b0..939c9d0 100644 --- a/system1-factory/web/js/auth-check.js +++ b/system1-factory/web/js/auth-check.js @@ -123,7 +123,6 @@ async function checkPageAccess(pageKey) { // 즉시 실행 함수로 스코프를 보호하고 로직을 실행 (async function() { if (!isLoggedIn()) { - console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); clearAuthData(); // 만약을 위해 한번 더 정리 window.location.href = window.getLoginUrl ? window.getLoginUrl() : '/login'; return; // 이후 코드 실행 방지 @@ -133,31 +132,28 @@ async function checkPageAccess(pageKey) { // 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우) if (!currentUser || !currentUser.username) { - console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); + console.error(' 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); clearAuthData(); window.location.href = window.getLoginUrl ? window.getLoginUrl() : '/login'; return; } const userRole = currentUser.role || currentUser.access_level || '사용자'; - console.log(`✅ ${currentUser.username}(${userRole})님 인증 성공.`); // 페이지 접근 권한 체크 (Admin은 건너뛰기) if (currentUser.role !== 'Admin' && currentUser.role !== 'System Admin') { const pageKey = getCurrentPageKey(); if (pageKey) { - console.log(`🔍 페이지 권한 체크: ${pageKey}`); const hasAccess = await checkPageAccess(pageKey); if (!hasAccess) { - console.error(`🚫 페이지 접근 권한이 없습니다: ${pageKey}`); + console.error(` 페이지 접근 권한이 없습니다: ${pageKey}`); alert('이 페이지에 접근할 권한이 없습니다.'); window.location.href = '/pages/dashboard.html'; return; } - console.log(`✅ 페이지 접근 권한 확인됨: ${pageKey}`); } } diff --git a/system1-factory/web/js/auth.js b/system1-factory/web/js/auth.js index 45cb9fa..e6d3a3e 100644 --- a/system1-factory/web/js/auth.js +++ b/system1-factory/web/js/auth.js @@ -19,7 +19,7 @@ export function parseJwt(token) { */ export function getToken() { if (window.getSSOToken) return window.getSSOToken(); - return localStorage.getItem('sso_token') || localStorage.getItem('token'); + return localStorage.getItem('sso_token'); } /** @@ -27,7 +27,7 @@ export function getToken() { */ export function getUser() { if (window.getSSOUser) return window.getSSOUser(); - const raw = localStorage.getItem('sso_user') || localStorage.getItem('user'); + const raw = localStorage.getItem('sso_user'); try { return raw ? JSON.parse(raw) : null; } catch(e) { @@ -37,16 +37,11 @@ export function getUser() { /** * 로그인 성공 후 토큰과 사용자 정보를 저장합니다. - * 하위 호환성을 위해 sso_token/sso_user와 token/user 모두에 저장합니다. + * sso_token/sso_user 키로 저장합니다. */ export function saveAuthData(token, user) { - const userStr = JSON.stringify(user); - // SSO 키 localStorage.setItem('sso_token', token); - localStorage.setItem('sso_user', userStr); - // 하위 호환 키 (캐시된 구버전 app-init.js 대응) - localStorage.setItem('token', token); - localStorage.setItem('user', userStr); + localStorage.setItem('sso_user', JSON.stringify(user)); } /** @@ -56,8 +51,6 @@ export function clearAuthData() { if (window.clearSSOAuth) { window.clearSSOAuth(); return; } localStorage.removeItem('sso_token'); localStorage.removeItem('sso_user'); - localStorage.removeItem('token'); - localStorage.removeItem('user'); localStorage.removeItem('userPageAccess'); } diff --git a/system1-factory/web/js/change-password.js b/system1-factory/web/js/change-password.js index 8bb6c8e..2888c73 100644 --- a/system1-factory/web/js/change-password.js +++ b/system1-factory/web/js/change-password.js @@ -205,6 +205,4 @@ form?.addEventListener('submit', async (e) => { // 페이지 로드 시 현재 사용자 정보 표시 document.addEventListener('DOMContentLoaded', () => { const user = JSON.parse(localStorage.getItem('sso_user') || '{}'); - console.log('🔐 비밀번호 변경 페이지 로드됨'); - console.log('👤 현재 사용자:', user.username || 'Unknown'); }); \ No newline at end of file diff --git a/system1-factory/web/js/component-loader.js b/system1-factory/web/js/component-loader.js index 97eca11..6d63146 100644 --- a/system1-factory/web/js/component-loader.js +++ b/system1-factory/web/js/component-loader.js @@ -43,14 +43,14 @@ async function getComponentHtml(componentName, componentPath) { export async function loadComponent(componentName, containerSelector, domProcessor = null) { const container = document.querySelector(containerSelector); if (!container) { - console.warn(`⚠️ 컴포넌트를 삽입할 컨테이너를 찾을 수 없습니다: ${containerSelector} (선택사항일 수 있음)`); + console.warn(` 컴포넌트를 삽입할 컨테이너를 찾을 수 없습니다: ${containerSelector} (선택사항일 수 있음)`); return; } const componentPath = config.components[componentName]; if (!componentPath) { - console.error(`🔴 설정 파일(config.js)에서 '${componentName}' 컴포넌트의 경로를 찾을 수 없습니다.`); - container.innerHTML = `

${componentName} 로딩 실패

`; + console.error(` 설정 파일(config.js)에서 '${componentName}' 컴포넌트의 경로를 찾을 수 없습니다.`); + container.textContent = `${componentName} 로딩 실패`; return; } @@ -72,10 +72,9 @@ export async function loadComponent(componentName, containerSelector, domProcess container.innerHTML = htmlText; } - console.log(`✅ '${componentName}' 컴포넌트 로딩 완료: ${containerSelector}`); } catch (error) { - console.error(`🔴 '${componentName}' 컴포넌트 로딩 실패:`, error); - container.innerHTML = `

${componentName} 로딩에 실패했습니다. 관리자에게 문의하세요.

`; + console.error(` '${componentName}' 컴포넌트 로딩 실패:`, error); + container.textContent = `${componentName} 로딩에 실패했습니다. 관리자에게 문의하세요.`; } } \ No newline at end of file diff --git a/system1-factory/web/js/daily-work-report.js b/system1-factory/web/js/daily-work-report.js index f7e7f14..bb0f8b8 100644 --- a/system1-factory/web/js/daily-work-report.js +++ b/system1-factory/web/js/daily-work-report.js @@ -1,7 +1,7 @@ // daily-work-report.js - 브라우저 호환 버전 // ================================================================= -// 🌐 API 설정 (window 객체에서 가져오기) +// API 설정 (window 객체에서 가져오기) // ================================================================= // API 설정은 api-config.js에서 window 객체에 설정됨 @@ -183,7 +183,7 @@ function formatDateForApi(date) { */ function getUser() { if (window.getSSOUser) return window.getSSOUser(); - const raw = localStorage.getItem('sso_user') || localStorage.getItem('user'); + const raw = localStorage.getItem('sso_user'); try { return raw ? JSON.parse(raw) : null; } catch(e) { return null; } } @@ -233,7 +233,7 @@ function renderTbmWorkList() {

작업보고서 목록

`; @@ -247,7 +247,7 @@ function renderTbmWorkList() { TBM에 없는 작업을 추가로 입력할 수 있습니다
@@ -326,7 +326,7 @@ function renderTbmWorkList() { html += `
- ⚠️ + 당일 신고된 문제 ${relatedIssues.length}건
@@ -349,7 +349,7 @@ function renderTbmWorkList() { ${relatedIssues.length > 5 ? `
외 ${relatedIssues.length - 5}건 더 있음
` : ''}
- 💡 위 문제로 인해 작업이 지연되었다면, 아래에서 부적합 시간을 추가해주세요. + 위 문제로 인해 작업이 지연되었다면, 아래에서 부적합 시간을 추가해주세요.
`; @@ -474,7 +474,7 @@ function renderTbmWorkList() { @@ -572,7 +572,7 @@ window.submitTbmWorkReport = async function(index) { } // 부적합 원인 유효성 검사 (issue_report_id 또는 category_id 또는 error_type_id 필요) - console.log('🔍 부적합 검증 시작:', defects.map(d => ({ + console.log(' 부적합 검증 시작:', defects.map(d => ({ defect_hours: d.defect_hours, category_id: d.category_id, item_id: d.item_id, @@ -583,7 +583,7 @@ window.submitTbmWorkReport = async function(index) { const invalidDefects = defects.filter(d => d.defect_hours > 0 && !d.error_type_id && !d.issue_report_id && !d.category_id && !d.item_id); if (invalidDefects.length > 0) { - console.error('❌ 유효하지 않은 부적합:', invalidDefects); + console.error(' 유효하지 않은 부적합:', invalidDefects); showMessage('부적합 시간이 있는 항목은 원인을 선택해주세요.', 'error'); return; } @@ -610,8 +610,6 @@ window.submitTbmWorkReport = async function(index) { work_status_id: errorHours > 0 ? 2 : 1 }; - console.log('🔍 TBM 제출 데이터:', JSON.stringify(reportData, null, 2)); - console.log('🔍 부적합 원인:', defects); try { const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', reportData); @@ -623,7 +621,7 @@ window.submitTbmWorkReport = async function(index) { // 부적합 원인이 있으면 저장 (이슈 기반 또는 레거시) if (defects.length > 0 && response.data?.report_id) { const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0); - console.log('📋 부적합 원인 필터링:', { + console.log(' 부적합 원인 필터링:', { 전체: defects.length, 유효: validDefects.length, validDefects: validDefects.map(d => ({ @@ -645,20 +643,17 @@ window.submitTbmWorkReport = async function(index) { note: d.note || '' })); - console.log('📤 부적합 저장 요청:', defectsToSend); const defectResponse = await window.apiCall(`/daily-work-reports/${response.data.report_id}/defects`, 'PUT', { defects: defectsToSend }); if (!defectResponse.success) { - console.error('❌ 부적합 저장 실패:', defectResponse); + console.error(' 부적합 저장 실패:', defectResponse); showMessage('작업보고서는 저장되었으나 부적합 원인 저장에 실패했습니다.', 'warning'); } else { - console.log('✅ 부적합 저장 성공:', defectResponse); } } else { - console.log('⚠️ 유효한 부적합 항목이 없어 저장 건너뜀'); } } @@ -808,7 +803,7 @@ window.batchSubmitTbmSession = async function(sessionKey) { 'success', '일괄제출 완료', `${totalCount}건의 작업보고서가 모두 성공적으로 제출되었습니다.`, - results.success.map(name => `✓ ${name}`) + results.success.map(name => ` ${name}`) ); } else if (successCount === 0) { // 모두 실패 @@ -816,13 +811,13 @@ window.batchSubmitTbmSession = async function(sessionKey) { 'error', '일괄제출 실패', `${totalCount}건의 작업보고서가 모두 실패했습니다.`, - results.failed.map(msg => `✗ ${msg}`) + results.failed.map(msg => ` ${msg}`) ); } else { // 일부 성공, 일부 실패 const details = [ - ...results.success.map(name => `✓ ${name} - 성공`), - ...results.failed.map(msg => `✗ ${msg}`) + ...results.success.map(name => ` ${name} - 성공`), + ...results.failed.map(msg => ` ${msg}`) ]; showSaveResultModal( 'warning', @@ -840,7 +835,7 @@ window.batchSubmitTbmSession = async function(sessionKey) { } finally { submitBtn.classList.remove('is-loading'); submitBtn.disabled = false; - submitBtn.textContent = `📤 이 세션 일괄제출 (${sessionRows.length}건)`; + submitBtn.textContent = ` 이 세션 일괄제출 (${sessionRows.length}건)`; } }; @@ -892,7 +887,7 @@ window.addManualWorkRow = function() {
- 🗺️ + 작업장소
@@ -923,7 +918,7 @@ window.addManualWorkRow = function() { 제출 `; @@ -1049,13 +1044,13 @@ window.openWorkplaceMapForManual = async function(manualIndex) { const safeImage = escapeHtml(cat.layout_image || ''); return ` `; }).join('') + ` `; @@ -1107,7 +1102,7 @@ window.selectWorkplaceCategory = async function(categoryId, categoryName, layout const safeName = escapeHtml(wp.workplace_name); return ` `; @@ -1136,7 +1131,6 @@ async function loadWorkplaceMap(categoryId, layoutImagePath, workplaces) { ? layoutImagePath : `${apiBaseUrl}${layoutImagePath}`; - console.log('🖼️ 이미지 로드 시도:', fullImageUrl); // 지도 영역 데이터 로드 const regionsResponse = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`); @@ -1164,11 +1158,10 @@ async function loadWorkplaceMap(categoryId, layoutImagePath, workplaces) { // 클릭 이벤트 리스너 추가 mapCanvas.onclick = handleMapClick; - console.log(`✅ 작업장 지도 로드 완료: ${mapRegions.length}개 영역`); }; mapImage.onerror = function() { - console.error('❌ 지도 이미지 로드 실패'); + console.error(' 지도 이미지 로드 실패'); document.getElementById('layoutMapArea').style.display = 'none'; showMessage('지도를 불러올 수 없어 리스트로 표시합니다.', 'warning'); }; @@ -1176,7 +1169,7 @@ async function loadWorkplaceMap(categoryId, layoutImagePath, workplaces) { mapImage.src = fullImageUrl; } catch (error) { - console.error('❌ 작업장 지도 로드 오류:', error); + console.error(' 작업장 지도 로드 오류:', error); document.getElementById('layoutMapArea').style.display = 'none'; } } @@ -1301,12 +1294,12 @@ window.confirmWorkplaceSelection = function() { if (displayDiv) { displayDiv.innerHTML = `
- + 작업장소 선택됨
-
🏭 ${escapeHtml(selectedWorkplaceCategoryName)}
-
📍 ${escapeHtml(selectedWorkplaceName)}
+
${escapeHtml(selectedWorkplaceCategoryName)}
+
${escapeHtml(selectedWorkplaceName)}
`; displayDiv.style.background = '#ecfdf5'; @@ -1354,11 +1347,11 @@ window.selectExternalWorkplace = function() { if (displayDiv) { displayDiv.innerHTML = `
- + 외부 선택됨
-
🌐 ${escapeHtml(externalWorkplaceName)}
+
${escapeHtml(externalWorkplaceName)}
`; displayDiv.style.background = '#f0f9ff'; @@ -1778,10 +1771,10 @@ function renderCompletedReports(reports) {
@@ -1997,7 +1990,7 @@ function getCurrentUser() { } try { - const token = window.getSSOToken ? window.getSSOToken() : (localStorage.getItem('sso_token') || localStorage.getItem('token')); + const token = window.getSSOToken ? window.getSSOToken() : (localStorage.getItem('sso_token')); if (token) { const payloadBase64 = token.split('.')[1]; if (payloadBase64) { @@ -2009,7 +2002,7 @@ function getCurrentUser() { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('user') || localStorage.getItem('userInfo'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) return JSON.parse(userInfo); } catch (error) { console.log('localStorage에서 사용자 정보 가져오기 실패:', error); @@ -2044,16 +2037,16 @@ function showSaveResultModal(type, title, message, details = null) { let icon = ''; switch (type) { case 'success': - icon = '✅'; + icon = ''; break; case 'error': - icon = '❌'; + icon = ''; break; case 'warning': - icon = '⚠️'; + icon = ''; break; default: - icon = 'ℹ️'; + icon = 'ℹ'; } // 모달 내용 구성 @@ -2157,7 +2150,6 @@ async function loadData() { try { showMessage('데이터를 불러오는 중...', 'loading'); - console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩 시작...'); await loadWorkers(); await loadProjects(); await loadWorkTypes(); @@ -2190,8 +2182,6 @@ async function loadWorkers() { return notResigned; }); - console.log(`✅ Workers 로드 성공: ${workers.length}명 (전체: ${allWorkers.length}명)`); - console.log(`📊 필터링 조건: employment_status≠resigned (퇴사자만 제외)`); } catch (error) { console.error('작업자 로딩 오류:', error); throw error; @@ -2203,7 +2193,6 @@ async function loadProjects() { console.log('Projects API 호출 중... (활성 프로젝트만)'); const data = await window.apiCall(`/projects/active/list`); projects = Array.isArray(data) ? data : (data.data || data.projects || []); - console.log('✅ 활성 프로젝트 로드 성공:', projects.length); } catch (error) { console.error('프로젝트 로딩 오류:', error); throw error; @@ -2216,12 +2205,10 @@ async function loadWorkTypes() { const data = response.data || response; if (Array.isArray(data) && data.length > 0) { workTypes = data; - console.log('✅ 작업 유형 API 사용 (통합 설정):', workTypes.length + '개'); return; } throw new Error('API 실패'); } catch (error) { - console.log('⚠️ 작업 유형 API 사용 불가, 기본값 사용:', error.message); workTypes = [ { id: 1, name: 'Base' }, { id: 2, name: 'Vessel' }, @@ -2236,12 +2223,10 @@ async function loadWorkStatusTypes() { const data = response.data || response; if (Array.isArray(data) && data.length > 0) { workStatusTypes = data; - console.log('✅ 업무 상태 유형 API 사용 (통합 설정):', workStatusTypes.length + '개'); return; } throw new Error('API 실패'); } catch (error) { - console.log('⚠️ 업무 상태 유형 API 사용 불가, 기본값 사용'); workStatusTypes = [ { id: 1, name: '정규' }, { id: 2, name: '에러' } @@ -2266,7 +2251,6 @@ async function loadErrorTypes() { const catResponse = await window.apiCall('/work-issues/categories/type/nonconformity'); if (catResponse && catResponse.success && Array.isArray(catResponse.data)) { issueCategories = catResponse.data; - console.log(`✅ 부적합 카테고리 ${issueCategories.length}개 로드`); // 모든 아이템 로드 const itemResponse = await window.apiCall('/work-issues/items'); @@ -2274,11 +2258,9 @@ async function loadErrorTypes() { // 부적합 카테고리의 아이템만 필터링 const categoryIds = issueCategories.map(c => c.category_id); issueItems = itemResponse.data.filter(item => categoryIds.includes(item.category_id)); - console.log(`✅ 부적합 아이템 ${issueItems.length}개 로드`); } } } catch (error) { - console.log('⚠️ 신고 카테고리 로드 실패:', error); issueCategories = []; issueItems = []; } @@ -2287,7 +2269,6 @@ async function loadErrorTypes() { // TBM 팀 구성 자동 불러오기 async function loadTbmTeamForDate(date) { try { - console.log('🛠️ TBM 팀 구성 조회 중:', date); const response = await window.apiCall(`/tbm/sessions/date/${date}`); if (response && response.success && response.data && response.data.length > 0) { @@ -2300,16 +2281,14 @@ async function loadTbmTeamForDate(date) { const teamRes = await window.apiCall(`/tbm/sessions/${targetSession.session_id}/team`); if (teamRes && teamRes.success && teamRes.data) { const teamWorkerIds = teamRes.data.map(m => m.user_id); - console.log(`✅ TBM 팀 구성 로드 성공: ${teamWorkerIds.length}명`); return teamWorkerIds; } } } - console.log('ℹ️ 해당 날짜의 TBM 팀 구성이 없습니다.'); return []; } catch (error) { - console.error('❌ TBM 팀 구성 조회 오류:', error); + console.error(' TBM 팀 구성 조회 오류:', error); return []; } } @@ -2340,7 +2319,7 @@ async function populateWorkerGrid() { font-size: 0.875rem; `; infoDiv.innerHTML = ` - 🛠️ TBM 팀 구성 자동 적용
+ TBM 팀 구성 자동 적용
오늘 TBM에서 구성된 팀원 ${tbmWorkerIds.length}명이 자동으로 선택되었습니다. `; grid.appendChild(infoDiv); @@ -2389,29 +2368,25 @@ function toggleWorkerSelection(workerId, btnElement) { // 작업 항목 추가 function addWorkEntry() { - console.log('🔧 addWorkEntry 함수 호출됨'); const container = document.getElementById('workEntriesList'); - console.log('🔧 컨테이너:', container); workEntryCounter++; - console.log('🔧 작업 항목 카운터:', workEntryCounter); const entryDiv = document.createElement('div'); entryDiv.className = 'work-entry'; entryDiv.dataset.id = workEntryCounter; - console.log('🔧 생성된 작업 항목 div:', entryDiv); entryDiv.innerHTML = `
작업 항목 #${workEntryCounter}
- 🏗️ + 프로젝트
@@ -2435,7 +2410,7 @@ function addWorkEntry() {
- 📊 + 업무 상태
@@ -2458,7 +2433,7 @@ function addWorkEntry() {
- + 작업 시간 (시간)
24) { display.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)'; - display.textContent += ' ⚠️ 24시간 초과'; + display.textContent += '24시간 초과'; } else { display.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; } @@ -2593,8 +2560,6 @@ async function saveWorkReport() { } const entries = document.querySelectorAll('.work-entry'); - console.log('🔍 찾은 작업 항목들:', entries); - console.log('🔍 작업 항목 개수:', entries.length); if (entries.length === 0) { showSaveResultModal( @@ -2606,10 +2571,8 @@ async function saveWorkReport() { } const newWorkEntries = []; - console.log('🔍 작업 항목 수집 시작...'); for (const entry of entries) { - console.log('🔍 작업 항목 처리 중:', entry); const projectSelect = entry.querySelector('.project-select'); const workTypeSelect = entry.querySelector('.work-type-select'); @@ -2617,7 +2580,7 @@ async function saveWorkReport() { const errorTypeSelect = entry.querySelector('.error-type-select'); const timeInput = entry.querySelector('.time-input'); - console.log('🔍 선택된 요소들:', { + console.log(' 선택된 요소들:', { projectSelect, workTypeSelect, workStatusSelect, @@ -2631,7 +2594,7 @@ async function saveWorkReport() { const errorTypeId = errorTypeSelect?.value; const workHours = timeInput?.value; - console.log('🔍 수집된 값들:', { + console.log(' 수집된 값들:', { projectId, workTypeId, workStatusId, @@ -2665,8 +2628,7 @@ async function saveWorkReport() { work_hours: parseFloat(workHours) }; - console.log('🔍 생성된 작업 항목:', workEntry); - console.log('🔍 작업 항목 상세:', { + console.log(' 작업 항목 상세:', { project_id: workEntry.project_id, work_type_id: workEntry.work_type_id, work_status_id: workEntry.work_status_id, @@ -2676,13 +2638,11 @@ async function saveWorkReport() { newWorkEntries.push(workEntry); } - console.log('🔍 최종 수집된 작업 항목들:', newWorkEntries); - console.log('🔍 총 작업 항목 개수:', newWorkEntries.length); try { const submitBtn = document.getElementById('submitBtn'); submitBtn.disabled = true; - submitBtn.textContent = '💾 저장 중...'; + submitBtn.textContent = ' 저장 중...'; const currentUser = getCurrentUser(); let totalSaved = 0; @@ -2706,18 +2666,13 @@ async function saveWorkReport() { created_by: currentUser?.user_id || currentUser?.id }; - console.log('🔄 배열 형태로 전송:', requestData); - console.log('🔄 work_entries:', requestData.work_entries); - console.log('🔄 work_entries[0] 상세:', requestData.work_entries[0]); - console.log('🔄 전송 데이터 JSON:', JSON.stringify(requestData, null, 2)); try { const result = await window.apiCall(`/daily-work-reports`, 'POST', requestData); - console.log('✅ 저장 성공:', result); totalSaved++; } catch (error) { - console.error('❌ 저장 실패:', error); + console.error(' 저장 실패:', error); totalFailed++; failureDetails.push(`${workerName}: ${error.message}`); @@ -2765,7 +2720,7 @@ async function saveWorkReport() { } finally { const submitBtn = document.getElementById('submitBtn'); submitBtn.disabled = false; - submitBtn.textContent = '💾 작업보고서 저장'; + submitBtn.textContent = ' 작업보고서 저장'; } } @@ -2801,7 +2756,7 @@ async function loadTodayWorkers() { const today = getKoreaToday(); const currentUser = getCurrentUser(); - content.innerHTML = '
📊 내가 입력한 오늘의 작업 현황을 불러오는 중... (통합 API)
'; + content.innerHTML = '
내가 입력한 오늘의 작업 현황을 불러오는 중... (통합 API)
'; section.style.display = 'block'; // 본인이 입력한 데이터만 조회 (통합 API 사용) @@ -2812,10 +2767,8 @@ async function loadTodayWorkers() { queryParams += `&created_by=${currentUser.id}`; } - console.log(`🔒 본인 입력분만 조회 (통합 API): ${API}/daily-work-reports?${queryParams}`); const rawData = await window.apiCall(`/daily-work-reports?${queryParams}`); - console.log('📊 당일 작업 데이터 (통합 API):', rawData); let data = []; if (Array.isArray(rawData)) { @@ -2830,7 +2783,7 @@ async function loadTodayWorkers() { console.error('당일 작업자 로드 오류:', error); content.innerHTML = `
- ❌ 오늘의 작업 현황을 불러올 수 없습니다.
+ 오늘의 작업 현황을 불러올 수 없습니다.
${error.message}
`; @@ -2844,7 +2797,7 @@ function displayMyDailyWorkers(data, date) { if (!Array.isArray(data) || data.length === 0) { content.innerHTML = `
- 📝 내가 오늘(${date}) 입력한 작업이 없습니다.
+ 내가 오늘(${date}) 입력한 작업이 없습니다.
새로운 작업을 추가해보세요!
`; @@ -2866,9 +2819,9 @@ function displayMyDailyWorkers(data, date) { const headerHtml = `
-

📊 내가 입력한 오늘(${escapeHtml(date)}) 작업 현황 - 총 ${parseInt(totalWorkers) || 0}명, ${parseInt(totalWorks) || 0}개 작업

+

내가 입력한 오늘(${escapeHtml(date)}) 작업 현황 - 총 ${parseInt(totalWorkers) || 0}명, ${parseInt(totalWorks) || 0}개 작업

`; @@ -2891,34 +2844,34 @@ function displayMyDailyWorkers(data, date) {
-
🏗️ 프로젝트
+
프로젝트
${projectName}
-
⚙️ 작업종류
+
작업종류
${workTypeName}
-
📊 작업상태
+
작업상태
${workStatusName}
-
⏰ 작업시간
+
작업시간
${workHours}시간
${errorTypeName ? `
-
❌ 에러유형
+
에러유형
${errorTypeName}
` : ''}
@@ -2928,7 +2881,7 @@ function displayMyDailyWorkers(data, date) { return `
-
👤 ${escapeHtml(workerName)}
+
${escapeHtml(workerName)}
총 ${parseFloat(totalHours)}시간
@@ -2970,12 +2923,12 @@ function showEditModal(workData) {
-

✏️ 작업 수정

+

작업 수정

- + ${workTypes.map(wt => ` @@ -2999,7 +2952,7 @@ function showEditModal(workData) {
- + ${errorTypes.map(et => ` @@ -3023,7 +2976,7 @@ function showEditModal(workData) {
- + @@ -3031,7 +2984,7 @@ function showEditModal(workData) {
@@ -3093,14 +3046,13 @@ async function saveEditedWork() { body: JSON.stringify(updateData) }); - console.log('✅ 수정 성공 (통합 API):', result); - showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + showMessage(' 작업이 성공적으로 수정되었습니다!', 'success'); closeEditModal(); refreshTodayWorkers(); } catch (error) { - console.error('❌ 수정 실패:', error); + console.error(' 수정 실패:', error); showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -3121,14 +3073,13 @@ async function deleteWorkItem(workId) { method: 'DELETE' }); - console.log('✅ 삭제 성공 (통합 API):', result); - showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + showMessage(' 작업이 성공적으로 삭제되었습니다!', 'success'); // 화면 새로고침 refreshTodayWorkers(); } catch (error) { - console.error('❌ 삭제 실패:', error); + console.error(' 삭제 실패:', error); showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -3164,7 +3115,6 @@ async function init() { // TBM 작업 목록 로드 (기본 탭) await loadIncompleteTbms(); - console.log('✅ 시스템 초기화 완료 (통합 API 설정 적용)'); } catch (error) { console.error('초기화 오류:', error); @@ -3422,7 +3372,6 @@ function renderInlineDefectList(index) { const defects = tempDefects[index] || []; - console.log(`📝 [renderInlineDefectList] index=${index}, 부적합 수=${defects.length}`, defects); // 이슈가 있으면 이슈 선택 UI, 없으면 레거시 UI if (nonconformityIssues.length > 0) { @@ -3430,7 +3379,7 @@ function renderInlineDefectList(index) { let html = `
- 📋 ${escapeHtml(workerWorkplaceName || '작업장소')} 관련 부적합 + ${escapeHtml(workerWorkplaceName || '작업장소')} 관련 부적합 ${parseInt(nonconformityIssues.length) || 0}건
diff --git a/system1-factory/web/js/daily-work-report/state.js b/system1-factory/web/js/daily-work-report/state.js index 889fe94..aa1ca9c 100644 --- a/system1-factory/web/js/daily-work-report/state.js +++ b/system1-factory/web/js/daily-work-report/state.js @@ -68,7 +68,7 @@ class DailyWorkReportState extends BaseState { } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { return JSON.parse(userInfo); } diff --git a/system1-factory/web/js/equipment-management.js b/system1-factory/web/js/equipment-management.js index 941a64f..a5a54fb 100644 --- a/system1-factory/web/js/equipment-management.js +++ b/system1-factory/web/js/equipment-management.js @@ -327,16 +327,13 @@ async function openEquipmentModal(equipmentId = null) { // 다음 관리번호 로드 async function loadNextEquipmentCode() { try { - console.log('📋 다음 관리번호 조회 중...'); const response = await axios.get('/equipments/next-code'); - console.log('📋 다음 관리번호 응답:', response.data); if (response.data.success) { document.getElementById('equipmentCode').value = response.data.data.next_code; - console.log('✅ 다음 관리번호 설정:', response.data.data.next_code); } } catch (error) { - console.error('❌ 다음 관리번호 조회 실패:', error); - console.error('❌ 에러 상세:', error.response?.data || error.message); + console.error(' 다음 관리번호 조회 실패:', error); + console.error(' 에러 상세:', error.response?.data || error.message); // 오류 시 기본값으로 빈 값 유지 (사용자가 직접 입력) } } diff --git a/system1-factory/web/js/group-leader-dashboard.js b/system1-factory/web/js/group-leader-dashboard.js index 6b708b2..0e2d7b6 100644 --- a/system1-factory/web/js/group-leader-dashboard.js +++ b/system1-factory/web/js/group-leader-dashboard.js @@ -2,7 +2,6 @@ // 그룹장 전용 대시보드 - 실시간 근태 및 작업 현황 (Real Data Version) import { apiCall } from './api-config.js'; -console.log('📊 그룹장 대시보드 스크립트 로딩 (Live Data)'); // 상태별 스타일/텍스트 매핑 const STATUS_MAP = { diff --git a/system1-factory/web/js/load-sections.js b/system1-factory/web/js/load-sections.js index da3fd38..7c32854 100644 --- a/system1-factory/web/js/load-sections.js +++ b/system1-factory/web/js/load-sections.js @@ -92,11 +92,10 @@ async function initializeSections() { // 5. 모든 수정이 완료된 HTML을 실제 DOM에 한 번에 삽입 mainContainer.innerHTML = doc.body.innerHTML; - console.log(`✅ ${currentUser.role} 역할의 섹션 로딩 완료.`); } catch (error) { console.error('섹션 로딩 중 오류 발생:', error); - mainContainer.innerHTML = `
콘텐츠 로딩에 실패했습니다: ${error.message}
`; + mainContainer.textContent = '콘텐츠 로딩에 실패했습니다. 페이지를 새로고침해 주세요.'; } } diff --git a/system1-factory/web/js/management-dashboard.js b/system1-factory/web/js/management-dashboard.js index cfd6eca..1f0eab8 100644 --- a/system1-factory/web/js/management-dashboard.js +++ b/system1-factory/web/js/management-dashboard.js @@ -39,22 +39,18 @@ function getCurrentUser() { const payloadBase64 = token.split('.')[1]; if (payloadBase64) { const payload = JSON.parse(atob(payloadBase64)); - console.log('토큰에서 추출한 사용자 정보:', payload); return payload; } } catch (error) { - console.log('토큰에서 사용자 정보 추출 실패:', error); } try { - const userInfo = localStorage.getItem('sso_user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + const userInfo = localStorage.getItem('sso_user'); if (userInfo) { const parsed = JSON.parse(userInfo); - console.log('localStorage에서 가져온 사용자 정보:', parsed); return parsed; } } catch (error) { - console.log('localStorage에서 사용자 정보 가져오기 실패:', error); } return null; @@ -134,7 +130,6 @@ async function loadWorkers() { return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; }); - console.log(`✅ 작업자 로드 성공: ${workers.length}명 (전체: ${allWorkers.length}명)`); } catch (error) { console.error('작업자 로딩 오류:', error); throw error; @@ -148,32 +143,27 @@ async function loadWorkData(date) { // 1차: view_all=true로 전체 데이터 시도 let queryParams = `date=${date}&view_all=true`; - console.log(`🔍 1차 시도: ${API}/daily-work-reports?${queryParams}`); let data = await apiCall(`${API}/daily-work-reports?${queryParams}`); workData = Array.isArray(data) ? data : (data.data || []); // 데이터가 없으면 다른 방법들 시도 if (workData.length === 0) { - console.log('⚠️ view_all로 데이터 없음, 다른 방법 시도...'); // 2차: admin=true로 시도 queryParams = `date=${date}&admin=true`; - console.log(`🔍 2차 시도: ${API}/daily-work-reports?${queryParams}`); data = await apiCall(`${API}/daily-work-reports?${queryParams}`); workData = Array.isArray(data) ? data : (data.data || []); if (workData.length === 0) { // 3차: 날짜 경로 파라미터로 시도 - console.log(`🔍 3차 시도: ${API}/daily-work-reports/date/${date}`); data = await apiCall(`${API}/daily-work-reports/date/${date}`); workData = Array.isArray(data) ? data : (data.data || []); if (workData.length === 0) { // 4차: 기본 파라미터만으로 시도 - console.log(`🔍 4차 시도: ${API}/daily-work-reports?date=${date}`); data = await apiCall(`${API}/daily-work-reports?date=${date}`); workData = Array.isArray(data) ? data : (data.data || []); @@ -181,15 +171,11 @@ async function loadWorkData(date) { } } - console.log(`✅ 최종 작업 데이터 로드 결과: ${workData.length}개`); // 디버깅을 위한 상세 로그 if (workData.length > 0) { - console.log('📊 로드된 데이터 샘플:', workData.slice(0, 3)); const uniqueWorkers = [...new Set(workData.map(w => w.worker_name))]; - console.log('👥 데이터에 포함된 작업자들:', uniqueWorkers); } else { - console.log('❌ 해당 날짜에 작업 데이터가 없거나 접근 권한이 없습니다.'); } return workData; @@ -201,10 +187,8 @@ async function loadWorkData(date) { // 구체적인 에러 정보 표시 if (error.message.includes('403')) { - console.log('🔒 권한 부족으로 인한 접근 제한'); throw new Error('해당 날짜의 데이터에 접근할 권한이 없습니다.'); } else if (error.message.includes('404')) { - console.log('📭 해당 날짜에 데이터 없음'); throw new Error('해당 날짜에 입력된 작업 데이터가 없습니다.'); } else { throw error; @@ -345,7 +329,6 @@ function displayDashboard(data) { filteredWorkData = data.workers; setupFiltering(); - console.log('✅ 대시보드 표시 완료'); } // 요약 섹션 표시 @@ -773,7 +756,6 @@ async function saveEditedWork(workId) { body: JSON.stringify(updateData) }); - console.log('✅ 수정 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); closeEditModal(); @@ -783,7 +765,7 @@ async function saveEditedWork(workId) { await loadDashboardData(); } catch (error) { - console.error('❌ 수정 실패:', error); + console.error(' 수정 실패:', error); showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -804,7 +786,6 @@ async function deleteWorkItem(workId) { method: 'DELETE' }); - console.log('✅ 삭제 성공 (통합 API):', result); showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); closeWorkerDetailModal(); @@ -813,7 +794,7 @@ async function deleteWorkItem(workId) { await loadDashboardData(); } catch (error) { - console.error('❌ 삭제 실패:', error); + console.error(' 삭제 실패:', error); showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); } } @@ -918,7 +899,6 @@ async function init() { // 이벤트 리스너 설정 setupEventListeners(); - console.log('✅ 관리자 대시보드 초기화 완료 (통합 API 설정 적용)'); // 자동으로 오늘 데이터 로드 loadDashboardData(); diff --git a/system1-factory/web/js/modern-dashboard.js b/system1-factory/web/js/modern-dashboard.js index 51f675e..0db3c77 100644 --- a/system1-factory/web/js/modern-dashboard.js +++ b/system1-factory/web/js/modern-dashboard.js @@ -62,7 +62,7 @@ document.addEventListener('DOMContentLoaded', async () => { } if (!window.apiCall) { - console.error('❌ API 함수를 로드할 수 없습니다.'); + console.error(' API 함수를 로드할 수 없습니다.'); showToast('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); return; } @@ -76,7 +76,6 @@ document.addEventListener('DOMContentLoaded', async () => { }); async function initializeDashboard() { - console.log('🚀 모던 대시보드 초기화 시작'); // 사용자 정보 설정 setupUserInfo(); @@ -104,7 +103,6 @@ async function initializeDashboard() { // TBM 페이지 접근 권한 확인 checkTbmPageAccess(); - console.log('✅ 모던 대시보드 초기화 완료'); } // ========== 사용자 정보 설정 ========== // @@ -113,7 +111,6 @@ function setupUserInfo() { const authData = getAuthData(); if (authData && authData.user) { currentUser = authData.user; - console.log('👤 사용자 정보 로드 완료:', currentUser.name, currentUser.role); } } @@ -179,7 +176,6 @@ function setupEventListeners() { // ========== 데이터 로드 ========== // async function loadDashboardData() { - console.log('📊 대시보드 데이터 로딩 시작'); try { // 로딩 상태 표시 @@ -200,10 +196,9 @@ async function loadDashboardData() { // 작업자 현황 표시 displayWorkers(workersData, 'card'); - console.log('✅ 대시보드 데이터 로딩 완료'); } catch (error) { - console.error('❌ 대시보드 데이터 로딩 오류:', error); + console.error(' 대시보드 데이터 로딩 오류:', error); showErrorState(); showToast('데이터를 불러오는 중 오류가 발생했습니다.', 'error'); } @@ -211,7 +206,6 @@ async function loadDashboardData() { async function loadWorkers() { try { - console.log('👥 작업자 데이터 로딩...'); const response = await window.apiCall('/workers'); const allWorkers = Array.isArray(response) ? response : (response.data || []); @@ -220,7 +214,6 @@ async function loadWorkers() { return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; }); - console.log(`✅ 작업자 ${workersData.length}명 로드 완료 (전체: ${allWorkers.length}명)`); return workersData; } catch (error) { console.error('작업자 데이터 로딩 오류:', error); @@ -231,10 +224,8 @@ async function loadWorkers() { async function loadWorkData(date) { try { - console.log(`📋 ${date} 작업 데이터 로딩...`); const response = await window.apiCall(`/daily-work-reports?date=${date}&view_all=true`); workData = Array.isArray(response) ? response : (response.data || []); - console.log(`✅ 작업 데이터 ${workData.length}건 로드 완료`); return workData; } catch (error) { console.error('작업 데이터 로딩 오류:', error); @@ -683,7 +674,6 @@ function checkAdminAccess() { const isFullAdmin = currentUser && ['admin', 'system'].includes(currentUser.access_level); const isGroupLeader = currentUser && currentUser.access_level === 'group_leader'; - console.log(`🔐 권한 확인: 사용자=${currentUser?.username}, 역할=${currentUser.access_level}, 전체관리자=${isFullAdmin}, 그룹리더=${isGroupLeader}`); adminElements.forEach(element => { const href = element.getAttribute('href'); @@ -725,22 +715,18 @@ function checkAdminAccess() { async function checkTbmPageAccess() { try { if (!currentUser || !currentUser.user_id) { - console.log('⚠️ TBM 페이지 권한 확인: 사용자 정보 없음'); return; } const tbmQuickAction = document.getElementById('tbmQuickAction'); if (!tbmQuickAction) { - console.log('⚠️ TBM 빠른 작업 버튼 요소를 찾을 수 없습니다'); return; } - console.log('🛠️ TBM 페이지 권한 확인 중...', { role: currentUser.role, access_level: currentUser.access_level }); // Admin은 모든 페이지 접근 가능 if (currentUser.role === 'Admin' || currentUser.role === 'System Admin' || currentUser.access_level === 'admin' || currentUser.access_level === 'system') { tbmQuickAction.style.display = 'block'; - console.log('✅ Admin 사용자 - TBM 빠른 작업 버튼 표시'); return; } @@ -755,15 +741,12 @@ async function checkTbmPageAccess() { if (tbmPage && tbmPage.can_access) { tbmQuickAction.style.display = 'block'; - console.log('✅ TBM 페이지 접근 권한 있음 - 빠른 작업 버튼 표시'); } else { - console.log('❌ TBM 페이지 접근 권한 없음 - 빠른 작업 버튼 숨김'); } } else { - console.log('⚠️ TBM 페이지 권한 확인 실패'); } } catch (error) { - console.error('❌ TBM 페이지 권한 확인 오류:', error); + console.error(' TBM 페이지 권한 확인 오류:', error); } } @@ -811,7 +794,6 @@ function showErrorState() { // ========== 작업자 관련 액션 함수들 ========== // function openWorkerModal(workerId, workerName) { - console.log(`📝 ${workerName}(ID: ${workerId}) 작업 보고서 모달 열기`); // 모달 데이터 설정 currentModalWorker = { @@ -825,7 +807,6 @@ function openWorkerModal(workerId, workerName) { } function handleVacation(workerId, vacationType) { - console.log(`🏖️ 작업자 ${workerId} 휴가 처리: ${vacationType}`); const vacationNames = { 'full': '연차', @@ -873,7 +854,6 @@ async function processVacation(workerId, vacationType, hours) { } function confirmOvertime(workerId) { - console.log(`⚠️ 작업자 ${workerId} 초과근무 확인`); if (confirm('12시간을 초과한 작업시간이 정상적인 입력인지 확인하시겠습니까?')) { // 초과근무 확인 처리 @@ -1269,8 +1249,6 @@ async function saveModalNewWork() { }] }; - console.log('📤 전송할 작업 데이터:', workData); - console.log('📋 현재 사용자:', currentUser); await window.apiCall('/daily-work-reports', 'POST', workData); diff --git a/system1-factory/web/js/my-attendance.js b/system1-factory/web/js/my-attendance.js index efe5825..f9a449a 100644 --- a/system1-factory/web/js/my-attendance.js +++ b/system1-factory/web/js/my-attendance.js @@ -381,7 +381,8 @@ function showLoading() { function showError(message) { const tbody = document.getElementById('attendanceTableBody'); - tbody.innerHTML = `${message}`; + const safeMsg = (window.escapeHtml ? window.escapeHtml(message) : message.replace(/[&<>"']/g, m => ({'&':'&','<':'<','>':'>','"':'"',"'":'''}[m]))); + tbody.innerHTML = `${safeMsg}`; // 통계 초기화 document.getElementById('totalHours').textContent = '-'; diff --git a/system1-factory/web/js/my-dashboard.js b/system1-factory/web/js/my-dashboard.js index c61a5f5..3fc7fa4 100644 --- a/system1-factory/web/js/my-dashboard.js +++ b/system1-factory/web/js/my-dashboard.js @@ -8,7 +8,6 @@ let currentMonth = new Date().getMonth() + 1; // 페이지 초기화 document.addEventListener('DOMContentLoaded', async () => { - console.log('📊 나의 대시보드 초기화 시작'); await loadUserInfo(); await loadVacationBalance(); @@ -16,7 +15,6 @@ document.addEventListener('DOMContentLoaded', async () => { await loadWorkHoursStats(); await loadRecentReports(); - console.log('✅ 나의 대시보드 초기화 완료'); }); // 사용자 정보 로드 diff --git a/system1-factory/web/js/my-profile.js b/system1-factory/web/js/my-profile.js index 3a50a9c..17422ad 100644 --- a/system1-factory/web/js/my-profile.js +++ b/system1-factory/web/js/my-profile.js @@ -117,6 +117,5 @@ function showError(message) { // 페이지 로드 시 실행 document.addEventListener('DOMContentLoaded', () => { - console.log('👤 프로필 페이지 로드됨'); loadProfile(); }); \ No newline at end of file diff --git a/system1-factory/web/js/navigation.js b/system1-factory/web/js/navigation.js index b854d9b..700e0ff 100644 --- a/system1-factory/web/js/navigation.js +++ b/system1-factory/web/js/navigation.js @@ -14,7 +14,6 @@ function redirect(url) { */ export function redirectToLogin() { const loginUrl = config.paths.loginPage + '?redirect=' + encodeURIComponent(window.location.href); - console.log(`🔄 로그인 페이지로 이동합니다: ${loginUrl}`); redirect(loginUrl); } @@ -25,7 +24,6 @@ export function redirectToLogin() { */ export function redirectToDefaultDashboard(backendRedirectUrl = null) { const destination = backendRedirectUrl || config.paths.defaultDashboard; - console.log(`🔄 대시보드로 이동합니다: ${destination}`); // 부드러운 화면 전환 효과 document.body.style.transition = 'opacity 0.3s ease-out'; @@ -40,7 +38,6 @@ export function redirectToDefaultDashboard(backendRedirectUrl = null) { * 시스템 대시보드 페이지로 리디렉션합니다. */ export function redirectToSystemDashboard() { - console.log(`🔄 시스템 대시보드로 이동합니다: ${config.paths.systemDashboard}`); redirect(config.paths.systemDashboard); } @@ -48,7 +45,6 @@ export function redirectToSystemDashboard() { * 그룹 리더 대시보드 페이지로 리디렉션합니다. */ export function redirectToGroupLeaderDashboard() { - console.log(`🔄 그룹 리더 대시보드로 이동합니다: ${config.paths.groupLeaderDashboard}`); redirect(config.paths.groupLeaderDashboard); } diff --git a/system1-factory/web/js/project-management.js b/system1-factory/web/js/project-management.js index 86822ce..5a07fba 100644 --- a/system1-factory/web/js/project-management.js +++ b/system1-factory/web/js/project-management.js @@ -8,7 +8,6 @@ let currentStatusFilter = 'all'; // 'all', 'active', 'inactive' // 페이지 초기화 document.addEventListener('DOMContentLoaded', function() { - console.log('📁 프로젝트 관리 페이지 초기화 시작'); initializePage(); loadProjects(); @@ -103,11 +102,9 @@ function setupSearchInput() { // 프로젝트 목록 로드 async function loadProjects() { try { - console.log('📊 프로젝트 목록 로딩 시작'); const response = await apiCall('/projects', 'GET'); - console.log('📊 API 응답 구조:', response); // API 응답이 { success: true, data: [...] } 형태인 경우 처리 let projectData = []; @@ -122,7 +119,6 @@ async function loadProjects() { allProjects = projectData; - console.log(`✅ 프로젝트 ${allProjects.length}개 로드 완료`); // 초기 필터 적용 applyAllFilters(); @@ -156,10 +152,10 @@ function renderProjects() { const projectsHtml = filteredProjects.map(project => { // 프로젝트 상태 아이콘 및 텍스트 const statusMap = { - 'planning': { icon: '📋', text: '계획', color: '#6b7280' }, - 'active': { icon: '🚀', text: '진행중', color: '#10b981' }, - 'completed': { icon: '✅', text: '완료', color: '#3b82f6' }, - 'cancelled': { icon: '❌', text: '취소', color: '#ef4444' } + 'planning': { icon: '', text: '계획', color: '#6b7280' }, + 'active': { icon: '', text: '진행중', color: '#10b981' }, + 'completed': { icon: '', text: '완료', color: '#3b82f6' }, + 'cancelled': { icon: '', text: '취소', color: '#ef4444' } }; const validStatuses = ['planning', 'active', 'completed', 'cancelled']; @@ -175,16 +171,9 @@ function renderProjects() { const safePm = escapeHtml(project.pm || '-'); const safeSite = escapeHtml(project.site || '-'); - console.log('🎨 카드 렌더링:', { - project_id: project.project_id, - project_name: project.project_name, - is_active_raw: project.is_active, - isInactive: isInactive - }); - return `
- ${isInactive ? '
🚫 비활성화됨
' : ''} + ${isInactive ? '
비활성화됨
' : ''}
${safeJobNo}
@@ -213,15 +202,15 @@ function renderProjects() { 현장 ${safeSite}
- ${isInactive ? '
⚠️ 작업보고서에서 숨김
' : ''} + ${isInactive ? '
작업보고서에서 숨김
' : ''}
@@ -252,12 +241,6 @@ function updateProjectStats() { if (totalProjectsElement) { totalProjectsElement.textContent = filteredProjects.length; } - - console.log('📊 프로젝트 통계:', { - 전체: filteredProjects.length, - 활성: activeProjects.length, - 비활성: inactiveProjects.length - }); } // 날짜 포맷팅 @@ -282,7 +265,6 @@ function filterByStatus(status) { // 필터링 적용 applyAllFilters(); - console.log(`🔍 상태 필터 적용: ${status}`); } // 통계 카드 활성화 상태 업데이트 @@ -371,7 +353,7 @@ async function refreshProjectList() { const refreshBtn = document.querySelector('.btn-secondary'); if (refreshBtn) { const originalText = refreshBtn.innerHTML; - refreshBtn.innerHTML = '새로고침 중...'; + refreshBtn.innerHTML = '새로고침 중...'; refreshBtn.disabled = true; await loadProjects(); @@ -415,12 +397,6 @@ function openProjectModal(project = null) { const isActiveValue = project.is_active === 1 || project.is_active === true || project.is_active === 'true'; document.getElementById('isActive').checked = isActiveValue; - console.log('🔧 프로젝트 로드:', { - project_id: project.project_id, - project_name: project.project_name, - is_active_raw: project.is_active, - is_active_processed: isActiveValue - }); } else { // 신규 등록 모드 modalTitle.textContent = '새 프로젝트 등록'; @@ -480,7 +456,6 @@ async function saveProject() { is_active: document.getElementById('isActive').checked ? 1 : 0 }; - console.log('💾 저장할 프로젝트 데이터:', projectData); // 필수 필드 검증 if (!projectData.job_no || !projectData.project_name) { @@ -523,7 +498,7 @@ function confirmDeleteProject(projectId) { return; } - if (confirm(`"${project.project_name}" 프로젝트를 정말 삭제하시겠습니까?\n\n⚠️ 삭제된 프로젝트는 복구할 수 없습니다.`)) { + if (confirm(`"${project.project_name}" 프로젝트를 정말 삭제하시겠습니까?\n\n 삭제된 프로젝트는 복구할 수 없습니다.`)) { deleteProjectById(projectId); } } diff --git a/system1-factory/web/js/safety-checklist-manage.js b/system1-factory/web/js/safety-checklist-manage.js index 79fb94f..8554462 100644 --- a/system1-factory/web/js/safety-checklist-manage.js +++ b/system1-factory/web/js/safety-checklist-manage.js @@ -46,7 +46,6 @@ const WEATHER_ICONS = { */ async function initPage() { try { - console.log('📋 안전 체크리스트 관리 페이지 초기화...'); await Promise.all([ loadAllChecks(), @@ -55,7 +54,6 @@ async function initPage() { ]); renderCurrentTab(); - console.log('✅ 초기화 완료. 체크항목:', allChecks.length, '개'); } catch (error) { console.error('초기화 실패:', error); showToast('데이터를 불러오는데 실패했습니다.', 'error'); @@ -73,7 +71,6 @@ async function loadAllChecks() { const response = await apiCall('/tbm/safety-checks'); if (response && response.success) { allChecks = response.data || []; - console.log('✅ 체크 항목 로드:', allChecks.length, '개'); } else { console.warn('체크 항목 응답 실패:', response); allChecks = []; @@ -93,7 +90,6 @@ async function loadWeatherConditions() { if (response && response.success) { weatherConditions = response.data || []; populateWeatherSelects(); - console.log('✅ 날씨 조건 로드:', weatherConditions.length, '개'); } } catch (error) { console.error('날씨 조건 로드 실패:', error); @@ -110,7 +106,6 @@ async function loadWorkTypes() { if (response && response.success) { workTypes = response.data || []; populateWorkTypeSelects(); - console.log('✅ 공정 목록 로드:', workTypes.length, '개'); } } catch (error) { console.error('공정 목록 로드 실패:', error); diff --git a/system1-factory/web/js/system-dashboard.js b/system1-factory/web/js/system-dashboard.js index 511adde..035a64f 100644 --- a/system1-factory/web/js/system-dashboard.js +++ b/system1-factory/web/js/system-dashboard.js @@ -1,10 +1,8 @@ // System Dashboard JavaScript -console.log('🚀 system-dashboard.js loaded'); import { apiRequest } from './api-helper.js'; import { getCurrentUser } from './auth.js'; -console.log('📦 modules imported successfully'); // 전역 변수 let systemData = { @@ -15,7 +13,6 @@ let systemData = { // Initialize on page load document.addEventListener('DOMContentLoaded', function() { - console.log('📄 DOM loaded, starting initialization'); initializeSystemDashboard(); setupEventListeners(); }); @@ -31,65 +28,51 @@ function setupEventListeners() { switch(action) { case 'account-management': button.addEventListener('click', openAccountManagement); - console.log('✅ Account management button listener added'); break; case 'system-logs': button.addEventListener('click', openSystemLogs); - console.log('✅ System logs button listener added'); break; case 'database-management': button.addEventListener('click', openDatabaseManagement); - console.log('✅ Database management button listener added'); break; case 'system-settings': button.addEventListener('click', openSystemSettings); - console.log('✅ System settings button listener added'); break; case 'backup-management': button.addEventListener('click', openBackupManagement); - console.log('✅ Backup management button listener added'); break; case 'monitoring': button.addEventListener('click', openMonitoring); - console.log('✅ Monitoring button listener added'); break; case 'close-modal': button.addEventListener('click', () => closeModal('account-modal')); - console.log('✅ Modal close button listener added'); break; } }); - console.log(`🎯 Total ${actionButtons.length} event listeners setup completed`); } // Initialize system dashboard async function initializeSystemDashboard() { try { - console.log('🚀 Starting system dashboard initialization...'); // Load user info await loadUserInfo(); - console.log('✅ User info loaded'); // Load system status await loadSystemStatus(); - console.log('✅ System status loaded'); // Load user statistics await loadUserStats(); - console.log('✅ User statistics loaded'); // Load recent activities await loadRecentActivities(); - console.log('✅ Recent activities loaded'); // Setup auto-refresh (every 30 seconds) setInterval(refreshSystemStatus, 30000); - console.log('🎉 System dashboard initialization completed'); } catch (error) { - console.error('❌ System dashboard initialization error:', error); + console.error(' System dashboard initialization error:', error); showNotification('Error loading system dashboard', 'error'); } } @@ -307,7 +290,6 @@ async function refreshSystemStatus() { // Open account management function openAccountManagement() { - console.log('🎯 Account management button clicked'); const modal = document.getElementById('account-modal'); const content = document.getElementById('account-management-content'); @@ -315,13 +297,11 @@ function openAccountManagement() { console.log('Content element:', content); if (modal && content) { - console.log('✅ Modal and content elements found, loading content...'); // Load account management content loadAccountManagementContent(content); modal.style.display = 'block'; - console.log('✅ Modal displayed'); } else { - console.error('❌ Modal or content element not found'); + console.error(' Modal or content element not found'); } } @@ -890,11 +870,9 @@ window.filterLogs = filterLogs; // 테스트용 전역 함수 window.testFunction = function() { - console.log('🧪 테스트 함수 호출됨!'); alert('테스트 함수가 정상적으로 작동합니다!'); }; -console.log('🌐 전역 함수들 노출 완료'); // 모달 외부 클릭 시 닫기 window.onclick = function(event) { diff --git a/system1-factory/web/js/task-management.js b/system1-factory/web/js/task-management.js index 82866e1..0ab8b7e 100644 --- a/system1-factory/web/js/task-management.js +++ b/system1-factory/web/js/task-management.js @@ -8,7 +8,6 @@ let currentEditingTask = null; // 페이지 초기화 document.addEventListener('DOMContentLoaded', async () => { - console.log('📋 작업 관리 페이지 초기화'); // API 함수가 로드될 때까지 대기 let retryCount = 0; @@ -33,7 +32,7 @@ async function loadAllData() { // 작업 목록 로드 await loadTasks(); } catch (error) { - console.error('❌ 데이터 로드 오류:', error); + console.error(' 데이터 로드 오류:', error); showToast('데이터를 불러오는 중 오류가 발생했습니다.', 'error'); } } @@ -51,11 +50,10 @@ async function loadWorkTypes() { workTypes = []; } - console.log('✅ 공정 목록 로드:', workTypes.length + '개'); renderWorkTypeTabs(); populateWorkTypeSelect(); } catch (error) { - console.error('❌ 공정 목록 조회 오류:', error); + console.error(' 공정 목록 조회 오류:', error); // API 오류 시에도 빈 배열로 처리 workTypes = []; renderWorkTypeTabs(); @@ -69,7 +67,6 @@ async function loadTasks() { if (response && response.success) { tasks = response.data || []; - console.log('✅ 작업 목록 로드:', tasks.length + '개'); } else { tasks = []; } @@ -77,7 +74,7 @@ async function loadTasks() { renderTasks(); updateStatistics(); } catch (error) { - console.error('❌ 작업 목록 조회 오류:', error); + console.error(' 작업 목록 조회 오류:', error); showToast('작업 목록을 불러오는 중 오류가 발생했습니다.', 'error'); tasks = []; renderTasks(); @@ -257,7 +254,7 @@ async function editTask(taskId) { document.body.style.overflow = 'hidden'; } } catch (error) { - console.error('❌ 작업 조회 오류:', error); + console.error(' 작업 조회 오류:', error); showToast('작업 정보를 불러올 수 없습니다.', 'error'); } } @@ -314,7 +311,7 @@ async function saveTask() { throw new Error(response.message || '저장에 실패했습니다.'); } } catch (error) { - console.error('❌ 작업 저장 오류:', error); + console.error(' 작업 저장 오류:', error); showToast('작업 저장 중 오류가 발생했습니다.', 'error'); } } @@ -339,7 +336,7 @@ async function deleteTask() { throw new Error(response.message || '삭제에 실패했습니다.'); } } catch (error) { - console.error('❌ 작업 삭제 오류:', error); + console.error(' 작업 삭제 오류:', error); showToast('작업 삭제 중 오류가 발생했습니다.', 'error'); } } @@ -399,7 +396,7 @@ async function editWorkType(workTypeId) { document.getElementById('workTypeModal').style.display = 'flex'; document.body.style.overflow = 'hidden'; } catch (error) { - console.error('❌ 공정 조회 오류:', error); + console.error(' 공정 조회 오류:', error); showToast('공정 정보를 불러올 수 없습니다.', 'error'); } } @@ -445,7 +442,7 @@ async function saveWorkType() { throw new Error(response.message || '저장에 실패했습니다.'); } } catch (error) { - console.error('❌ 공정 저장 오류:', error); + console.error(' 공정 저장 오류:', error); showToast('공정 저장 중 오류가 발생했습니다.', 'error'); } } @@ -477,7 +474,7 @@ async function deleteWorkType() { throw new Error(response.message || '삭제에 실패했습니다.'); } } catch (error) { - console.error('❌ 공정 삭제 오류:', error); + console.error(' 공정 삭제 오류:', error); showToast('공정 삭제 중 오류가 발생했습니다.', 'error'); } } diff --git a/system1-factory/web/js/tbm.js b/system1-factory/web/js/tbm.js index ec779c2..6951ffb 100644 --- a/system1-factory/web/js/tbm.js +++ b/system1-factory/web/js/tbm.js @@ -44,7 +44,6 @@ function formatDate(d) { return window.CommonUtils.formatDate(d); } // 페이지 초기화 document.addEventListener('DOMContentLoaded', async () => { - console.log('🛠️ TBM 관리 페이지 초기화'); // API 함수가 로드될 때까지 대기 let retryCount = 0; @@ -542,7 +541,6 @@ function populateLeaderSelect() { const jobTypeText = worker.job_type ? ` (${escapeHtml(worker.job_type)})` : ''; leaderSelect.innerHTML = ``; leaderSelect.disabled = true; - console.log('✅ 입력자 자동 설정:', worker.worker_name); } else { // 작업자를 찾을 수 없는 경우 leaderSelect.innerHTML = ''; @@ -560,7 +558,6 @@ function populateLeaderSelect() { return ``; }).join(''); leaderSelect.disabled = false; - console.log('✅ 관리자: 입력자 선택 가능'); } } @@ -637,16 +634,14 @@ window.closeTbmModal = closeTbmModal; // TBM 세션 저장 (간소화: 프로젝트+공정+작업자, task/workplace=null) async function saveTbmSession() { - console.log('💾 TBM 저장 시작...'); let leaderId = parseInt(document.getElementById('leaderId').value); if (!leaderId || isNaN(leaderId)) { if (!currentUser.user_id) { - console.log('📝 관리자 계정: leader_user_id를 NULL로 설정'); leaderId = null; } else { - console.error('❌ 입력자 설정 오류'); + console.error(' 입력자 설정 오류'); showToast('입력자 정보가 올바르지 않습니다.', 'error'); return; } @@ -704,7 +699,7 @@ async function saveTbmSession() { throw new Error(teamResponse.message || '팀원 수정에 실패했습니다.'); } } catch (error) { - console.error('❌ TBM 세션 수정 오류:', error); + console.error(' TBM 세션 수정 오류:', error); showToast('TBM 세션 수정 중 오류가 발생했습니다.', 'error'); } return; @@ -745,7 +740,6 @@ async function saveTbmSession() { if (response && response.success) { createdSessionId = response.data.session_id; - console.log('✅ TBM 세션 생성 완료:', createdSessionId); const teamResponse = await window.TbmAPI.addTeamMembers(createdSessionId, members); @@ -765,7 +759,7 @@ async function saveTbmSession() { throw new Error(response.message || '저장에 실패했습니다.'); } } catch (error) { - console.error('❌ TBM 세션 저장 오류:', error); + console.error(' TBM 세션 저장 오류:', error); // 409 중복 배정 에러 처리 if (error.duplicates && error.duplicates.length > 0) { @@ -1540,7 +1534,7 @@ async function loadWorkplacesByCategory(categoryId) { `).join(''); } catch (error) { - console.error('❌ 작업장 로드 오류:', error); + console.error(' 작업장 로드 오류:', error); workplaceList.innerHTML = '
작업장을 불러오는 중 오류가 발생했습니다
'; } } @@ -1641,7 +1635,6 @@ async function loadWorkplaceMap(categoryId, layoutImagePath) { ? layoutImagePath : `${apiBaseUrl}${layoutImagePath}`; - console.log('🖼️ 이미지 로드 시도:', fullImageUrl); // 지도 영역 데이터 로드 mapRegions = await window.TbmAPI.loadMapRegions(categoryId); @@ -1666,11 +1659,10 @@ async function loadWorkplaceMap(categoryId, layoutImagePath) { // 클릭 이벤트 리스너 추가 mapCanvas.onclick = handleMapClick; - console.log(`✅ 작업장 지도 로드 완료: ${mapRegions.length}개 영역`); }; mapImage.onerror = function() { - console.error('❌ 지도 이미지 로드 실패'); + console.error(' 지도 이미지 로드 실패'); document.getElementById('layoutMapArea').style.display = 'none'; document.getElementById('workplaceListSection').style.display = 'block'; document.getElementById('workplaceList').style.display = 'flex'; @@ -1681,7 +1673,7 @@ async function loadWorkplaceMap(categoryId, layoutImagePath) { mapImage.src = fullImageUrl; } catch (error) { - console.error('❌ 작업장 지도 로드 오류:', error); + console.error(' 작업장 지도 로드 오류:', error); document.getElementById('layoutMapArea').style.display = 'none'; document.getElementById('workplaceList').style.display = 'flex'; } @@ -2030,7 +2022,7 @@ async function openTeamCompositionModal(sessionId) { lockBodyScroll(); } catch (error) { - console.error('❌ 팀 구성 로드 오류:', error); + console.error(' 팀 구성 로드 오류:', error); showToast('팀 구성을 불러오는 중 오류가 발생했습니다.', 'error'); } } @@ -2130,7 +2122,7 @@ async function saveTeamComposition() { throw new Error(response.message || '저장에 실패했습니다.'); } } catch (error) { - console.error('❌ 팀 구성 저장 오류:', error); + console.error(' 팀 구성 저장 오류:', error); showToast('팀 구성 저장 중 오류가 발생했습니다.', 'error'); } } @@ -2222,7 +2214,7 @@ async function openSafetyCheckModal(sessionId) { lockBodyScroll(); } catch (error) { - console.error('❌ 안전 체크 조회 오류:', error); + console.error(' 안전 체크 조회 오류:', error); showToast('안전 체크 정보를 불러오는 중 오류가 발생했습니다.', 'error'); } } @@ -2328,7 +2320,7 @@ async function saveSafetyChecklist() { showToast('안전 체크가 완료되었습니다.', 'success'); closeSafetyModal(); } catch (error) { - console.error('❌ 안전 체크 저장 오류:', error); + console.error(' 안전 체크 저장 오류:', error); showToast('안전 체크 저장 중 오류가 발생했습니다.', 'error'); } } @@ -2473,7 +2465,7 @@ async function completeTbmSession() { throw new Error(response.message || '완료 처리에 실패했습니다.'); } } catch (error) { - console.error('❌ TBM 완료 처리 오류:', error); + console.error(' TBM 완료 처리 오류:', error); showToast('TBM 완료 처리 중 오류가 발생했습니다.', 'error'); } finally { if (btn) { btn.disabled = false; btn.innerHTML = ' 완료'; } @@ -2622,7 +2614,6 @@ async function viewTbmSession(sessionId) { // 푸터 버튼 동적 생성 const footer = document.getElementById('detailModalFooter'); const safeId = parseInt(session.session_id) || 0; - console.log('📋 TBM 상세 - session_id:', safeId, 'status:', session.status); if (session.status === 'draft') { footer.innerHTML = `