diff --git a/system3-nonconformance/web/issues-dashboard.html b/system3-nonconformance/web/issues-dashboard.html index 822ae61..2faa1e1 100644 --- a/system3-nonconformance/web/issues-dashboard.html +++ b/system3-nonconformance/web/issues-dashboard.html @@ -115,57 +115,6 @@ - -
-
- -

AI 유사 부적합 검색

-
-
- - -
- - - - -
-
- -

AI Q&A (과거 사례 기반)

-
-
- - -
- - -
-
-
@@ -600,19 +549,6 @@
- - - diff --git a/system3-nonconformance/web/static/js/pages/issues-dashboard.js b/system3-nonconformance/web/static/js/pages/issues-dashboard.js index b2a3860..f4b23ff 100644 --- a/system3-nonconformance/web/static/js/pages/issues-dashboard.js +++ b/system3-nonconformance/web/static/js/pages/issues-dashboard.js @@ -1786,130 +1786,5 @@ document.addEventListener('DOMContentLoaded', function() { } }); -// AI 시맨틱 검색 -async function aiSemanticSearch() { - const query = document.getElementById('aiSearchQuery')?.value?.trim(); - if (!query || typeof AiAPI === 'undefined') return; - - const loading = document.getElementById('aiSearchLoading'); - const results = document.getElementById('aiSearchResults'); - if (loading) loading.classList.remove('hidden'); - if (results) { results.classList.add('hidden'); results.innerHTML = ''; } - - const data = await AiAPI.searchSimilar(query, 8); - if (loading) loading.classList.add('hidden'); - - if (!data.available || !data.results || data.results.length === 0) { - results.innerHTML = '

검색 결과가 없습니다

'; - results.classList.remove('hidden'); - return; - } - - results.innerHTML = data.results.map(r => { - const meta = r.metadata || {}; - const similarity = Math.round((r.similarity || 0) * 100); - const issueId = meta.issue_id || r.id.replace('issue_', ''); - const doc = (r.document || '').substring(0, 100); - const cat = meta.category || ''; - const status = meta.review_status || ''; - return ` -
- ${similarity}% -
-
-
- No.${issueId} - ${cat ? `${cat}` : ''} - ${status ? `${status}` : ''} -
-

${doc}

-
- - `; - }).join(''); - results.classList.remove('hidden'); -} - -// RAG Q&A -async function aiAskQuestion() { - const question = document.getElementById('aiQaQuestion')?.value?.trim(); - if (!question || typeof AiAPI === 'undefined') return; - - const loading = document.getElementById('aiQaLoading'); - const result = document.getElementById('aiQaResult'); - const answer = document.getElementById('aiQaAnswer'); - const sources = document.getElementById('aiQaSources'); - - if (loading) loading.classList.remove('hidden'); - if (result) result.classList.add('hidden'); - - const projectId = document.getElementById('projectFilter')?.value || null; - const data = await AiAPI.askQuestion(question, projectId ? parseInt(projectId) : null); - - if (loading) loading.classList.add('hidden'); - - if (!data.available) { - if (answer) answer.textContent = 'AI 서비스를 사용할 수 없습니다'; - if (result) result.classList.remove('hidden'); - return; - } - - if (answer) answer.textContent = data.answer || ''; - if (sources && data.sources) { - const refs = data.sources.slice(0, 5).map(s => - `No.${s.id}(${s.similarity}%)` - ).join(', '); - sources.textContent = refs ? `참고: ${refs}` : ''; - } - if (result) result.classList.remove('hidden'); -} - -// AI 이슈 상세 모달 -async function showAiIssueModal(issueId) { - const modal = document.getElementById('aiIssueModal'); - const title = document.getElementById('aiIssueModalTitle'); - const body = document.getElementById('aiIssueModalBody'); - if (!modal || !body) return; - - title.textContent = `부적합 No.${issueId}`; - body.innerHTML = '
로딩 중...
'; - modal.classList.remove('hidden'); - - try { - const token = typeof TokenManager !== 'undefined' ? TokenManager.getToken() : null; - const headers = token ? { 'Authorization': `Bearer ${token}` } : {}; - const res = await fetch(`/api/issues/${issueId}`, { headers }); - if (!res.ok) throw new Error('fetch failed'); - const issue = await res.json(); - - const categoryText = typeof getCategoryText === 'function' ? getCategoryText(issue.category || issue.final_category) : (issue.category || issue.final_category || '-'); - const statusText = typeof getStatusText === 'function' ? getStatusText(issue.review_status) : (issue.review_status || '-'); - const deptText = typeof getDepartmentText === 'function' ? getDepartmentText(issue.responsible_department) : (issue.responsible_department || '-'); - - body.innerHTML = ` -
- ${categoryText} - ${statusText} - ${deptText} - ${issue.report_date ? `${issue.report_date}` : ''} -
- ${issue.description ? `
설명:

${issue.description}

` : ''} - ${issue.detail_notes ? `
상세:

${issue.detail_notes}

` : ''} - ${issue.final_description ? `
최종 판정:

${issue.final_description}

` : ''} - ${issue.solution ? `
해결방안:

${issue.solution}

` : ''} - ${issue.cause_detail ? `
원인:

${issue.cause_detail}

` : ''} - ${issue.management_comment ? `
관리 의견:

${issue.management_comment}

` : ''} -
- 관리함에서 보기 → -
- `; - } catch (e) { - body.innerHTML = `

