refactor: 미사용 로컬 부적합 현황 페이지 삭제

NAV_MENU에서 이미 tkqc.technicalkorea.net으로 외부 링크 설정됨.
로컬 nonconformity.html + tkfb-nonconformity.js는 중복 파일이므로 삭제.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-04-01 11:42:16 +09:00
parent 39c333bb39
commit e9ece8c6f1
2 changed files with 0 additions and 215 deletions

View File

@@ -1,96 +0,0 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<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=2026033108">
</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>
<!-- Mobile overlay -->
<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">
<!-- Sidebar Nav -->
<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">
<!-- 페이지 헤더 -->
<div class="mb-5">
<h2 class="text-xl font-bold text-gray-800">부적합 현황</h2>
<p class="text-sm text-gray-500 mt-0.5">자재, 설계, 검사 등 작업 관련 부적합 신고 현황입니다.</p>
</div>
<!-- 통계 카드 -->
<div class="grid grid-cols-2 lg:grid-cols-4 gap-3 mb-5" id="statsGrid">
<div class="stat-card">
<div class="stat-value text-blue-600" id="statReported">-</div>
<div class="stat-label">신고</div>
</div>
<div class="stat-card">
<div class="stat-value text-orange-600" id="statReceived">-</div>
<div class="stat-label">접수</div>
</div>
<div class="stat-card">
<div class="stat-value text-purple-600" id="statProgress">-</div>
<div class="stat-label">처리중</div>
</div>
<div class="stat-card">
<div class="stat-value text-green-600" id="statCompleted">-</div>
<div class="stat-label">완료</div>
</div>
</div>
<!-- 필터 바 -->
<div class="bg-white rounded-xl shadow-sm p-4 mb-5 flex flex-wrap items-center gap-3">
<select id="filterStatus" class="input-field px-3 py-2 rounded-lg text-sm">
<option value="">전체 상태</option>
<option value="reported">신고</option>
<option value="received">접수</option>
<option value="in_progress">처리중</option>
<option value="completed">완료</option>
<option value="closed">종료</option>
</select>
<input type="date" id="filterStartDate" class="input-field px-3 py-2 rounded-lg text-sm" title="시작일">
<input type="date" id="filterEndDate" class="input-field px-3 py-2 rounded-lg text-sm" title="종료일">
<a id="btnNewReport" href="#" class="ml-auto inline-flex items-center gap-2 px-4 py-2 bg-orange-600 text-white rounded-lg text-sm font-semibold hover:bg-orange-700 transition-colors">
<i class="fas fa-plus"></i>부적합 신고
</a>
</div>
<!-- 신고 목록 -->
<div id="issueList" class="space-y-3">
<div class="bg-white rounded-xl shadow-sm p-8 text-center text-gray-400 text-sm">로딩 중...</div>
</div>
</div>
</div>
</div>
<script src="/static/js/tkfb-core.js?v=2026040102"></script>
<script src="/static/js/tkfb-nonconformity.js"></script>
</body>
</html>

View File

