feat: TBM 모바일 시스템 + 작업 분할/이동 + 권한 통합
TBM 시스템: - 4단계 워크플로우 (draft→세부편집→완료→작업보고) - 모바일 전용 TBM 페이지 (tbm-mobile.html) + 3단계 생성 위자드 - 작업자 작업 분할 (work_hours + split_seq) - 작업자 이동 보내기/빼오기 (tbm_transfers 테이블) - 생성 시 중복 배정 방지 (당일 배정 현황 조회) - 데스크탑 TBM 페이지 세부편집 기능 추가 작업보고서: - 모바일 전용 작업보고서 페이지 (report-create-mobile.html) - TBM에서 사전 등록된 work_hours 자동 반영 권한 시스템: - tkuser user_page_permissions 테이블과 system1 페이지 접근 연동 - pageAccessRoutes를 userRoutes보다 먼저 등록 (라우트 우선순위 수정) - TKUSER_DEFAULT_ACCESS 폴백 추가 (개인→부서→기본값 3단계) - 권한 캐시키 갱신 (userPageAccess_v2) 기타: - app-init.js 캐시 버스팅 (v=5) - iOS Safari touch-action: manipulation 적용 - KST 타임존 날짜 버그 수정 (toISOString UTC 이슈) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -11,7 +11,7 @@
|
||||
<link rel="icon" type="image/png" href="/img/favicon.png">
|
||||
<!-- 최적화된 로딩: API 설정 → 앱 초기화 (병렬 컴포넌트 로딩) -->
|
||||
<script src="/js/api-base.js"></script>
|
||||
<script src="/js/app-init.js?v=3" defer></script>
|
||||
<script src="/js/app-init.js?v=5" defer></script>
|
||||
<!-- instant.page: 링크 호버 시 페이지 프리로딩 -->
|
||||
<script src="https://instant.page/5.2.0" type="module"></script>
|
||||
</head>
|
||||
@@ -144,9 +144,9 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!-- TBM 생성/수정 모달 -->
|
||||
<!-- TBM 생성 모달 (간소화) -->
|
||||
<div id="tbmModal" class="tbm-modal-overlay" style="display: none;">
|
||||
<div class="tbm-modal" style="max-width: 1000px;">
|
||||
<div class="tbm-modal" style="max-width: 800px;">
|
||||
<div class="tbm-modal-header">
|
||||
<h2 class="tbm-modal-title" id="modalTitle">
|
||||
<span>📝</span>
|
||||
@@ -159,7 +159,7 @@
|
||||
<form id="tbmForm" onsubmit="event.preventDefault(); saveTbmSession();">
|
||||
<input type="hidden" id="sessionId">
|
||||
|
||||
<!-- 고정 정보 섹션 -->
|
||||
<!-- 기본 정보 섹션 -->
|
||||
<div class="tbm-form-section">
|
||||
<h3 class="tbm-form-section-title">
|
||||
<span>📅</span>
|
||||
@@ -177,32 +177,44 @@
|
||||
<input type="hidden" id="leaderId">
|
||||
</div>
|
||||
</div>
|
||||
<div class="tbm-form-row">
|
||||
<div class="tbm-form-group">
|
||||
<label class="tbm-form-label">프로젝트</label>
|
||||
<select id="newTbmProjectId" class="tbm-form-input">
|
||||
<option value="">선택 안함</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="tbm-form-group">
|
||||
<label class="tbm-form-label">공정<span class="tbm-form-required">*</span></label>
|
||||
<select id="newTbmWorkTypeId" class="tbm-form-input" required>
|
||||
<option value="">공정 선택...</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 작업자 및 작업 정보 섹션 -->
|
||||
<!-- 작업자 선택 섹션 -->
|
||||
<div class="tbm-form-section">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
|
||||
<h3 class="tbm-form-section-title" style="margin: 0; border: 0; padding: 0;">
|
||||
<span>👥</span>
|
||||
작업자 및 작업 정보
|
||||
작업자 선택
|
||||
<span id="newTbmWorkerCount" style="color: #3b82f6; font-size: 0.875rem;">(0명)</span>
|
||||
</h3>
|
||||
<div style="display: flex; gap: 0.5rem;">
|
||||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="openBulkSettingModal()">
|
||||
일괄 설정
|
||||
</button>
|
||||
<button type="button" class="tbm-btn tbm-btn-primary tbm-btn-sm" onclick="openWorkerSelectionModal()">
|
||||
<span class="tbm-btn-icon">+</span>
|
||||
작업자 선택
|
||||
</button>
|
||||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="selectAllNewTbmWorkers()">전체 선택</button>
|
||||
<button type="button" class="tbm-btn tbm-btn-secondary tbm-btn-sm" onclick="deselectAllNewTbmWorkers()">전체 해제</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 작업자 카드 리스트 -->
|
||||
<div id="workerTaskList" class="tbm-worker-list">
|
||||
<!-- 작업자 카드들이 여기에 동적으로 추가됩니다 -->
|
||||
<div class="tbm-empty-state" id="workerListEmpty" style="padding: 2rem; border: 2px dashed #d1d5db; border-radius: 10px;">
|
||||
<div class="tbm-empty-icon">👥</div>
|
||||
<p class="tbm-empty-description" style="margin: 0;">작업자를 선택해주세요</p>
|
||||
<div id="newTbmWorkerGrid" class="tbm-worker-select-grid">
|
||||
<!-- 작업자 체크박스 그리드가 여기에 동적으로 생성됩니다 -->
|
||||
</div>
|
||||
|
||||
<div class="tbm-alert tbm-alert-info" style="margin-top: 1rem;">
|
||||
<span class="tbm-alert-icon">💡</span>
|
||||
<div class="tbm-alert-content">
|
||||
<div class="tbm-alert-text">저장 후 카드를 클릭하면 작업자별 <strong>작업/작업장</strong>을 입력할 수 있습니다.</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -400,6 +412,9 @@
|
||||
<div class="tbm-workplace-map-container">
|
||||
<canvas id="workplaceMapCanvas"></canvas>
|
||||
</div>
|
||||
<button type="button" class="landscape-trigger-btn" id="landscapeTriggerBtn" onclick="openLandscapeMap()" style="display:none;">
|
||||
📺 전체화면 지도
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 리스트 기반 선택 (모바일에서 토글) -->
|
||||
@@ -525,11 +540,18 @@
|
||||
<label class="tbm-form-label">종료 시간</label>
|
||||
<input type="time" id="endTime" class="tbm-form-input">
|
||||
</div>
|
||||
|
||||
<div class="tbm-form-group" style="margin-top: 1rem;">
|
||||
<label class="tbm-form-label">작업자 근태</label>
|
||||
<div id="completeAttendanceList" style="max-height: 300px; overflow-y: auto; border: 1px solid #e5e7eb; border-radius: 0.5rem; padding: 0.5rem;">
|
||||
<div style="text-align:center; color:#9ca3af; padding:1rem;">로딩 중...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tbm-modal-footer">
|
||||
<button type="button" class="tbm-btn tbm-btn-secondary" onclick="closeCompleteModal()">취소</button>
|
||||
<button type="button" class="tbm-btn tbm-btn-success" onclick="completeTbmSession()">
|
||||
<button type="button" class="tbm-btn tbm-btn-success" id="completeModalBtn" onclick="completeTbmSession()">
|
||||
<span class="tbm-btn-icon">✓</span>
|
||||
완료
|
||||
</button>
|
||||
@@ -657,6 +679,19 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 가로모드 전체화면 지도 오버레이 -->
|
||||
<div id="landscapeOverlay" class="landscape-overlay" style="display:none;">
|
||||
<div id="landscapeInner" class="landscape-inner">
|
||||
<div class="landscape-header">
|
||||
<h3>🏭 작업장 선택</h3>
|
||||
<button type="button" class="landscape-close-btn" onclick="closeLandscapeMap()">×</button>
|
||||
</div>
|
||||
<div class="landscape-canvas-wrap">
|
||||
<canvas id="landscapeCanvas"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 토스트 알림 -->
|
||||
<div class="toast-container" id="toastContainer"></div>
|
||||
</div>
|
||||
@@ -667,7 +702,7 @@
|
||||
<script src="/js/tbm/api.js?v=1"></script>
|
||||
|
||||
<!-- 기존 UI 로직 (점진적 마이그레이션) -->
|
||||
<script type="module" src="/js/tbm.js?v=8"></script>
|
||||
<script type="module" src="/js/tbm.js?v=10"></script>
|
||||
|
||||
<!-- 모바일 하단 네비게이션 -->
|
||||
<div id="mobile-nav-container"></div>
|
||||
|
||||
Reference in New Issue
Block a user