This commit is contained in:
2026-02-26 17:57:38 +09:00
parent 130ea35d29
commit 909340ff76

View File

@@ -13,33 +13,81 @@
<ul class="nav-list">
<li class="nav-item" onclick="location.href='/dashboard'">대시보드</li>
<li class="nav-item active" onclick="location.href='/mailTest'">메일관리</li>
<li class="nav-item">로그관리</li>
<li class="nav-item">파일관리</li>
</ul>
</nav>
<div class="mail-wrapper">
<aside class="mail-sidebar">
<select class="project-select"><option>라오스 ITTC 관개 교육센터</option></select>
<ul class="folder-list"><li class="folder-item active"><span>📥 수신함</span></li></ul>
<select class="project-select">
<option>라오스 ITTC 관개 교육센터</option>
<option>베트남 푸옥호아 발전소</option>
</select>
<ul class="folder-list">
<li class="folder-item active"><span>📥 수신함</span><span>12</span></li>
<li class="folder-item"><span>📤 발신함</span></li>
<li class="folder-item"><span>📁 중요메일</span></li>
</ul>
</aside>
<section class="mail-list-area">
<div class="mail-items-container"><div class="mail-item active"><div>라오스 농림부</div><div>ITTC 교육센터 착공식 일정 협의</div></div></div>
<div class="search-bar">
<input type="text" placeholder="제목, 내용, 기관 검색...">
<div style="display:flex; gap:4px;">
<select style="flex:1; padding:4px; font-size:11px;"><option>모든 상대기관</option></select>
<select style="flex:1; padding:4px; font-size:11px;"><option>전체 기간</option></select>
</div>
</div>
<div class="mail-items-container">
<div class="mail-item active">
<div style="display:flex; justify-content:space-between; margin-bottom:4px;">
<span style="font-weight:700; color:var(--primary-color);">라오스 농림부</span>
<span style="font-size:11px; color:var(--text-sub);">오후 2:30</span>
</div>
<div style="font-weight:600; font-size:12px; margin-bottom:4px;">ITTC 교육센터 착공식 일정 협의</div>
<div style="font-size:11px; color:var(--text-sub); display:-webkit-box; -webkit-line-clamp:2; -webkit-box-orient:vertical; overflow:hidden;">안녕하세요. 착공식 관련하여 첨부 드리는 공문을...</div>
</div>
</div>
</section>
<section class="mail-content-area">
<div class="mail-content-header">
<h2 style="font-size:18px; color:var(--primary-color); margin-bottom:8px;">ITTC 교육센터 착공식 일정 협의 요청</h2>
<div style="font-size:12px; color:var(--text-sub);"><strong>보낸사람</strong> pany.s@lao.gov.la (라오스 농림부)</div>
<div style="font-size:12px; color:var(--text-sub);"><strong>날짜</strong> 2026년 2월 26일 14:30</div>
</div>
<div class="mail-body">
안녕하세요. 이태훈 선임연구원님.<br><br>
라오스 ITTC 관개 교육센터 착공식과 관련하여 정부 측 인사의 일정을 반영한 최종 공문을 송부합니다.
</div>
<div class="attachment-area">
<div style="display:flex; justify-content:space-between;">
<div>첨부파일 리스트</div>
<div class="ai-toggle-wrap"><span class="ai-label">AI 판단</span><label class="switch"><input type="checkbox" id="aiToggle" checked onchange="renderFiles()"><span class="slider"></span></label></div>
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:12px;">
<div style="font-weight:700; font-size:13px;">첨부파일 리스트</div>
<div class="ai-toggle-wrap">
<span class="ai-label">AI 판단</span>
<label class="switch">
<input type="checkbox" id="aiToggle" checked onchange="renderFiles()">
<span class="slider"></span>
</label>
</div>
</div>
<div id="attachmentList"></div>
</div>
</section>
</div>
<script>
let currentFiles = [];
async function loadAttachments() {
const res = await fetch('/attachments');
currentFiles = await res.json();
renderFiles();
try {
const res = await fetch('/attachments');
currentFiles = await res.json();
renderFiles();
} catch (e) { console.error(e); }
}
function renderFiles() {
const isAiActive = document.getElementById('aiToggle').checked;
const container = document.getElementById('attachmentList');
@@ -47,10 +95,18 @@
currentFiles.forEach((file, index) => {
const item = document.createElement('div');
item.className = 'attachment-item-wrap';
item.style.marginBottom = "8px";
const btnAiClass = isAiActive ? 'btn-ai' : 'btn-normal';
item.innerHTML = `
<div class="attachment-item">
<div class="file-info"><span>📄</span><div>${file.name}</div><span id="recommend-${index}" class="ai-recommend" style="display:none;"></span></div>
<div class="file-info">
<span style="font-size:20px;">📄</span>
<div>
<div style="font-size:12px; font-weight:700;">${file.name}</div>
<div style="font-size:10px; color:var(--text-sub);">${file.size}</div>
</div>
<span id="recommend-${index}" class="ai-recommend" style="display:none;">분석 대기 중...</span>
</div>
<div class="btn-group">
<button class="btn-upload ${btnAiClass}" onclick="startAnalysis(${index})">AI 분석</button>
<button class="btn-upload btn-normal" onclick="confirmUpload(${index})">파일 업로드</button>
@@ -61,25 +117,45 @@
container.appendChild(item);
});
}
async function startAnalysis(index) {
const file = currentFiles[index];
const logArea = document.getElementById(`log-area-${index}`);
const logContent = document.getElementById(`log-content-${index}`);
const recLabel = document.getElementById(`recommend-${index}`);
logArea.classList.add('active');
logContent.innerHTML = '>>> 분석 가동...';
logContent.innerHTML = '<div class="log-line log-info">>>> 3중 레이어 AI 엔진 가동...</div>';
recLabel.style.display = 'inline-block';
recLabel.innerText = '분석 중...';
const res = await fetch(`/analyze-file?filename=${encodeURIComponent(file.name)}`);
const analysis = await res.json();
recLabel.innerText = `추천: ${analysis.suggested_path}`;
logContent.innerHTML = `[결과] ${analysis.suggested_path}<br>└ ${analysis.reason}`;
currentFiles[index].analysis = analysis;
try {
const res = await fetch(`/analyze-file?filename=${encodeURIComponent(file.name)}`);
const analysis = await res.json();
analysis.log_steps.forEach(step => {
const line = document.createElement('div');
line.className = 'log-line';
line.innerText = " " + step;
logContent.appendChild(line);
});
const resLine = document.createElement('div');
resLine.className = 'log-line log-success';
resLine.style.marginTop = "8px";
resLine.innerHTML = `[결과] ${analysis.suggested_path}<br>└ 근거: ${analysis.reason}`;
logContent.appendChild(resLine);
const details = document.createElement('details');
details.innerHTML = `<summary style="color:#da8cf1; cursor:pointer; font-size:10px; margin-top:5px;">[추출 원본 데이터 보기]</summary><div style="color:#a0aec0; padding:8px; background:#2d3748; margin-top:5px; white-space:pre-wrap; max-height:150px; overflow-y:auto; border-radius:4px; font-size:10px;">${analysis.raw_text}</div>`;
logContent.appendChild(details);
recLabel.innerText = `추천: ${analysis.suggested_path}`;
if(analysis.suggested_path === "분석실패") {
recLabel.style.color = "#f21d0d"; recLabel.style.background = "#fee9e7";
}
currentFiles[index].analysis = analysis;
} catch (e) { logContent.innerHTML += '<div class="log-line">ERR: 서버 오류</div>'; }
}
function confirmUpload(index) {
const file = currentFiles[index];
const path = file.analysis ? file.analysis.suggested_path : "선택한 탭";
if (confirm(`[${file.name}] 파일을 [${path}]로 업로드하시겠습니까?`)) alert("완료");
if (confirm(`[${file.name}] 파일을 [${path}] 위치로 업로드하시겠습니까?`)) alert("완료되었습니다.");
}
loadAttachments();
</script>