@@ -1,119 +0,0 @@
/* ===== 부적합 현황 (Nonconformity List) ===== */
const CATEGORY_TYPE = 'nonconformity';
const STATUS_LABELS = {
reported: '신고', received: '접수', in_progress: '처리중',
completed: '완료', closed: '종료'
};
const STATUS_BADGE = {
reported: 'badge-blue', received: 'badge-orange', in_progress: 'badge-purple',
completed: 'badge-green', closed: 'badge-gray'
};
function getReportUrl() {
const h = location.hostname;
if (h.includes('technicalkorea.net')) return 'https://tkreport.technicalkorea.net/pages/safety/issue-report.html?type=nonconformity';
return location.protocol + '//' + h + ':30180/pages/safety/issue-report.html?type=nonconformity';
}
function getIssueDetailUrl(reportId) {
const h = location.hostname;
if (h.includes('technicalkorea.net')) return `https://tkreport.technicalkorea.net/pages/safety/issue-detail.html?id=${reportId}&from=nonconformity`;
return `${location.protocol}//${h}:30180/pages/safety/issue-detail.html?id=${reportId}&from=nonconformity`;
}
async function loadStats() {
try {
const data = await api(`/work-issues/stats/summary?category_type=${CATEGORY_TYPE}`);
if (data.success && data.data) {
document.getElementById('statReported').textContent = data.data.reported || 0;
document.getElementById('statReceived').textContent = data.data.received || 0;
document.getElementById('statProgress').textContent = data.data.in_progress || 0;
document.getElementById('statCompleted').textContent = data.data.completed || 0;
}
} catch {
document.getElementById('statsGrid').style.display = 'none';
}
}
async function loadIssues() {
const params = new URLSearchParams();
params.append('category_type', CATEGORY_TYPE);
const status = document.getElementById('filterStatus').value;
const startDate = document.getElementById('filterStartDate').value;
const endDate = document.getElementById('filterEndDate').value;
if (status) params.append('status', status);
if (startDate) params.append('start_date', startDate);
if (endDate) params.append('end_date', endDate);
try {
const data = await api(`/work-issues?${params.toString()}`);
if (data.success) renderIssues(data.data || []);
} catch {
document.getElementById('issueList').innerHTML =
'<div class="bg-white rounded-xl shadow-sm p-8 text-center text-gray-400 text-sm">목록을 불러올 수 없습니다. 잠시 후 다시 시도해주세요.</div>';
}
}
function renderIssues(issues) {
const el = document.getElementById('issueList');
if (!issues.length) {
el.innerHTML = '<div class="bg-white rounded-xl shadow-sm p-8 text-center"><p class="font-semibold text-gray-700 mb-1">등록된 부적합 신고가 없습니다</p><p class="text-sm text-gray-400">새로운 부적합을 신고하려면 \'부적합 신고\' 버튼을 클릭하세요.</p></div>';
return;
}
el.innerHTML = issues.map(issue => {
const reportDate = formatDateTime(issue.report_date);
let loc = escapeHtml(issue.custom_location || '');
if (issue.factory_name) {
loc = escapeHtml(issue.factory_name);
if (issue.workplace_name) loc += ` - ${escapeHtml(issue.workplace_name)}`;
}
const title = escapeHtml(issue.issue_item_name || issue.issue_category_name || '부적합 신고');
const categoryName = escapeHtml(issue.issue_category_name || '부적합');
const reportId = parseInt(issue.report_id) || 0;
const validStatuses = ['reported', 'received', 'in_progress', 'completed', 'closed'];
const safeStatus = validStatuses.includes(issue.status) ? issue.status : 'reported';
const reporter = escapeHtml(issue.reporter_full_name || issue.reporter_name || '-');
const assigned = issue.assigned_full_name ? escapeHtml(issue.assigned_full_name) : '';
const photos = [issue.photo_path1, issue.photo_path2, issue.photo_path3, issue.photo_path4, issue.photo_path5].filter(Boolean);
return `<div class="bg-white rounded-xl shadow-sm p-4 border border-transparent hover:border-orange-200 hover:shadow-md transition-all cursor-pointer" onclick="location.href='${getIssueDetailUrl(reportId)}'">
<div class="flex justify-between items-start mb-2">
<span class="text-sm text-gray-400">#${reportId}</span>
<span class="badge ${STATUS_BADGE[safeStatus] || 'badge-gray'}">${STATUS_LABELS[issue.status] || escapeHtml(issue.status || '-')}</span>
</div>
<div class="mb-2">
<span class="badge badge-orange mr-1 text-xs">${categoryName}</span>
<span class="font-semibold text-gray-800">${title}</span>
</div>
<div class="flex flex-wrap gap-3 text-sm text-gray-500">
<span class="flex items-center gap-1"><i class="fas fa-user text-xs"></i>${reporter}</span>
<span class="flex items-center gap-1"><i class="fas fa-calendar text-xs"></i>${reportDate}</span>
${loc ? `<span class="flex items-center gap-1"><i class="fas fa-map-marker-alt text-xs"></i>${loc}</span>` : ''}
${assigned ? `<span class="flex items-center gap-1"><i class="fas fa-user-cog text-xs"></i>담당: ${assigned}</span>` : ''}
</div>
${photos.length > 0 ? `<div class="flex gap-2 mt-3">${photos.slice(0, 3).map(p => `<img src="${encodeURI(p)}" alt="사진" loading="lazy" class="w-14 h-14 object-cover rounded border border-gray-200">`).join('')}${photos.length > 3 ? `<span class="flex items-center text-sm text-gray-400">+${photos.length - 3}</span>` : ''}</div>` : ''}
</div>`;
}).join('');
}
/* ===== Init ===== */
(async function() {
if (!await initAuth()) return;
// 신고 버튼 URL 설정
document.getElementById('btnNewReport').href = getReportUrl();
// 필터 이벤트
document.getElementById('filterStatus').addEventListener('change', loadIssues);
document.getElementById('filterStartDate').addEventListener('change', loadIssues);
document.getElementById('filterEndDate').addEventListener('change', loadIssues);
await Promise.all([loadStats(), loadIssues()]);
})();