Skip to content

Commit dcf7888

Browse files
committed
feat: Implement content truncation for preview to prevent memory overflow and enhance user experience
1 parent 7ed03ba commit dcf7888

File tree

2 files changed

+102
-22
lines changed

2 files changed

+102
-22
lines changed

sources/gc-qa-rag-etl/etlapp-web/src/GenericETL.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,37 @@ const GenericETL: React.FC = () => {
265265
};
266266

267267
// Single file content preview
268+
// 限制预览内容大小,避免大文件导致内存溢出
269+
const truncateContentForPreview = (content: any, maxItems: number = 50): any => {
270+
if (!content) return content;
271+
272+
// 处理 Groups 数组(QA/Full 结果)
273+
if (content.Groups && Array.isArray(content.Groups)) {
274+
if (content.Groups.length > maxItems) {
275+
return {
276+
...content,
277+
Groups: content.Groups.slice(0, maxItems),
278+
_truncated: true,
279+
_originalCount: content.Groups.length,
280+
};
281+
}
282+
}
283+
284+
// 处理 chunks 数组(Embedding 结果)
285+
if (content.chunks && Array.isArray(content.chunks)) {
286+
if (content.chunks.length > maxItems) {
287+
return {
288+
...content,
289+
chunks: content.chunks.slice(0, maxItems),
290+
_truncated: true,
291+
_originalCount: content.chunks.length,
292+
};
293+
}
294+
}
295+
296+
return content;
297+
};
298+
268299
const handlePreview = async (
269300
row: any,
270301
stage: "das" | "embedding" | "qa" | "full"
@@ -286,7 +317,9 @@ const GenericETL: React.FC = () => {
286317
);
287318
title = `${row.filename} - ${stage}`;
288319
}
289-
setPreviewContent(content);
320+
// 截断大内容以避免内存问题
321+
const truncatedContent = truncateContentForPreview(content);
322+
setPreviewContent(truncatedContent);
290323
setPreviewTitle(title);
291324
setPreviewModal(true);
292325
};
Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import React from "react";
2-
import { Modal } from "antd";
1+
import React, { useMemo } from "react";
2+
import { Modal, Alert } from "antd";
33

44
interface PreviewModalProps {
55
open: boolean;
@@ -8,30 +8,77 @@ interface PreviewModalProps {
88
onCancel: () => void;
99
}
1010

11+
const MAX_PREVIEW_LENGTH = 100000; // 限制预览字符数为 100KB
12+
1113
const PreviewModal: React.FC<PreviewModalProps> = ({
1214
open,
1315
title,
1416
content,
1517
onCancel,
16-
}) => (
17-
<Modal
18-
open={open}
19-
title={title}
20-
onCancel={onCancel}
21-
footer={null}
22-
width={800}
23-
>
24-
<div
25-
style={{
26-
maxHeight: 500,
27-
overflow: "auto",
28-
borderRadius: 6,
29-
padding: 12,
30-
}}
18+
}) => {
19+
const { displayContent, isTruncated, totalSize, truncatedInfo } = useMemo(() => {
20+
if (!content) {
21+
return { displayContent: "", isTruncated: false, totalSize: 0, truncatedInfo: "" };
22+
}
23+
24+
// 检查是否有数据层面的截断标记
25+
const dataLevelTruncated = content._truncated === true;
26+
const originalCount = content._originalCount || 0;
27+
let truncatedInfo = "";
28+
if (dataLevelTruncated) {
29+
const currentCount = content.Groups?.length || content.chunks?.length || 0;
30+
truncatedInfo = `数据已截断: 仅显示前 ${currentCount} 条,共 ${originalCount} 条`;
31+
}
32+
33+
const fullJson = JSON.stringify(content, null, 2);
34+
const totalSize = fullJson.length;
35+
36+
if (totalSize <= MAX_PREVIEW_LENGTH) {
37+
return { displayContent: fullJson, isTruncated: dataLevelTruncated, totalSize, truncatedInfo };
38+
}
39+
40+
// 截断内容,保留前 MAX_PREVIEW_LENGTH 字符
41+
const truncated = fullJson.slice(0, MAX_PREVIEW_LENGTH);
42+
return {
43+
displayContent: truncated + "\n\n... (内容已截断)",
44+
isTruncated: true,
45+
totalSize,
46+
truncatedInfo: truncatedInfo || `内容过大,仅显示前 ${(MAX_PREVIEW_LENGTH / 1024).toFixed(0)} KB`,
47+
};
48+
}, [content]);
49+
50+
return (
51+
<Modal
52+
open={open}
53+
title={title}
54+
onCancel={onCancel}
55+
footer={null}
56+
width={800}
3157
>
32-
{content ? JSON.stringify(content, null, 2) : ""}
33-
</div>
34-
</Modal>
35-
);
58+
{isTruncated && (
59+
<Alert
60+
message={truncatedInfo || `内容过大 (${(totalSize / 1024 / 1024).toFixed(2)} MB),仅显示前 ${(MAX_PREVIEW_LENGTH / 1024).toFixed(0)} KB`}
61+
type="warning"
62+
showIcon
63+
style={{ marginBottom: 12 }}
64+
/>
65+
)}
66+
<pre
67+
style={{
68+
maxHeight: 500,
69+
overflow: "auto",
70+
borderRadius: 6,
71+
padding: 12,
72+
backgroundColor: "#f5f5f5",
73+
fontSize: 12,
74+
whiteSpace: "pre-wrap",
75+
wordBreak: "break-all",
76+
}}
77+
>
78+
{displayContent}
79+
</pre>
80+
</Modal>
81+
);
82+
};
3683

3784
export default PreviewModal;

0 commit comments

Comments
 (0)