diff --git a/templates/pages/repo.html b/templates/pages/repo.html index bcab9b5..d5da539 100644 --- a/templates/pages/repo.html +++ b/templates/pages/repo.html @@ -51,9 +51,9 @@ border: 1px solid #fde68a; } @media print { - nav, footer, #review-actions, #btn-review, #btn-toggle-diff, + nav, footer, #review-actions, #btn-review, .note-save-indicator, select, input, #review-progress, - #diff-review-container, #history-select, + #history-select, label[for="base-ref"], label[for="head-ref"], label[for="top-n"], label[for="concurrency"] { display: none !important; } @@ -139,9 +139,6 @@
-
@@ -183,28 +180,6 @@ @@ -275,12 +250,15 @@
- @@ -626,109 +594,15 @@ return Markdown.render(text); } - // ── Inline AI Review (quick review in Diff tab) ───────────────── - - let inlineReviewSSE = null; - let inlineSuggestions = []; - - function startInlineReview() { - const base = document.getElementById('select-base').value; - const head = document.getElementById('select-head').value; - if (!base || !head) { - showToast('č¯ˇå…ˆé€‰æ‹Š Base 和 Head åšļæŸĨįœ‹ Diff', 'warning'); - return; - } - - // Cancel previous if running - if (inlineReviewSSE) { - inlineReviewSSE.abort(); - } - - const btn = document.getElementById('btn-inline-review'); - const progress = document.getElementById('review-progress'); - const summary = document.getElementById('review-summary'); - - btn.disabled = true; - btn.textContent = 'âŗ åŽĄæŸĨ中...'; - progress.classList.remove('hidden'); - summary.classList.add('hidden'); - - inlineSuggestions = []; - let totalFiles = 0; - let completedFiles = 0; - - inlineReviewSSE = SSE.post(`/api/repos/${repoId}/review`, { - base, head, top_n: 0, - }, { - start(data) { - totalFiles = data.total_files || 0; - document.getElementById('review-progress-text').textContent = `å‡†å¤‡åŽĄæŸĨ ${totalFiles} ä¸Ē文äģļ...`; - document.getElementById('review-progress-bar').style.width = '5%'; - }, - file_start(data) { - completedFiles++; - const pct = totalFiles > 0 ? Math.round((completedFiles / totalFiles) * 80 + 10) : 50; - document.getElementById('review-progress-bar').style.width = pct + '%'; - document.getElementById('review-progress-text').textContent = `æ­Ŗåœ¨åŽĄæŸĨ: ${data.file || ''} (${completedFiles}/${totalFiles})`; - }, - suggestion(data) { - inlineSuggestions.push(data); - }, - summary(data) { - const el = document.getElementById('review-summary-content'); - if (data.score !== undefined) { - el.innerHTML = renderSummaryHtml(data); - } else { - el.innerHTML = renderMarkdown(data.content || ''); - } - document.getElementById('review-progress-bar').style.width = '90%'; - }, - done() { - document.getElementById('review-progress-bar').style.width = '100%'; - document.getElementById('review-progress-text').textContent = 'åŽĄæŸĨ厌成īŧ'; - - setTimeout(() => { - progress.classList.add('hidden'); - summary.classList.remove('hidden'); - btn.disabled = false; - btn.textContent = '🤖 AI č¯„åŽĄ'; - }, 500); - - // Insert suggestions into the existing diff - insertInlineSuggestions(); - inlineReviewSSE = null; - }, - analysis_saved(data) { - // Update "æŸĨįœ‹åŽŒæ•´åŽĄæŸĨ" link behavior - }, - error(data) { - showToast('åŽĄæŸĨå¤ąč´Ĩ: ' + (data.message || 'æœĒįŸĨ错蝝'), 'error'); - progress.classList.add('hidden'); - btn.disabled = false; - btn.textContent = '🤖 AI č¯„åŽĄ'; - inlineReviewSSE = null; - }, - }); - } - - function cancelInlineReview() { - if (inlineReviewSSE) { - inlineReviewSSE.abort(); - inlineReviewSSE = null; - } - document.getElementById('review-progress').classList.add('hidden'); - const btn = document.getElementById('btn-inline-review'); - btn.disabled = false; - btn.textContent = '🤖 AI č¯„åŽĄ'; - } + // ── Insert suggestions into Diff tab's diff view ────────────── function insertInlineSuggestions() { const fileSeverities = {}; const severityOrder = { critical: 3, warning: 2, info: 1 }; - inlineSuggestions.forEach((s, i) => { + allSuggestions.forEach((s, i) => { if (s.file) { - DiffViewer.insertFileSuggestion(s.file, s.severity, s.content, 'inline-sug-' + i); + DiffViewer.insertFileSuggestion(s.file, s.severity, s.content, 'sug-' + i); const cur = fileSeverities[s.file] || 'info'; if ((severityOrder[s.severity] || 0) > (severityOrder[cur] || 0)) { fileSeverities[s.file] = s.severity; @@ -746,12 +620,10 @@ } } - function clearInlineReview() { + function clearInlineSuggestions() { const container = document.getElementById('diff-container'); container.querySelectorAll('.file-suggestions-container').forEach(el => el.remove()); container.querySelectorAll('.file-tree-severity').forEach(el => el.remove()); - document.getElementById('review-summary').classList.add('hidden'); - inlineSuggestions = []; } // ── Generate PR Description ───────────────────────────────────── @@ -847,10 +719,9 @@ document.body.removeChild(textarea); } - // ── Full AI Code Review ───────────────────────────────────────── + // ── AI Code Review ───────────────────────────────────────────── let currentSSE = null; - let diffVisible = true; let allSuggestions = []; let fileReviews = {}; let currentAnalysisId = null; @@ -871,7 +742,7 @@ } const btn = document.getElementById('btn-review'); - const progress = document.getElementById('review-progress-full'); + const progress = document.getElementById('review-progress'); const results = document.getElementById('review-results'); btn.disabled = true; @@ -885,18 +756,16 @@ currentAnalysisId = null; document.getElementById('summary-content').innerHTML = ''; document.getElementById('file-reviews').innerHTML = ''; - document.getElementById('review-actions').classList.add('hidden'); + + // Clear previous inline suggestions from diff view + clearInlineSuggestions(); + window._reviewDiff = null; // Progress tracking let totalFiles = 0; let completedFiles = 0; let startedFiles = 0; - function updateProgress() { - const pct = totalFiles > 0 ? Math.round((completedFiles / totalFiles) * 80 + 10) : 50; - document.getElementById('review-progress-bar-full').style.width = pct + '%'; - } - const concurrency = document.getElementById('concurrency').value; currentSSE = SSE.post(`/api/repos/${repoId}/review`, { @@ -906,13 +775,13 @@ }, { start(data) { totalFiles = data.total_files || 0; - document.getElementById('review-progress-text-full').textContent = `å‡†å¤‡åŽĄæŸĨ ${totalFiles} ä¸Ē文äģļ...`; - document.getElementById('review-progress-bar-full').style.width = '5%'; + document.getElementById('review-progress-text').textContent = `å‡†å¤‡åŽĄæŸĨ ${totalFiles} ä¸Ē文äģļ...`; + document.getElementById('review-progress-bar').style.width = '5%'; }, file_start(data) { startedFiles++; const currentFile = data.file || ''; - document.getElementById('review-progress-text-full').textContent = `æ­Ŗåœ¨åŽĄæŸĨ: ${currentFile} (${startedFiles}/${totalFiles})`; + document.getElementById('review-progress-text').textContent = `æ­Ŗåœ¨åŽĄæŸĨ: ${currentFile} (${startedFiles}/${totalFiles})`; if (!fileReviews[currentFile]) { fileReviews[currentFile] = { filename: currentFile, suggestions: [], summary: '' }; @@ -929,8 +798,9 @@ }, file_end(data) { completedFiles++; - updateProgress(); - document.getElementById('review-progress-text-full').textContent = `åˇ˛åŽŒæˆ ${completedFiles}/${totalFiles} ä¸Ē文äģļ`; + const pct = totalFiles > 0 ? Math.round((completedFiles / totalFiles) * 80 + 10) : 50; + document.getElementById('review-progress-bar').style.width = pct + '%'; + document.getElementById('review-progress-text').textContent = `åˇ˛åŽŒæˆ ${completedFiles}/${totalFiles} ä¸Ē文äģļ`; }, file_summary(data) { if (data.file && fileReviews[data.file]) { @@ -949,25 +819,41 @@ } else { el.innerHTML = renderMarkdown(data.content || ''); } - document.getElementById('review-progress-bar-full').style.width = '90%'; - document.getElementById('review-progress-text-full').textContent = 'į”Ÿæˆæ€ģįģ“...'; + document.getElementById('review-progress-bar').style.width = '90%'; + document.getElementById('review-progress-text').textContent = 'į”Ÿæˆæ€ģįģ“...'; }, done() { - document.getElementById('review-progress-bar-full').style.width = '100%'; - document.getElementById('review-progress-text-full').textContent = 'åŽĄæŸĨ厌成īŧ'; + document.getElementById('review-progress-bar').style.width = '100%'; + document.getElementById('review-progress-text').textContent = 'åŽĄæŸĨ厌成īŧ'; setTimeout(() => { progress.classList.add('hidden'); results.classList.remove('hidden'); - document.getElementById('review-actions').classList.remove('hidden'); btn.disabled = false; btn.textContent = 'åŧ€å§‹åŽĄæŸĨ'; updatePrintHeader(); }, 500); - // Render inline suggestions if diff is available + // Insert suggestions into the Diff tab's diff view if (window._reviewDiff) { - renderInlineReview(window._reviewDiff); + DiffViewer.init('diff-container'); + DiffViewer.renderDiff(window._reviewDiff, { + onComplete() { + insertInlineSuggestions(); + } + }); + } else { + // Diff not streamed; fetch it and render + fetch(`/api/repos/${repoId}/diff?base=${encodeURIComponent(base)}&head=${encodeURIComponent(head)}`, { credentials: 'same-origin' }) + .then(r => r.json()) + .then(d => { + if (d.diff) { + DiffViewer.init('diff-container'); + DiffViewer.renderDiff(d.diff, { + onComplete() { insertInlineSuggestions(); } + }); + } + }).catch(() => {}); } currentSSE = null; @@ -989,6 +875,17 @@ }); } + function cancelReview() { + if (currentSSE) { + currentSSE.abort(); + currentSSE = null; + } + document.getElementById('review-progress').classList.add('hidden'); + const btn = document.getElementById('btn-review'); + btn.disabled = false; + btn.textContent = 'åŧ€å§‹åŽĄæŸĨ'; + } + function appendSuggestionCard(suggestion) { const container = document.getElementById('file-reviews'); @@ -1025,41 +922,6 @@ return (str || '').replace(/[^a-zA-Z0-9]/g, '-'); } - function renderInlineReview(diffString) { - const container = document.getElementById('review-diff-container'); - if (!container) return; - - DiffViewer.init('review-diff-container'); - DiffViewer.renderDiff(diffString, { - onComplete() { - const fileSeverities = {}; - const severityOrder = { critical: 3, warning: 2, info: 1 }; - - allSuggestions.forEach((s, i) => { - if (s.file) { - DiffViewer.insertFileSuggestion(s.file, s.severity, s.content, 'sug-' + i); - const cur = fileSeverities[s.file] || 'info'; - if ((severityOrder[s.severity] || 0) > (severityOrder[cur] || 0)) { - fileSeverities[s.file] = s.severity; - } - } - }); - - Object.entries(fileSeverities).forEach(([file, sev]) => { - DiffViewer.markFileSeverity(file, sev); - }); - } - }); - } - - function toggleDiffView() { - const container = document.getElementById('review-diff-container'); - const btn = document.getElementById('btn-toggle-diff'); - diffVisible = !diffVisible; - container.style.display = diffVisible ? '' : 'none'; - btn.textContent = diffVisible ? '隐藏 Diff' : '昞į¤ē Diff'; - } - function updatePrintHeader() { const baseEl = document.getElementById('select-base'); const headEl = document.getElementById('select-head'); @@ -1143,7 +1005,7 @@ document.getElementById('review-actions').classList.remove('hidden'); updatePrintHeader(); - // Load diff and render inline + // Load diff and render with inline suggestions in Diff tab const base = data.base_ref; const head = data.head_ref; @@ -1152,7 +1014,12 @@ const diffData = await diffResp.json(); const diffString = diffData.diff || ''; if (diffString) { - renderInlineReview(diffString); + DiffViewer.init('diff-container'); + DiffViewer.renderDiff(diffString, { + onComplete() { + insertInlineSuggestions(); + } + }); } }