- ai-service: Ollama 기반 AI 서비스 (분류, 시맨틱 검색, RAG Q&A, 패턴 분석) - AI 어시스턴트 페이지: 채팅형 Q&A, 시맨틱 검색, 패턴 분석, 분류 테스트 - 권한 시스템에 ai_assistant 페이지 등록 (기본 비활성) - 기존 페이지에 AI 기능 통합 (대시보드, 수신함, 관리함) - docker-compose, gateway, nginx 설정 업데이트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
351 lines
19 KiB
HTML
351 lines
19 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ko">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>관리함 - 작업보고서</title>
|
|
<script>if(window.innerWidth<=768)window.location.replace('/m/management.html');</script>
|
|
|
|
<!-- Tailwind CSS -->
|
|
<link rel="preload" href="https://cdn.tailwindcss.com" as="script">
|
|
<script src="https://cdn.tailwindcss.com"></script>
|
|
|
|
<!-- Font Awesome -->
|
|
<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/mobile-calendar.css">
|
|
|
|
<!-- 공통 스타일 및 페이지 전용 스타일 -->
|
|
<link rel="stylesheet" href="/static/css/tkqc-common.css?v=20260213">
|
|
<link rel="stylesheet" href="/static/css/issues-management.css?v=20260213">
|
|
</head>
|
|
<body>
|
|
<!-- 공통 헤더가 여기에 자동으로 삽입됩니다 -->
|
|
|
|
<!-- Main Content -->
|
|
<main class="container mx-auto px-4 py-8" style="padding-top: 72px;">
|
|
<!-- 페이지 헤더 -->
|
|
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<div>
|
|
<h1 class="text-2xl font-bold text-gray-900 flex items-center">
|
|
<i class="fas fa-cog text-green-500 mr-3"></i>
|
|
관리함
|
|
</h1>
|
|
<p class="text-gray-600 mt-1">부적합 사항을 처리하고 상태를 관리하세요</p>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<!-- 프로젝트 필터 및 상태 탭 -->
|
|
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
|
|
<div class="space-y-4">
|
|
<!-- 프로젝트 선택 -->
|
|
<div class="max-w-md">
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">📁 프로젝트</label>
|
|
<select id="projectFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
|
<option value="">전체 프로젝트</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 상태 탭 및 추가 정보 버튼 -->
|
|
<div class="flex items-center justify-between">
|
|
<div class="flex space-x-1 bg-gray-100 p-1 rounded-lg max-w-md">
|
|
<button id="inProgressTab"
|
|
class="flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 bg-blue-500 text-white"
|
|
onclick="switchTab('in_progress')">
|
|
<i class="fas fa-cog mr-2"></i>진행 중
|
|
</button>
|
|
<button id="completedTab"
|
|
class="flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 text-gray-600 hover:text-gray-900"
|
|
onclick="switchTab('completed')">
|
|
<i class="fas fa-check-circle mr-2"></i>완료됨
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 추가 정보 입력 버튼 (진행 중 탭에서만 표시) -->
|
|
<button id="additionalInfoBtn"
|
|
class="px-4 py-2 bg-orange-500 text-white text-sm font-medium rounded-lg hover:bg-orange-600 transition-colors duration-200 shadow-sm"
|
|
onclick="openAdditionalInfoModal()"
|
|
style="display: none;">
|
|
<i class="fas fa-plus-circle mr-2"></i>추가 정보 입력
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 프로젝트별 통계 -->
|
|
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
|
|
<div class="bg-gray-50 p-4 rounded-lg">
|
|
<div class="flex items-center">
|
|
<i class="fas fa-chart-bar text-gray-500 text-xl mr-3"></i>
|
|
<div>
|
|
<p class="text-sm text-gray-600">총 부적합</p>
|
|
<p class="text-2xl font-bold text-gray-700" id="totalCount">0</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="bg-blue-50 p-4 rounded-lg">
|
|
<div class="flex items-center">
|
|
<i class="fas fa-cog text-blue-500 text-xl mr-3"></i>
|
|
<div>
|
|
<p class="text-sm text-blue-600">진행 중</p>
|
|
<p class="text-2xl font-bold text-blue-700" id="inProgressCount">0</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="bg-purple-50 p-4 rounded-lg">
|
|
<div class="flex items-center">
|
|
<i class="fas fa-hourglass-half text-purple-500 text-xl mr-3"></i>
|
|
<div>
|
|
<p class="text-sm text-purple-600">완료 대기</p>
|
|
<p class="text-2xl font-bold text-purple-700" id="pendingCompletionCount">0</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="bg-green-50 p-4 rounded-lg">
|
|
<div class="flex items-center">
|
|
<i class="fas fa-check-circle text-green-500 text-xl mr-3"></i>
|
|
<div>
|
|
<p class="text-sm text-green-600">완료됨</p>
|
|
<p class="text-2xl font-bold text-green-700" id="completedCount">0</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 부적합 관리 목록 -->
|
|
<div class="bg-white rounded-xl shadow-sm">
|
|
<div class="p-6 border-b border-gray-200">
|
|
<div class="flex items-center justify-between">
|
|
<h2 class="text-lg font-semibold text-gray-800">부적합 관리</h2>
|
|
<div class="flex items-center space-x-4">
|
|
<select id="sortOrder" class="text-sm border border-gray-300 rounded px-2 py-1" onchange="sortIssues()">
|
|
<option value="newest">최신순</option>
|
|
<option value="oldest">오래된순</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="issuesList" class="p-4">
|
|
<!-- 날짜별 그룹화된 부적합 목록이 여기에 동적으로 생성됩니다 -->
|
|
</div>
|
|
|
|
<!-- 빈 상태 -->
|
|
<div id="emptyState" class="hidden p-12 text-center">
|
|
<i class="fas fa-cog text-6xl text-gray-300 mb-4"></i>
|
|
<h3 class="text-lg font-medium text-gray-900 mb-2">관리할 부적합이 없습니다</h3>
|
|
<p class="text-gray-500">처리가 필요한 부적합이 있으면 여기에 표시됩니다.</p>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<!-- 완료된 이슈 상세보기 모달 -->
|
|
<div id="issueDetailModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50">
|
|
<div class="flex items-center justify-center min-h-screen p-4">
|
|
<div class="bg-white rounded-xl max-w-4xl w-full max-h-[90vh] overflow-y-auto">
|
|
<div class="p-6">
|
|
<!-- 모달 헤더 -->
|
|
<div class="flex items-center justify-between mb-6">
|
|
<h2 class="text-xl font-semibold text-gray-900" id="modalTitle">부적합 상세 정보</h2>
|
|
<button onclick="closeIssueDetailModal()" class="text-gray-400 hover:text-gray-600">
|
|
<i class="fas fa-times text-xl"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 모달 내용 -->
|
|
<div id="modalContent" class="space-y-6">
|
|
<!-- 동적으로 생성될 내용 -->
|
|
</div>
|
|
|
|
<!-- AI 유사 부적합 패널 -->
|
|
<div id="aiSimilarPanel" class="mt-6 border-t pt-6 hidden">
|
|
<div class="flex items-center justify-between mb-3">
|
|
<h3 class="text-sm font-semibold text-gray-700">
|
|
<i class="fas fa-robot text-purple-500 mr-2"></i>AI 유사 부적합
|
|
</h3>
|
|
<button id="aiSimilarRefresh" onclick="loadSimilarIssues()" class="text-xs text-purple-500 hover:text-purple-700">
|
|
<i class="fas fa-sync-alt mr-1"></i>검색
|
|
</button>
|
|
</div>
|
|
<div id="aiSimilarLoading" class="hidden text-center py-4">
|
|
<i class="fas fa-spinner fa-spin text-purple-500 mr-2"></i>
|
|
<span class="text-sm text-gray-500">유사 이슈 검색 중...</span>
|
|
</div>
|
|
<div id="aiSimilarResults" class="space-y-2">
|
|
<!-- 유사 이슈 목록 -->
|
|
</div>
|
|
<div id="aiSimilarEmpty" class="hidden text-center py-3">
|
|
<p class="text-sm text-gray-400">유사한 부적합이 없습니다</p>
|
|
</div>
|
|
|
|
<!-- RAG 해결방안 제안 -->
|
|
<div class="mt-4 pt-3 border-t border-purple-100">
|
|
<button id="aiSuggestSolutionBtn" onclick="aiSuggestSolution()"
|
|
class="w-full px-3 py-2 bg-gradient-to-r from-purple-500 to-indigo-500 text-white text-sm rounded-lg hover:from-purple-600 hover:to-indigo-600 transition-all">
|
|
<i class="fas fa-lightbulb mr-2"></i>AI 해결방안 제안 (과거 사례 기반)
|
|
</button>
|
|
<div id="aiSuggestLoading" class="hidden mt-2 text-center py-3">
|
|
<i class="fas fa-spinner fa-spin text-purple-500 mr-1"></i>
|
|
<span class="text-xs text-gray-500">과거 사례 분석 중...</span>
|
|
</div>
|
|
<div id="aiSuggestResult" class="hidden mt-2 bg-indigo-50 border border-indigo-200 rounded-lg p-3">
|
|
<div id="aiSuggestContent" class="text-sm text-gray-700 whitespace-pre-line"></div>
|
|
<div id="aiSuggestSources" class="mt-2 text-xs text-indigo-500"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 모달 푸터 -->
|
|
<div class="flex justify-end space-x-3 mt-6 pt-6 border-t">
|
|
<button onclick="closeIssueDetailModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">
|
|
취소
|
|
</button>
|
|
<button onclick="saveModalChanges()" class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600">
|
|
저장
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 상태 변경 모달 -->
|
|
<div id="statusModal" class="fixed inset-0 bg-black bg-opacity-50 modal hidden z-50">
|
|
<div class="flex items-center justify-center min-h-screen p-4">
|
|
<div class="bg-white rounded-xl max-w-md w-full p-6">
|
|
<div class="flex items-center justify-between mb-4">
|
|
<h3 class="text-lg font-semibold text-gray-900">상태 변경</h3>
|
|
<button onclick="closeStatusModal()" class="text-gray-400 hover:text-gray-600">
|
|
<i class="fas fa-times"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<div class="space-y-4">
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">새 상태</label>
|
|
<select id="newStatus" class="w-full px-3 py-2 border border-gray-300 rounded-lg">
|
|
<option value="processing">처리 중</option>
|
|
<option value="pending">대기 중</option>
|
|
<option value="completed">완료</option>
|
|
</select>
|
|
</div>
|
|
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">처리 메모</label>
|
|
<textarea id="statusNote" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg"
|
|
placeholder="상태 변경 사유나 처리 내용을 입력하세요..."></textarea>
|
|
</div>
|
|
|
|
<div class="flex justify-end space-x-3">
|
|
<button onclick="closeStatusModal()" class="px-4 py-2 text-gray-600 hover:text-gray-800">
|
|
취소
|
|
</button>
|
|
<button onclick="updateStatus()" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600">
|
|
변경
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 추가 정보 입력 모달 -->
|
|
<div id="additionalInfoModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center">
|
|
<div class="bg-white rounded-xl shadow-xl max-w-md w-full mx-4 max-h-[90vh] overflow-y-auto">
|
|
<div class="p-6">
|
|
<!-- 모달 헤더 -->
|
|
<div class="flex items-center justify-between mb-6">
|
|
<h3 class="text-lg font-semibold text-gray-900">
|
|
<i class="fas fa-info-circle text-orange-500 mr-2"></i>
|
|
추가 정보 입력
|
|
</h3>
|
|
<button onclick="closeAdditionalInfoModal()" class="text-gray-400 hover:text-gray-600 transition-colors">
|
|
<i class="fas fa-times text-xl"></i>
|
|
</button>
|
|
</div>
|
|
|
|
<!-- 모달 내용 -->
|
|
<form id="additionalInfoForm" class="space-y-4">
|
|
<!-- 원인부서 -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">
|
|
<i class="fas fa-building text-gray-500 mr-1"></i>
|
|
원인부서
|
|
</label>
|
|
<select id="causeDepartment" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500">
|
|
<option value="">선택하세요</option>
|
|
<option value="production">생산</option>
|
|
<option value="quality">품질</option>
|
|
<option value="purchasing">구매</option>
|
|
<option value="design">설계</option>
|
|
<option value="sales">영업</option>
|
|
</select>
|
|
</div>
|
|
|
|
<!-- 해당자 상세 -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">
|
|
<i class="fas fa-user text-gray-500 mr-1"></i>
|
|
해당자 상세
|
|
</label>
|
|
<input type="text" id="responsiblePersonDetail"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500"
|
|
placeholder="해당자 이름, 직책 등 상세 정보">
|
|
</div>
|
|
|
|
<!-- 원인 상세 -->
|
|
<div>
|
|
<label class="block text-sm font-medium text-gray-700 mb-2">
|
|
<i class="fas fa-clipboard-list text-gray-500 mr-1"></i>
|
|
원인 상세
|
|
</label>
|
|
<textarea id="causeDetail" rows="4"
|
|
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-orange-500 focus:border-orange-500 resize-none"
|
|
placeholder="원인에 대한 상세한 설명을 입력하세요"></textarea>
|
|
</div>
|
|
|
|
<!-- 안내 메시지 -->
|
|
<div class="bg-orange-50 border border-orange-200 rounded-lg p-3">
|
|
<div class="flex items-start">
|
|
<i class="fas fa-info-circle text-orange-500 mt-0.5 mr-2"></i>
|
|
<div class="text-sm text-orange-700">
|
|
<p class="font-medium mb-1">기록용 정보</p>
|
|
<p>이 정보는 내부 기록용으로만 사용되며, 모든 필드는 선택사항입니다.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 버튼 -->
|
|
<div class="flex space-x-3 pt-4">
|
|
<button type="button" onclick="closeAdditionalInfoModal()"
|
|
class="flex-1 px-4 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors">
|
|
취소
|
|
</button>
|
|
<button type="submit"
|
|
class="flex-1 px-4 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 transition-colors">
|
|
<i class="fas fa-save mr-2"></i>저장
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Scripts -->
|
|
<script src="/static/js/date-utils.js?v=20260213"></script>
|
|
<script src="/static/js/core/permissions.js?v=20260306"></script>
|
|
<script src="/static/js/components/common-header.js?v=20260306"></script>
|
|
<script src="/static/js/core/page-manager.js?v=20260306"></script>
|
|
<script src="/static/js/utils/issue-helpers.js?v=20260306"></script>
|
|
<script src="/static/js/utils/photo-modal.js?v=20260306"></script>
|
|
<script src="/static/js/utils/toast.js?v=20260306"></script>
|
|
<script src="/static/js/components/mobile-bottom-nav.js?v=20260306"></script>
|
|
<script src="/static/js/api.js?v=20260306"></script>
|
|
<script src="/static/js/pages/issues-management.js?v=20260306"></script>
|
|
</body>
|
|
</html>
|