feat: diff 过大时跳过渲染(仿 Gitee 风格警告)

This commit is contained in:
2026-06-19 20:33:20 +08:00
parent a12d266a30
commit 987f331474
+50
View File
@@ -199,6 +199,34 @@ const DiffViewer = {
}
},
// ── Diff too large guard ────────────────────────────────────────
_isTooLarge(files) {
const MAX_FILES = 300;
const MAX_LINES = 10000;
const totalAdd = files.reduce((s, f) => s + (f.additions || 0), 0);
const totalDel = files.reduce((s, f) => s + (f.deletions || 0), 0);
return files.length > MAX_FILES || (totalAdd + totalDel) > MAX_LINES;
},
_renderTooLargeWarning(files, totalAdd, totalDel, onExpand) {
const id = 'diff-expand-' + Math.random().toString(36).slice(2, 8);
this.container.innerHTML = `
<div class="bg-yellow-50 border border-yellow-200 rounded-lg p-6 text-center">
<div class="text-yellow-600 text-lg font-medium mb-2">⚠️ 变更过大,已跳过渲染</div>
<p class="text-sm text-gray-600 mb-1">
共 <strong>${files.length}</strong> 个文件,
<span class="text-green-600">+${totalAdd}</span>
<span class="text-red-600">-${totalDel}</span>
</p>
<p class="text-xs text-gray-400 mb-4">渲染大量变更可能导致浏览器卡顿</p>
<button id="${id}" class="px-4 py-2 bg-blue-600 text-white text-sm rounded-md hover:bg-blue-700">
显示 Diff
</button>
</div>`;
document.getElementById(id).addEventListener('click', onExpand);
},
// ── Incremental rendering pipeline ──────────────────────────────
// Render diff with file tree sidebar — incremental, non-blocking
@@ -213,6 +241,17 @@ const DiffViewer = {
// Parse files for tree (fast — just regex + string ops)
this.files = this._parseDiffFiles(diffString);
// Guard: if diff is too large, show warning instead of rendering
if (!options.forceRender && this._isTooLarge(this.files)) {
const totalAdd = this.files.reduce((s, f) => s + f.additions, 0);
const totalDel = this.files.reduce((s, f) => s + f.deletions, 0);
const self = this;
this._renderTooLargeWarning(this.files, totalAdd, totalDel, function () {
self.renderDiff(diffString, { ...options, forceRender: true });
});
return;
}
const tree = this._buildTree(this.files);
// Split diff into per-file chunks for incremental rendering
@@ -285,6 +324,17 @@ const DiffViewer = {
const combinedDiff = files.map(f => f.patch).join('\n');
this.rawDiff = combinedDiff;
// Guard: if diff is too large, show warning
if (!options.forceRender && this._isTooLarge(this.files)) {
const totalAdd = this.files.reduce((s, f) => s + f.additions, 0);
const totalDel = this.files.reduce((s, f) => s + f.deletions, 0);
const self = this;
this._renderTooLargeWarning(this.files, totalAdd, totalDel, function () {
self.renderFiles(files, { ...options, forceRender: true });
});
return;
}
// Split into per-file chunks
this._chunks = this.files.map(f => f._patch).filter(Boolean);
this._chunkIndex = 0;