feat: diff 过大时跳过渲染(仿 Gitee 风格警告)
This commit is contained in:
@@ -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 ──────────────────────────────
|
// ── Incremental rendering pipeline ──────────────────────────────
|
||||||
|
|
||||||
// Render diff with file tree sidebar — incremental, non-blocking
|
// Render diff with file tree sidebar — incremental, non-blocking
|
||||||
@@ -213,6 +241,17 @@ const DiffViewer = {
|
|||||||
|
|
||||||
// Parse files for tree (fast — just regex + string ops)
|
// Parse files for tree (fast — just regex + string ops)
|
||||||
this.files = this._parseDiffFiles(diffString);
|
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);
|
const tree = this._buildTree(this.files);
|
||||||
|
|
||||||
// Split diff into per-file chunks for incremental rendering
|
// Split diff into per-file chunks for incremental rendering
|
||||||
@@ -285,6 +324,17 @@ const DiffViewer = {
|
|||||||
const combinedDiff = files.map(f => f.patch).join('\n');
|
const combinedDiff = files.map(f => f.patch).join('\n');
|
||||||
this.rawDiff = combinedDiff;
|
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
|
// Split into per-file chunks
|
||||||
this._chunks = this.files.map(f => f._patch).filter(Boolean);
|
this._chunks = this.files.map(f => f._patch).filter(Boolean);
|
||||||
this._chunkIndex = 0;
|
this._chunkIndex = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user