修复内存溢出问题

This commit is contained in:
2025-09-19 01:25:30 +08:00
parent 803cc100be
commit 9674740c0d
13 changed files with 1085 additions and 337 deletions

View File

@@ -61,10 +61,10 @@ export const HistoryPanel: React.FC = () => {
// 分页状态
const [currentPage, setCurrentPage] = useState(1);
const itemsPerPage = 30; // 每页显示的项目数
const itemsPerPage = 20; // 减少每页显示的项目数
// 悬浮预览状态
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number, size?: number} | null>(null);
const [hoveredImage, setHoveredImage] = useState<{url: string, title: string, width?: number, height?: number} | null>(null);
const [previewPosition, setPreviewPosition] = useState<{x: number, y: number}>({x: 0, y: 0});
const generations = currentProject?.generations || [];
@@ -76,7 +76,7 @@ export const HistoryPanel: React.FC = () => {
const uploadResult = generationOrEdit.uploadResults[index];
if (uploadResult.success && uploadResult.url) {
// 添加参数以降低图片质量
return `${uploadResult.url}?x-oss-process=image/quality,q_50`;
return `${uploadResult.url}?x-oss-process=image/quality,q_30`; // 降低质量到30%
}
}
return null;
@@ -480,7 +480,7 @@ export const HistoryPanel: React.FC = () => {
<div className="flex items-center justify-between mb-2">
<h4 className="text-xs font-medium text-gray-500 uppercase tracking-wide"></h4>
<span className="text-xs text-gray-400">
{filteredGenerations.length + filteredEdits.length}/1000
{filteredGenerations.length + filteredEdits.length}/100
</span>
</div>
{filteredGenerations.length === 0 && filteredEdits.length === 0 ? (
@@ -530,25 +530,16 @@ export const HistoryPanel: React.FC = () => {
// 创建图像对象以获取尺寸
const img = new Image();
img.onload = () => {
// 计算文件大小仅对base64数据
let size = 0;
if (imageUrl.startsWith('data:')) {
// 估算base64数据大小
const base64Data = imageUrl.split(',')[1];
size = Math.round((base64Data.length * 3) / 4);
}
setHoveredImage({
url: imageUrl,
title: `生成记录 G${globalIndex + 1}`,
width: img.width,
height: img.height,
size: size
height: img.height
});
// 计算预览位置,确保不超出屏幕边界
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300; // 减小预览窗口大小
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -596,13 +587,12 @@ export const HistoryPanel: React.FC = () => {
url: imageUrl,
title: `生成记录 G${globalIndex + 1}`,
width: 0,
height: 0,
size: 0
height: 0
});
// 计算预览位置
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -641,8 +631,8 @@ export const HistoryPanel: React.FC = () => {
}}
onMouseMove={(e) => {
// 调整预览位置以避免被遮挡
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -688,9 +678,9 @@ export const HistoryPanel: React.FC = () => {
}}
>
{(() => {
// 优先使用上传后的远程链接,如果没有则使用原始链接
// 优先使用上传后的远程链接
const imageUrl = getUploadedImageUrl(generation, 0) ||
(generation.outputAssets && generation.outputAssets.length > 0 ? generation.outputAssets[0].url : null);
(generation.outputAssets && generation.outputAssets.length > 0 && generation.outputAssets[0].url ? generation.outputAssets[0].url : null);
if (imageUrl) {
return <img src={imageUrl} alt="生成的变体" className="w-full h-full object-cover" />;
@@ -757,25 +747,16 @@ export const HistoryPanel: React.FC = () => {
// 创建图像对象以获取尺寸
const img = new Image();
img.onload = () => {
// 计算文件大小仅对base64数据
let size = 0;
if (imageUrl.startsWith('data:')) {
// 估算base64数据大小
const base64Data = imageUrl.split(',')[1];
size = Math.round((base64Data.length * 3) / 4);
}
setHoveredImage({
url: imageUrl,
title: `编辑记录 E${globalIndex + 1}`,
width: img.width,
height: img.height,
size: size
height: img.height
});
// 计算预览位置,确保不超出屏幕边界
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -816,13 +797,12 @@ export const HistoryPanel: React.FC = () => {
url: imageUrl,
title: `编辑记录 E${globalIndex + 1}`,
width: 0,
height: 0,
size: 0
height: 0
});
// 计算预览位置
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -865,8 +845,8 @@ export const HistoryPanel: React.FC = () => {
}}
onMouseMove={(e) => {
// 调整预览位置以避免被遮挡
const previewWidth = 500;
const previewHeight = 500;
const previewWidth = 300;
const previewHeight = 300;
const offsetX = 10;
const offsetY = 10;
@@ -904,9 +884,9 @@ export const HistoryPanel: React.FC = () => {
}}
>
{(() => {
// 优先使用上传后的远程链接,如果没有则使用原始链接
// 优先使用上传后的远程链接
const imageUrl = getUploadedImageUrl(edit, 0) ||
(edit.outputAssets && edit.outputAssets.length > 0 ? edit.outputAssets[0].url : null);
(edit.outputAssets && edit.outputAssets.length > 0 && edit.outputAssets[0].url ? edit.outputAssets[0].url : null);
if (imageUrl) {
return <img src={imageUrl} alt="编辑的变体" className="w-full h-full object-cover" />;
@@ -1042,7 +1022,7 @@ export const HistoryPanel: React.FC = () => {
// 获取上传后的远程链接(如果存在)
// 参考图像在uploadResults中从索引1开始索引0是生成的图像
const uploadedUrl = gen.uploadResults && gen.uploadResults[index + 1] && gen.uploadResults[index + 1].success
? `${gen.uploadResults[index + 1].url}?x-oss-process=image/quality,q_50`
? `${gen.uploadResults[index + 1].url}?x-oss-process=image/quality,q_30`
: null;
const displayUrl = uploadedUrl || asset.url;
@@ -1150,7 +1130,7 @@ export const HistoryPanel: React.FC = () => {
// 获取上传后的远程链接(如果存在)
// 参考图像在uploadResults中从索引1开始索引0是生成的图像
const uploadedUrl = parentGen.uploadResults && parentGen.uploadResults[index + 1] && parentGen.uploadResults[index + 1].success
? `${parentGen.uploadResults[index + 1].url}?x-oss-process=image/quality,q_50`
? `${parentGen.uploadResults[index + 1].url}?x-oss-process=image/quality,q_30`
: null;
const displayUrl = uploadedUrl || asset.url;
@@ -1219,7 +1199,25 @@ export const HistoryPanel: React.FC = () => {
if (imageUrl) {
// 处理数据URL和常规URL
if (imageUrl.startsWith('data:')) {
if (imageUrl.startsWith('data:') || imageUrl.startsWith('blob:')) {
// 对于Blob URL我们需要获取实际的Blob数据
if (imageUrl.startsWith('blob:')) {
// 从AppStore获取Blob
const blob = useAppStore.getState().getBlob(imageUrl);
if (blob) {
const url = URL.createObjectURL(blob);
const link = document.createElement('a');
link.href = url;
link.download = `nano-banana-${Date.now()}.png`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(url);
return;
}
}
// 对于数据URL直接下载
const link = document.createElement('a');
link.href = imageUrl;
link.download = `nano-banana-${Date.now()}.png`;
@@ -1266,8 +1264,8 @@ export const HistoryPanel: React.FC = () => {
style={{
left: `${previewPosition.x}px`,
top: `${previewPosition.y}px`,
maxWidth: '300px',
maxHeight: '300px'
maxWidth: '200px', // 减小最大宽度
maxHeight: '200px'
}}
>
<div className="bg-gray-900 text-white text-xs p-2 truncate font-medium">
@@ -1276,7 +1274,7 @@ export const HistoryPanel: React.FC = () => {
<img
src={hoveredImage.url}
alt="预览"
className="w-full h-auto max-h-[200px] object-contain"
className="w-full h-auto max-h-[150px] object-contain"
/>
{/* 图像信息 */}
<div className="p-2 bg-gray-50 border-t border-gray-200 text-xs">
@@ -1286,12 +1284,6 @@ export const HistoryPanel: React.FC = () => {
<span className="text-gray-800">{hoveredImage.width} × {hoveredImage.height}</span>
</div>
)}
{hoveredImage.size > 0 && (
<div className="flex justify-between text-gray-600 mt-1">
<span>:</span>
<span className="text-gray-800">{Math.round(hoveredImage.size / 1024)} KB</span>
</div>
)}
</div>
</div>
)}