/** * Project Master Overseas Mail Management JS * 기능: 첨부파일 로드, AI 분석, 메일 목록 렌더링, 미리보기, 주소록 관리 */ let currentFiles = []; let editingIndex = -1; const HIERARCHY = { "행정": { "계약": ["계약관리", "기성관리", "업무지시서", "인원관리"], "업무관리": ["업무일지(2025)", "업무일지(2025년 이전)", "발주처 정기보고", "본사업무보고", "공사감독일지", "양식서류"] }, "설계성과품": { "시방서": ["공사시방서"], "설계도면": ["공통", "토공", "비탈면안전공", "배수공", "교량공", "포장공"], "수량산출서": ["토공", "배수공"], "내역서": ["단가산출서"], "보고서": ["실시설계보고서", "지반조사보고서"], "측량계산부": ["측량계산부"], "설계단계 수행협의": ["회의·협의"] }, "시공검측": { "토공": ["검측 (깨기)", "검측 (노체)"], "배수공": ["검측 (V형측구)", "검측 (종배수관)"], "구조물공": ["검측 (평목교)"], "포장공": ["검측 (기층)"] }, "설계변경": { "실정보고": ["토공", "배수공", "안전관리"], "기술지원 검토": ["토공", "구조물&부대공"] } }; const MAIL_SAMPLES = { inbound: [ { person: "라오스 농림부", email: "pany.s@lao.gov.la", time: "2026-03-05", title: "ITTC 교육센터 착공식 일정 협의", summary: "착공식 관련하여 정부 측 인사의 일정을 반영한 최종 공문을 송부합니다.", active: true }, { person: "현대건설 (김철수 소장)", email: "cs.kim@hdec.co.kr", time: "2026-03-04", title: "[긴급] 어천-공주(4차) 하도급 변경계약 통보", summary: "철거공사 물량 변동에 따른 계약 금액 조정 건입니다. 검토 후 승인 부탁드립니다.", active: false } ], outbound: [ { person: "공사관리부 (본사)", email: "hq_pm@projectmaster.com", time: "2026-03-04", title: "어천-공주 2월 월간 공정보고서 제출", summary: "2월 한 달간의 주요 공정 및 예산 집행 현황 보고서입니다.", active: false } ], drafts: [], deleted: [] }; let currentMailTab = 'inbound'; let filteredMails = []; // --- 첨부파일 데이터 로드 및 렌더링 --- async function loadAttachments() { try { const res = await fetch(API.ATTACHMENTS); currentFiles = await res.json(); renderFiles(); } catch (e) { console.error("Failed to load attachments:", e); } } function renderFiles() { const isAiActive = document.getElementById('aiToggle').checked; const container = document.getElementById('attachmentList'); if (!container) return; container.innerHTML = ''; currentFiles.forEach((file, index) => { const item = document.createElement('div'); item.className = 'attachment-item-wrap'; item.style.marginBottom = "8px"; let pathText = "경로를 선택해주세요"; let modeClass = "manual-mode"; if (file.analysis) { const prefix = file.analysis.isManual ? "선택 경로: " : "추천: "; pathText = `${prefix}${file.analysis.suggested_path}`; modeClass = file.analysis.isManual ? "manual-mode" : "smart-mode"; } else if (isAiActive) { pathText = "AI 분석 대기 중..."; modeClass = "smart-mode"; } item.innerHTML = `
📄
${file.name}
${file.size}
${pathText} ${isAiActive ? `` : ''}
`; container.appendChild(item); }); } // --- AI 분석 실행 --- async function startAnalysis(index, event) { if (event) event.stopPropagation(); const file = currentFiles[index]; if (!file) return; // UI 상태 업데이트: 분석 중 표시 const logArea = document.getElementById(`log-area-${index}`); const logContent = document.getElementById(`log-content-${index}`); if (logArea) logArea.classList.add('active'); if (logContent) { logContent.innerHTML = `
AI가 문서를 정밀 분석 중입니다...
`; } try { const res = await fetch(`${API.ANALYZE_FILE}?filename=${encodeURIComponent(file.name)}`); const result = await res.json(); if (result.error) { if (logContent) logContent.innerHTML = `
오류: ${result.error}
`; return; } // 분석 결과 저장 및 UI 갱신 currentFiles[index].analysis = result.final_result; currentFiles[index].analysis.isManual = false; if (logContent) { logContent.innerHTML = `
✨ AI 분석 완료
${result.final_result.reason}
`; } renderFiles(); } catch (e) { console.error("AI Analysis failed:", e); if (logContent) logContent.innerHTML = `
분석 실패: 네트워크 오류가 발생했습니다.
`; } } // --- 미리보기 제어 --- function showPreview(index, event) { if (event && (event.target.closest('.btn-group') || event.target.closest('.path-display'))) return; const file = currentFiles[index]; if (!file) return; const previewArea = document.getElementById('mailPreviewArea'); const toggleIcon = document.getElementById('previewToggleIcon'); const fullViewBtn = document.getElementById('fullViewBtn'); const previewContainer = document.getElementById('previewContainer'); if (previewArea) { previewArea.classList.add('active'); if (toggleIcon) toggleIcon.innerText = '▶'; } const fileUrl = Utils.getSafeFileUrl(file.name); if (fullViewBtn) { fullViewBtn.style.display = 'block'; fullViewBtn.onclick = () => window.open(fileUrl, 'PMFullView', 'width=1000,height=800'); } if (file.name.toLowerCase().endsWith('.pdf')) { previewContainer.innerHTML = ``; } else { previewContainer.innerHTML = `
${file.name}
`; } document.querySelectorAll('.attachment-item').forEach(item => item.classList.remove('active')); if (event?.currentTarget) event.currentTarget.classList.add('active'); } function togglePreviewAuto() { const area = document.getElementById('mailPreviewArea'); const icon = document.getElementById('previewToggleIcon'); if (area) { const isActive = area.classList.toggle('active'); if (icon) icon.innerText = isActive ? '▶' : '◀'; } } // --- 메일 리스트 제어 --- function renderMailList(tabType, mailsToShow = null) { currentMailTab = tabType; const container = document.querySelector('.mail-items-container'); if (!container) return; const mails = mailsToShow || MAIL_SAMPLES[tabType] || []; filteredMails = mails; updateBulkActionBar(); container.innerHTML = mails.map((mail, idx) => `
${mail.person}
${mail.time}
${mail.title}
${mail.summary}
`).join(''); const activeIdx = mails.findIndex(m => m.active); if (activeIdx !== -1) updateMailContent(mails[activeIdx]); } function selectMailItem(el, index) { document.querySelectorAll('.mail-item').forEach(item => item.classList.remove('active')); el.classList.add('active'); const mail = filteredMails[index]; if (mail) updateMailContent(mail); } function updateMailContent(mail) { const title = document.querySelector('.mail-content-header h2'); if (title) title.innerText = mail.title; document.querySelector('.mail-body').innerHTML = mail.summary.replace(/\n/g, '
') + "

본 내용은 샘플 데이터입니다."; } function switchMailTab(el, tabType) { document.querySelectorAll('.mail-tab').forEach(tab => tab.classList.remove('active')); el.classList.add('active'); renderMailList(tabType); } // --- 경로 선택 모달 --- function openPathModal(index, event) { if (event) event.stopPropagation(); editingIndex = index; const tabSelect = document.getElementById('tabSelect'); if (tabSelect) { tabSelect.innerHTML = Object.keys(HIERARCHY).map(tab => ``).join(''); updateCategories(); ModalManager.open('pathModal'); } } function updateCategories() { const tab = document.getElementById('tabSelect').value; document.getElementById('categorySelect').innerHTML = Object.keys(HIERARCHY[tab]).map(cat => ``).join(''); updateSubs(); } function updateSubs() { const tab = document.getElementById('tabSelect').value; const cat = document.getElementById('categorySelect').value; document.getElementById('subSelect').innerHTML = HIERARCHY[tab][cat].map(sub => ``).join(''); } function applyPathSelection() { const path = `${document.getElementById('tabSelect').value} > ${document.getElementById('categorySelect').value} > ${document.getElementById('subSelect').value}`; if (!currentFiles[editingIndex].analysis) currentFiles[editingIndex].analysis = {}; currentFiles[editingIndex].analysis.suggested_path = path; currentFiles[editingIndex].analysis.isManual = true; renderFiles(); ModalManager.close('pathModal'); } // --- 주소록 관리 --- let addressBookData = [ { name: "이태훈", dept: "PM Overseas / 선임연구원", email: "th.lee@projectmaster.com", phone: "010-1234-5678" }, { name: "Pany S.", dept: "라오스 농림부 / 국장", email: "pany.s@lao.gov.la", phone: "+856-20-1234-5678" } ]; let contactEditingIndex = -1; function openAddressBook() { renderAddressBook(); ModalManager.open('addressBookModal'); } function closeAddressBook() { ModalManager.close('addressBookModal'); } function renderAddressBook() { const body = document.getElementById('addressBookBody'); if (!body) return; body.innerHTML = addressBookData.map((c, idx) => ` ${c.name}${c.dept}${c.email}${c.phone} `).join(''); } function toggleAddContactForm() { const form = document.getElementById('addContactForm'); if (form.style.display === 'none') form.style.display = 'block'; else { form.style.display = 'none'; contactEditingIndex = -1; } } function editContact(index) { const c = addressBookData[index]; contactEditingIndex = index; document.getElementById('newContactName').value = c.name; document.getElementById('newContactDept').value = c.dept; document.getElementById('newContactEmail').value = c.email; document.getElementById('newContactPhone').value = c.phone; document.getElementById('addContactForm').style.display = 'block'; } function deleteContact(index) { if (confirm(`'${addressBookData[index].name}'님을 삭제하시겠습니까?`)) { addressBookData.splice(index, 1); renderAddressBook(); } } function addContact() { const name = document.getElementById('newContactName').value; if (!name) return alert("이름을 입력해주세요."); const data = { name, dept: document.getElementById('newContactDept').value, email: document.getElementById('newContactEmail').value, phone: document.getElementById('newContactPhone').value }; if (contactEditingIndex > -1) addressBookData[contactEditingIndex] = data; else addressBookData.push(data); renderAddressBook(); toggleAddContactForm(); } // --- 공통 액션 --- function updateBulkActionBar() { const count = document.querySelectorAll('.mail-item-checkbox:checked').length; const bar = document.getElementById('mailBulkActions'); if (count > 0) { bar.classList.add('active'); document.getElementById('selectedCount').innerText = `${count}개 선택됨`; } else bar.classList.remove('active'); } // 초기화 document.addEventListener('DOMContentLoaded', () => { loadAttachments(); renderMailList('inbound'); });