feat: Phase 3 — 前端交互功能完成
This commit is contained in:
@@ -0,0 +1,126 @@
|
||||
// Review Inline: renders AI review suggestions inline in a diff view
|
||||
const ReviewInline = {
|
||||
suggestions: [],
|
||||
|
||||
init(diffContainerId, suggestionsContainerId) {
|
||||
this.diffContainer = document.getElementById(diffContainerId);
|
||||
this.suggestionsContainer = document.getElementById(suggestionsContainerId);
|
||||
this.suggestions = [];
|
||||
},
|
||||
|
||||
// Add a suggestion to the collection
|
||||
addSuggestion(suggestion) {
|
||||
this.suggestions.push(suggestion);
|
||||
},
|
||||
|
||||
// Render all collected suggestions inline in the diff
|
||||
renderInline() {
|
||||
if (!this.diffContainer) return;
|
||||
|
||||
this.suggestions.forEach((s, index) => {
|
||||
DiffViewer.insertSuggestion(
|
||||
s.file,
|
||||
s.line,
|
||||
s.side || 'right',
|
||||
s.severity || 'info',
|
||||
s.content || '',
|
||||
`suggestion-${index}`
|
||||
);
|
||||
});
|
||||
},
|
||||
|
||||
// Render a single suggestion card (for the card-based view)
|
||||
renderSuggestionCard(suggestion) {
|
||||
const severityStyles = {
|
||||
critical: {
|
||||
border: 'border-l-4 border-red-500',
|
||||
bg: 'bg-red-50',
|
||||
badge: 'bg-red-100 text-red-800',
|
||||
icon: '🔴',
|
||||
label: '严重',
|
||||
},
|
||||
warning: {
|
||||
border: 'border-l-4 border-yellow-500',
|
||||
bg: 'bg-yellow-50',
|
||||
badge: 'bg-yellow-100 text-yellow-800',
|
||||
icon: '🟡',
|
||||
label: '建议',
|
||||
},
|
||||
info: {
|
||||
border: 'border-l-4 border-green-500',
|
||||
bg: 'bg-green-50',
|
||||
badge: 'bg-green-100 text-green-800',
|
||||
icon: '🟢',
|
||||
label: '提示',
|
||||
},
|
||||
};
|
||||
|
||||
const style = severityStyles[suggestion.severity] || severityStyles.info;
|
||||
|
||||
return `
|
||||
<div class="review-card ${style.border} ${style.bg} rounded-lg p-4 mb-3">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="${style.badge} px-2 py-0.5 rounded text-xs font-medium">
|
||||
${style.icon} ${style.label}
|
||||
</span>
|
||||
${suggestion.file ? `<span class="text-xs text-gray-500 font-mono">${suggestion.file}</span>` : ''}
|
||||
${suggestion.line ? `<span class="text-xs text-gray-400">行 ${suggestion.line}</span>` : ''}
|
||||
</div>
|
||||
<div class="text-sm text-gray-700 review-content">${suggestion.content || ''}</div>
|
||||
${suggestion.code_example ? `
|
||||
<pre class="mt-2 p-2 bg-gray-100 rounded text-xs overflow-x-auto"><code>${this._escapeHtml(suggestion.code_example)}</code></pre>
|
||||
` : ''}
|
||||
</div>`;
|
||||
},
|
||||
|
||||
// Render file review section
|
||||
renderFileReview(fileReview) {
|
||||
const severityOrder = { critical: 0, warning: 1, info: 2 };
|
||||
const suggestions = (fileReview.suggestions || []).sort((a, b) =>
|
||||
(severityOrder[a.severity] || 2) - (severityOrder[b.severity] || 2)
|
||||
);
|
||||
|
||||
const maxSeverity = suggestions.length > 0 ? suggestions[0].severity : 'info';
|
||||
const severityColors = {
|
||||
critical: 'border-red-500',
|
||||
warning: 'border-yellow-500',
|
||||
info: 'border-green-500',
|
||||
};
|
||||
|
||||
let html = `
|
||||
<div class="file-review bg-white rounded-lg shadow-md ${severityColors[maxSeverity] || ''} border-l-4 mb-4">
|
||||
<div class="p-4 border-b border-gray-100">
|
||||
<h3 class="font-medium text-gray-900 font-mono text-sm">${fileReview.filename || ''}</h3>
|
||||
${fileReview.summary ? `<p class="text-sm text-gray-600 mt-1">${fileReview.summary}</p>` : ''}
|
||||
</div>
|
||||
<div class="p-4 space-y-3">`;
|
||||
|
||||
suggestions.forEach(s => {
|
||||
html += this.renderSuggestionCard(s);
|
||||
});
|
||||
|
||||
html += `
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
return html;
|
||||
},
|
||||
|
||||
// Render overall summary
|
||||
renderSummary(summary) {
|
||||
if (!summary) return '';
|
||||
return `
|
||||
<div class="bg-white rounded-lg shadow-md p-6 mb-6">
|
||||
<h2 class="text-lg font-semibold text-gray-900 mb-3">整体评估</h2>
|
||||
<div class="prose text-sm text-gray-700">${summary}</div>
|
||||
</div>`;
|
||||
},
|
||||
|
||||
_escapeHtml(text) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = text;
|
||||
return div.innerHTML;
|
||||
}
|
||||
};
|
||||
|
||||
window.ReviewInline = ReviewInline;
|
||||
Reference in New Issue
Block a user