이슈를 불러올 수 없습니다

- 관리함에서 보기 →`; - } -} - // 초기화 initializeDashboardApp(); diff --git a/system3-nonconformance/web/static/js/pages/issues-management.js b/system3-nonconformance/web/static/js/pages/issues-management.js index cdec667..97d45f3 100644 --- a/system3-nonconformance/web/static/js/pages/issues-management.js +++ b/system3-nonconformance/web/static/js/pages/issues-management.js @@ -456,6 +456,18 @@ function createInProgressRow(issue, project) { 해결방안 (확정) + ${!isPendingCompletion ? ` + + + ` : ''}
@@ -984,6 +996,48 @@ async function aiSuggestSolution() { if (result) result.classList.remove('hidden'); } +// RAG: AI 해결방안 제안 (인라인 카드용) +async function aiSuggestSolutionInline(issueId) { + if (typeof AiAPI === 'undefined') return; + const btn = event.target.closest('button'); + const result = document.getElementById(`aiSuggestResult_${issueId}`); + const content = document.getElementById(`aiSuggestContent_${issueId}`); + const sources = document.getElementById(`aiSuggestSources_${issueId}`); + + if (btn) { btn.disabled = true; btn.innerHTML = 'AI 분석 중...'; } + if (result) result.classList.add('hidden'); + + const data = await AiAPI.suggestSolution(issueId); + + if (btn) { btn.disabled = false; btn.innerHTML = 'AI 해결방안 제안 (과거 사례 기반)'; } + + if (!data.available) { + if (content) content.textContent = 'AI 서비스를 사용할 수 없습니다'; + if (result) result.classList.remove('hidden'); + return; + } + + if (content) content.textContent = data.suggestion || ''; + if (sources && data.referenced_issues) { + const refs = data.referenced_issues + .filter(r => r.has_solution) + .map(r => `No.${r.id}(${r.similarity}%)`) + .join(', '); + sources.textContent = refs ? `참고 사례: ${refs}` : ''; + } + if (result) result.classList.remove('hidden'); +} + +// AI 제안 → 해결방안 textarea에 적용 +function applyAiSuggestion(issueId) { + const content = document.getElementById(`aiSuggestContent_${issueId}`); + const textarea = document.getElementById(`management_comment_${issueId}`); + if (content && textarea) { + textarea.value = content.textContent; + textarea.focus(); + } +} + // AI 유사 부적합 검색 async function loadSimilarIssues() { if (!currentModalIssueId || typeof AiAPI === 'undefined') return;