Files
tk-factory-services/system1-factory/web/pages/inspection/zone-detail.html
Hyungi Ahn 6f1efdb03c fix: 로그인 리다이렉트 통합 및 캐시 버스팅 정리
- config.js loginPage를 /index.html에서 /login(SSO)으로 변경
- navigation.js, load-navbar.js에 redirect 파라미터 추가
- 8개 JS 파일의 하드코딩된 '/login' → window.getLoginUrl() 전환
- 로그아웃 시 clearSSOAuth() 호출 추가 (SSO 쿠키 삭제)
- api-base.js v=2→v=3 (SW 캐시 해제 코드 통합)
- TBM 모듈 버전 쿼리스트링 통일 (tbm.html, tbm-mobile.html)
- dashboard.html SW 캐시 해제 인라인 코드 제거 (api-base.js에서 처리)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:56:08 +09:00

298 lines
13 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>구역 상세 | (주)테크니컬코리아</title>
<link rel="stylesheet" href="/css/design-system.css">
<link rel="stylesheet" href="/css/admin-pages.css?v=8">
<link rel="stylesheet" href="/css/zone-detail.css?v=3">
<link rel="icon" type="image/png" href="/img/favicon.png">
<script src="/js/api-base.js?v=3"></script>
<script src="/js/app-init.js?v=9" defer></script>
</head>
<body>
<!-- 네비게이션 바 -->
<div id="navbar-container"></div>
<!-- 메인 레이아웃 -->
<div class="page-container">
<main class="main-content">
<div class="dashboard-main">
<!-- 페이지 헤더 -->
<div class="zone-header">
<div class="zone-header-left">
<button class="btn btn-back" onclick="goBack()">
<span></span> 돌아가기
</button>
</div>
<div class="zone-header-center">
<h1 id="zoneName" class="zone-title">작업장</h1>
<p id="zoneCategory" class="zone-subtitle">공장</p>
</div>
<div class="zone-header-right">
<span id="currentDate" class="current-date"></span>
</div>
</div>
<!-- 요약 카드 -->
<div id="summaryCards" class="summary-cards">
<!-- JS에서 렌더링 -->
</div>
<!-- 탭 네비게이션 -->
<div class="tab-navigation">
<button class="tab-btn active" data-tab="map" onclick="switchTab('map')">
🗺️ 구역 현황
</button>
<button class="tab-btn" data-tab="issues" onclick="switchTab('issues')">
🚨 안전신고/부적합
</button>
<button class="tab-btn" data-tab="equipment" onclick="switchTab('equipment')">
⚙️ 설비/수리
</button>
<button class="tab-btn" data-tab="visits" onclick="switchTab('visits')">
🚶 출입현황
</button>
<button class="tab-btn" data-tab="tbm" onclick="switchTab('tbm')">
📋 TBM
</button>
<button class="tab-btn" data-tab="patrol" onclick="switchTab('patrol')">
🔍 순회점검
</button>
</div>
<!-- 탭 콘텐츠 -->
<div class="tab-contents">
<!-- 구역 현황 탭 -->
<div id="tab-map" class="tab-content active">
<div class="map-editor-section">
<div class="map-editor-header">
<h3>구역 현황</h3>
<div class="map-editor-actions">
<button class="btn btn-primary btn-sm" id="addItemBtn" onclick="startAddItem()">
현황 등록
</button>
</div>
</div>
<div class="map-editor-container">
<div id="zoneMapContainer" class="zone-map-container">
<div class="map-placeholder">지도를 로딩 중...</div>
</div>
<div class="map-legend">
<div class="legend-title">주의 수준</div>
<div class="legend-items">
<div class="legend-item"><span class="legend-color" style="background: #10b981;"></span> 양호</div>
<div class="legend-item"><span class="legend-color" style="background: #f59e0b;"></span> 주의</div>
<div class="legend-item"><span class="legend-color" style="background: #ef4444;"></span> 관리필요</div>
</div>
<div class="legend-title" style="margin-top: 1rem;">설비 상태</div>
<div class="legend-items">
<div class="legend-item"><span style="margin-right: 4px;">⚙️</span> 정상 가동</div>
<div class="legend-item"><span style="margin-right: 4px;">🔧</span> 수리 필요</div>
<div class="legend-item"><span style="margin-right: 4px;">⚠️</span> 점검중</div>
<div class="legend-item"><span style="margin-right: 4px;">📤</span> 타 작업장 이동</div>
<div class="legend-item"><span style="margin-right: 4px;">📥</span> 임시 배치</div>
</div>
</div>
</div>
<div id="zoneItemsList" class="zone-items-list">
<!-- JS에서 렌더링 -->
</div>
</div>
</div>
<!-- 안전신고/부적합 탭 -->
<div id="tab-issues" class="tab-content">
<div id="issuesContent" class="content-loading">
<div class="loading-spinner"></div>
<p>로딩 중...</p>
</div>
</div>
<!-- 설비/수리 탭 -->
<div id="tab-equipment" class="tab-content">
<div id="equipmentContent" class="content-loading">
<div class="loading-spinner"></div>
<p>로딩 중...</p>
</div>
</div>
<!-- 출입현황 탭 -->
<div id="tab-visits" class="tab-content">
<div id="visitsContent" class="content-loading">
<div class="loading-spinner"></div>
<p>로딩 중...</p>
</div>
</div>
<!-- TBM 탭 -->
<div id="tab-tbm" class="tab-content">
<div id="tbmContent" class="content-loading">
<div class="loading-spinner"></div>
<p>로딩 중...</p>
</div>
</div>
<!-- 순회점검 탭 -->
<div id="tab-patrol" class="tab-content">
<div id="patrolContent" class="content-loading">
<div class="loading-spinner"></div>
<p>로딩 중...</p>
</div>
</div>
</div>
</div>
</main>
</div>
<!-- 현황 등록/수정 모달 -->
<div id="zoneItemModal" class="modal-overlay" style="display: none;">
<div class="modal-container" style="max-width: 520px;">
<div class="modal-header">
<h2 id="zoneItemModalTitle">현황 등록</h2>
<button class="btn-close" onclick="closeZoneItemModal()">&times;</button>
</div>
<div class="modal-body">
<form id="zoneItemForm">
<input type="hidden" id="zoneItemId">
<input type="hidden" id="zoneItemX">
<input type="hidden" id="zoneItemY">
<input type="hidden" id="zoneItemWidth">
<input type="hidden" id="zoneItemHeight">
<!-- 프로젝트 여부 -->
<div class="form-group">
<label>프로젝트 여부 *</label>
<div class="radio-group">
<label class="radio-label">
<input type="radio" name="zoneItemProjectType" value="project" onchange="onProjectTypeChange(this.value)">
<span class="radio-text">프로젝트</span>
</label>
<label class="radio-label">
<input type="radio" name="zoneItemProjectType" value="non_project" onchange="onProjectTypeChange(this.value)" checked>
<span class="radio-text">프로젝트 아님</span>
</label>
<label class="radio-label">
<input type="radio" name="zoneItemProjectType" value="unknown" onchange="onProjectTypeChange(this.value)">
<span class="radio-text">판단 못함</span>
</label>
</div>
</div>
<!-- 프로젝트 선택 (프로젝트일 경우만 표시) -->
<div class="form-group" id="projectSelectGroup" style="display: none;">
<label for="zoneItemProject">프로젝트 선택</label>
<select id="zoneItemProject" class="form-control">
<option value="">프로젝트를 선택하세요</option>
<!-- JS에서 동적 로드 -->
</select>
</div>
<!-- 명칭 -->
<div class="form-group">
<label for="zoneItemName">명칭 *</label>
<input type="text" id="zoneItemName" class="form-control" placeholder="예: A사 제품, 작업 자재, 이동 설비" required>
</div>
<!-- 상태/유형 + 주의수준 -->
<div class="form-row">
<div class="form-group" style="flex: 1.5;">
<label for="zoneItemType">상태/유형</label>
<div class="select-with-add">
<select id="zoneItemType" class="form-control">
<option value="working">작업중</option>
<option value="temp_storage">임시적치</option>
<option value="moved_equipment">이동설비</option>
<option value="unreported">미신고품</option>
</select>
<button type="button" class="btn-add-option" onclick="addCustomType()" title="유형 추가">+</button>
</div>
</div>
<div class="form-group" style="flex: 1;">
<label for="zoneItemWarning">주의 수준</label>
<select id="zoneItemWarning" class="form-control">
<option value="good">양호</option>
<option value="caution">주의</option>
<option value="needs_management">관리필요</option>
</select>
</div>
</div>
<!-- 상세 설명 -->
<div class="form-group">
<label for="zoneItemDesc">상세 설명</label>
<textarea id="zoneItemDesc" class="form-control" rows="2" placeholder="현황에 대한 상세 설명, 주의사항, 담당자 등"></textarea>
</div>
<!-- 사진 등록 -->
<div class="form-group">
<label>사진</label>
<div class="photo-upload-area">
<input type="file" id="zoneItemPhoto" accept="image/*" multiple onchange="onPhotoSelected(event)" style="display: none;">
<div id="photoPreviewList" class="photo-preview-list">
<!-- 미리보기 이미지들 -->
</div>
<button type="button" class="btn-add-photo" onclick="document.getElementById('zoneItemPhoto').click()">
<span class="photo-icon">📷</span>
<span>사진 추가</span>
</button>
</div>
</div>
<!-- 표시 색상 -->
<div class="form-group">
<label>표시 색상</label>
<div class="color-picker-row">
<input type="color" id="zoneItemColor" class="form-control color-input" value="#3b82f6">
<div class="color-presets">
<button type="button" class="color-preset" style="background: #10b981;" onclick="setItemColor('#10b981')" title="양호"></button>
<button type="button" class="color-preset" style="background: #f59e0b;" onclick="setItemColor('#f59e0b')" title="주의"></button>
<button type="button" class="color-preset" style="background: #ef4444;" onclick="setItemColor('#ef4444')" title="관리필요"></button>
<button type="button" class="color-preset" style="background: #3b82f6;" onclick="setItemColor('#3b82f6')" title="기본"></button>
<button type="button" class="color-preset" style="background: #8b5cf6;" onclick="setItemColor('#8b5cf6')" title="기타"></button>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" onclick="closeZoneItemModal()">취소</button>
<button type="button" class="btn btn-danger" id="deleteZoneItemBtn" onclick="deleteZoneItem()" style="display: none;">삭제</button>
<button type="button" class="btn btn-primary" onclick="saveZoneItem()">저장</button>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script type="module">
import '/js/api-config.js?v=3';
</script>
<script>
(function() {
const checkApiConfig = setInterval(() => {
if (window.API_BASE_URL) {
clearInterval(checkApiConfig);
axios.defaults.baseURL = window.API_BASE_URL;
const token = localStorage.getItem('sso_token');
if (token) {
axios.defaults.headers.common['Authorization'] = `Bearer ${token}`;
}
axios.interceptors.response.use(
response => response,
error => {
if (error.response?.status === 401) {
alert('세션이 만료되었습니다. 다시 로그인해주세요.');
window.location.href = '/pages/login.html';
}
return Promise.reject(error);
}
);
}
}, 50);
})();
</script>
<script src="/js/zone-detail.js?v=6"></script>
</body>
</html>