/** * domain_selector.js * * 도메인 지식 선택 시스템 * - 폴더 설정 직후 자동으로 도메인 선택 모달 표시 * - 체크박스로 도메인 선택 → 선택된 .txt 합쳐서 서버 전달 * - "세부 분야별" 선택 시 하위 항목 펼침 */ // ===== 상태 ===== let domainConfig = null; // 서버에서 로드한 config let selectedDomains = []; // 선택된 도메인 ID 배열 let domainLoaded = false; // ===== 초기화 ===== async function loadDomainConfig() { try { const resp = await fetch('/api/domain-config'); if (!resp.ok) throw new Error('도메인 설정 로드 실패'); domainConfig = await resp.json(); domainLoaded = true; console.log('[Domain] 설정 로드 완료:', domainConfig.categories.length, '카테고리'); } catch (e) { console.error('[Domain] 설정 로드 실패:', e); // fallback: 빈 config domainConfig = { categories: [] }; } } // 페이지 로드 시 config 가져오기 document.addEventListener('DOMContentLoaded', loadDomainConfig); // ===== 모달 열기/닫기 ===== function openDomainModal() { if (!domainConfig || !domainConfig.categories) { alert('도메인 설정을 불러오는 중입니다. 잠시 후 다시 시도해주세요.'); return; } renderDomainModal(); document.getElementById('domainModal').style.display = 'flex'; } function closeDomainModal() { document.getElementById('domainModal').style.display = 'none'; } // ===== 모달 렌더링 ===== function renderDomainModal() { const container = document.getElementById('domainCategoryList'); if (!container) return; container.innerHTML = ''; domainConfig.categories.forEach(cat => { const catDiv = document.createElement('div'); catDiv.className = 'domain-category'; catDiv.dataset.id = cat.id; // 메인 체크박스 행 const isChecked = selectedDomains.includes(cat.id); catDiv.innerHTML = ` `; // 하위 항목이 있으면 서브 패널 추가 if (cat.children && cat.children.length > 0) { const subPanel = document.createElement('div'); subPanel.className = 'domain-sub-panel'; subPanel.id = `sub_${cat.id}`; subPanel.style.display = isChecked ? 'block' : 'none'; // 그룹별로 묶기 const groups = {}; cat.children.forEach(child => { const g = child.group || '기타'; if (!groups[g]) groups[g] = []; groups[g].push(child); }); Object.entries(groups).forEach(([groupName, children]) => { const groupDiv = document.createElement('div'); groupDiv.className = 'domain-sub-group'; groupDiv.innerHTML = `
${groupName}
`; const chipsDiv = document.createElement('div'); chipsDiv.className = 'domain-sub-chips'; children.forEach(child => { const childChecked = selectedDomains.includes(child.id); chipsDiv.innerHTML += ` `; }); groupDiv.appendChild(chipsDiv); subPanel.appendChild(groupDiv); }); catDiv.appendChild(subPanel); } container.appendChild(catDiv); }); // 선택 요약 업데이트 updateDomainSummary(); } // ===== 선택 로직 ===== function toggleDomainCategory(catId, checked) { const cat = domainConfig.categories.find(c => c.id === catId); if (!cat) return; if (checked) { // 카테고리 추가 if (!selectedDomains.includes(catId)) { selectedDomains.push(catId); } // 하위 항목이 있으면 서브 패널 펼침 if (cat.children && cat.children.length > 0) { const subPanel = document.getElementById(`sub_${catId}`); if (subPanel) subPanel.style.display = 'block'; const expand = document.getElementById(`expand_${catId}`); if (expand) expand.classList.add('open'); } } else { // 카테고리 제거 selectedDomains = selectedDomains.filter(d => d !== catId); // 하위 항목도 전부 제거 if (cat.children) { cat.children.forEach(child => { selectedDomains = selectedDomains.filter(d => d !== child.id); }); const subPanel = document.getElementById(`sub_${catId}`); if (subPanel) subPanel.style.display = 'none'; const expand = document.getElementById(`expand_${catId}`); if (expand) expand.classList.remove('open'); } } renderDomainModal(); } function toggleDomainChild(parentId, childId, checked) { if (checked) { if (!selectedDomains.includes(childId)) { selectedDomains.push(childId); } } else { selectedDomains = selectedDomains.filter(d => d !== childId); } // 칩 UI 업데이트 renderDomainModal(); } // ===== 선택 요약 ===== function updateDomainSummary() { const summaryEl = document.getElementById('domainSummaryText'); if (!summaryEl) return; if (selectedDomains.length === 0) { summaryEl.textContent = '선택된 도메인이 없습니다. AI가 자동으로 분야를 판단합니다.'; summaryEl.className = 'domain-summary-text empty'; return; } // 선택된 항목 이름 수집 const names = []; domainConfig.categories.forEach(cat => { if (selectedDomains.includes(cat.id)) { names.push(cat.label); } if (cat.children) { cat.children.forEach(child => { if (selectedDomains.includes(child.id)) { names.push(child.label); } }); } }); summaryEl.textContent = names.join(', '); summaryEl.className = 'domain-summary-text'; } // ===== 확인 (서버에 전달) ===== async function submitDomainSelection() { if (selectedDomains.length === 0) { // 선택 없으면 step3 자동 분석 모드 closeDomainModal(); updateDomainDisplay('자동 분석 (AI 판단)'); return; } try { const resp = await fetch('/api/domain-combine', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ selected: selectedDomains }) }); const data = await resp.json(); if (data.success) { closeDomainModal(); // 사이드바에 선택 결과 표시 const names = data.selected_names || selectedDomains; updateDomainDisplay(names.join(', ')); console.log('[Domain] 도메인 지식 결합 완료:', data.combined_length, '자'); } else { alert('도메인 지식 결합 실패: ' + (data.error || '알 수 없는 오류')); } } catch (e) { console.error('[Domain] 서버 전달 실패:', e); alert('서버 통신 오류가 발생했습니다.'); } } // ===== 사이드바 표시 업데이트 ===== function updateDomainDisplay(text) { const el = document.getElementById('domainDisplayText'); if (el) { el.textContent = text; el.className = 'domain-display-text' + (text.includes('자동') ? ' auto' : ' selected'); } } // ===== 전체 선택/해제 ===== function selectAllDomains() { selectedDomains = []; domainConfig.categories.forEach(cat => { selectedDomains.push(cat.id); if (cat.children) { cat.children.forEach(child => selectedDomains.push(child.id)); } }); renderDomainModal(); } function clearAllDomains() { selectedDomains = []; renderDomainModal(); } // ===== 폴더 설정 후 자동 호출 ===== // 기존 submitFolder() 함수에서 성공 후 이 함수 호출 function onFolderSetComplete() { // 약간의 딜레이 후 도메인 선택 모달 표시 setTimeout(() => { openDomainModal(); }, 500); }