Section A (Backend): - POST /api/proxy-input: TBM 세션+팀배정+작업보고서 일괄 생성 (트랜잭션) - GET /api/proxy-input/daily-status: 일별 TBM/보고서 입력 현황 - GET /api/proxy-input/daily-status/detail: 작업자별 상세 - tbm_sessions에 is_proxy_input, proxy_input_by 컬럼 추가 - system1/system2/tkuser requireMinLevel → shared requirePage 전환 - permissionModel에 factory_proxy_input, factory_daily_status 키 등록 Section B (Frontend): - daily-status.html: 날짜 네비 + 요약 카드 + 필터 탭 + 작업자 리스트 + 바텀시트 - proxy-input.html: 미입력자 카드 + 확장 폼 + 일괄 설정 + 저장 - tkfb-core.js NAV_MENU에 입력 현황/대리입력 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
121 lines
5.7 KiB
HTML
121 lines
5.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
|
<title>대리입력 - TK 공장관리</title>
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
|
<link rel="stylesheet" href="/static/css/tkfb.css?v=2026033001">
|
|
<link rel="stylesheet" href="/css/proxy-input.css?v=2026033001">
|
|
</head>
|
|
<body class="bg-gray-50">
|
|
<header class="bg-orange-700 text-white sticky top-0 z-50">
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
|
<div class="flex justify-between items-center h-14">
|
|
<div class="flex items-center gap-3">
|
|
<button id="mobileMenuBtn" class="lg:hidden text-orange-200 hover:text-white"><i class="fas fa-bars text-xl"></i></button>
|
|
<i class="fas fa-industry text-xl text-orange-200"></i>
|
|
<h1 class="text-lg font-semibold">TK 공장관리</h1>
|
|
</div>
|
|
<div class="flex items-center gap-4">
|
|
<span id="headerUserName" class="text-sm hidden sm:block">-</span>
|
|
<div id="headerUserAvatar" class="w-8 h-8 bg-orange-600 rounded-full flex items-center justify-center text-sm font-bold">-</div>
|
|
<button onclick="doLogout()" class="text-orange-200 hover:text-white" title="로그아웃"><i class="fas fa-sign-out-alt"></i></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</header>
|
|
<div id="mobileOverlay" class="hidden fixed inset-0 bg-black/50 z-30 lg:hidden"></div>
|
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 fade-in">
|
|
<div class="flex gap-6">
|
|
<nav id="sideNav" class="hidden lg:flex flex-col gap-1 w-52 flex-shrink-0 pt-2 fixed lg:static z-40 bg-white lg:bg-transparent p-4 lg:p-0 rounded-lg lg:rounded-none shadow-lg lg:shadow-none top-14 left-0 bottom-0 overflow-y-auto"></nav>
|
|
<div class="flex-1 min-w-0">
|
|
|
|
<!-- Header -->
|
|
<div class="pi-header">
|
|
<div class="pi-header-row">
|
|
<button type="button" onclick="history.back()" class="pi-back-btn"><i class="fas fa-arrow-left"></i></button>
|
|
<h1>대리입력</h1>
|
|
<div class="pi-header-date" id="headerDate">-</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Date + Status -->
|
|
<div class="pi-date-bar">
|
|
<div class="pi-date-info">
|
|
<i class="fas fa-calendar-alt text-blue-500"></i>
|
|
<input type="date" id="dateInput" class="pi-date-input" onchange="onDateChange(this.value)">
|
|
<button type="button" class="pi-refresh-btn" onclick="loadWorkers()"><i class="fas fa-sync-alt"></i></button>
|
|
</div>
|
|
<div class="pi-status-badge" id="statusBadge">
|
|
<i class="fas fa-exclamation-triangle text-amber-500"></i>
|
|
<span>미입력 <strong id="missingNum">0</strong>명</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Bulk Actions -->
|
|
<div class="pi-bulk hidden" id="bulkBar">
|
|
<span class="pi-bulk-label"><i class="fas fa-layer-group mr-1"></i>일괄 설정 (<span id="selectedCount">0</span>명)</span>
|
|
<div class="pi-bulk-actions">
|
|
<button type="button" class="pi-bulk-btn" onclick="bulkSet('project')"><i class="fas fa-folder mr-1"></i>프로젝트</button>
|
|
<button type="button" class="pi-bulk-btn" onclick="bulkSet('workType')"><i class="fas fa-wrench mr-1"></i>공종</button>
|
|
<button type="button" class="pi-bulk-btn" onclick="bulkSet('hours')"><i class="fas fa-clock mr-1"></i>시간</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Worker Cards -->
|
|
<div class="pi-cards" id="workerCards">
|
|
<div class="ds-skeleton"></div>
|
|
<div class="ds-skeleton"></div>
|
|
</div>
|
|
|
|
<!-- Empty State -->
|
|
<div class="pi-empty hidden" id="emptyState">
|
|
<i class="fas fa-check-circle text-3xl text-green-300"></i>
|
|
<p>미입력 작업자가 없습니다</p>
|
|
<a href="/pages/work/daily-status.html" class="ds-link">현황으로 돌아가기</a>
|
|
</div>
|
|
|
|
<!-- No Permission -->
|
|
<div class="ds-empty hidden" id="noPermission">
|
|
<i class="fas fa-lock text-3xl text-gray-300"></i>
|
|
<p>접근 권한이 없습니다</p>
|
|
<a href="/pages/dashboard.html" class="ds-link">대시보드로 이동</a>
|
|
</div>
|
|
|
|
<!-- Bottom Save -->
|
|
<div class="pi-bottom" id="bottomSave">
|
|
<button type="button" class="pi-save-btn" id="saveBtn" onclick="saveProxyInput()" disabled>
|
|
<i class="fas fa-save mr-2"></i><span id="saveBtnText">저장할 작업자를 선택하세요</span>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- Toast -->
|
|
<div id="toastContainer" class="toast-container"></div>
|
|
|
|
<!-- Bulk Select Modal -->
|
|
<div class="pi-modal-overlay hidden" id="bulkModal">
|
|
<div class="pi-modal">
|
|
<div class="pi-modal-header">
|
|
<span id="bulkModalTitle">일괄 설정</span>
|
|
<button type="button" onclick="closeBulkModal()"><i class="fas fa-times"></i></button>
|
|
</div>
|
|
<div class="pi-modal-body" id="bulkModalBody"></div>
|
|
<div class="pi-modal-footer">
|
|
<button type="button" class="pi-modal-cancel" onclick="closeBulkModal()">취소</button>
|
|
<button type="button" class="pi-modal-confirm" id="bulkConfirmBtn">적용</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="/static/js/tkfb-core.js?v=2026033001"></script>
|
|
<script src="/js/api-base.js?v=2026031701"></script>
|
|
<script src="/js/proxy-input.js?v=2026033001"></script>
|
|
</body>
|
|
</html>
|