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 검색 중...
-
-
-
-
-
-
-
-
-
-
AI Q&A (과거 사례 기반)
-
-
-
-
-
-
-
- 과거 사례 분석 중...
-
-
-
-
-
-
-
-
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.detail_notes ? `` : ''}
- ${issue.final_description ? `최종 판정:${issue.final_description}
` : ''}
- ${issue.solution ? `` : ''}
- ${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;