You've already forked Nano-Banana-AI-Image-Editor
问题修复
This commit is contained in:
@@ -630,16 +630,76 @@ export const HistoryPanel: React.FC<{
|
||||
};
|
||||
img.onerror = (error) => {
|
||||
console.error('图像加载失败:', error);
|
||||
// 即使图像加载失败,也显示预览
|
||||
setHoveredImage({
|
||||
url: imageUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
// 传递鼠标位置信息给App组件
|
||||
if (setPreviewPosition) {
|
||||
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||
// 如果是Blob URL失效,尝试重新获取
|
||||
if (imageUrl.startsWith('blob:')) {
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(imageUrl);
|
||||
if (blob) {
|
||||
console.log('从AppStore找到Blob,尝试重新创建URL...');
|
||||
// 重新创建Blob URL
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
// 更新显示
|
||||
setHoveredImage({
|
||||
url: newUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
// 传递鼠标位置信息给App组件
|
||||
if (setPreviewPosition) {
|
||||
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||
}
|
||||
// 预加载新URL
|
||||
const newImg = new Image();
|
||||
newImg.onload = () => {
|
||||
setHoveredImage({
|
||||
url: newUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: newImg.width,
|
||||
height: newImg.height
|
||||
});
|
||||
};
|
||||
newImg.src = newUrl;
|
||||
} else {
|
||||
// 即使图像加载失败,也显示预览
|
||||
setHoveredImage({
|
||||
url: imageUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
// 传递鼠标位置信息给App组件
|
||||
if (setPreviewPosition) {
|
||||
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||
}
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('导入AppStore时出错:', err);
|
||||
// 即使图像加载失败,也显示预览
|
||||
setHoveredImage({
|
||||
url: imageUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
// 传递鼠标位置信息给App组件
|
||||
if (setPreviewPosition) {
|
||||
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 即使图像加载失败,也显示预览
|
||||
setHoveredImage({
|
||||
url: imageUrl,
|
||||
title: `生成记录 G${globalIndex + 1}`,
|
||||
width: 0,
|
||||
height: 0
|
||||
});
|
||||
// 传递鼠标位置信息给App组件
|
||||
if (setPreviewPosition) {
|
||||
setPreviewPosition({ x: e.clientX, y: e.clientY });
|
||||
}
|
||||
}
|
||||
};
|
||||
img.src = imageUrl;
|
||||
@@ -1026,7 +1086,30 @@ export const HistoryPanel: React.FC<{
|
||||
? `${gen.uploadResults[index].url}?x-oss-process=image/quality,q_30`
|
||||
: null;
|
||||
|
||||
const displayUrl = uploadedUrl || asset.url;
|
||||
// 如果没有上传的URL,则使用asset中的URL
|
||||
const displayUrl = uploadedUrl || asset.url || asset.blobUrl;
|
||||
|
||||
// 如果URL是blob:开头但已失效,尝试重新创建
|
||||
if (displayUrl && displayUrl.startsWith('blob:')) {
|
||||
// 检查blob是否仍然有效
|
||||
const img = new Image();
|
||||
img.onerror = () => {
|
||||
// Blob URL可能已失效,尝试重新创建
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
// 更新显示
|
||||
const imgElement = document.querySelector(`img[src="${displayUrl}"]`);
|
||||
if (imgElement) {
|
||||
imgElement.src = newUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
img.src = displayUrl;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -1042,11 +1125,30 @@ export const HistoryPanel: React.FC<{
|
||||
});
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`生成结果 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
{displayUrl ? (
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`生成结果 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
// 如果图像加载失败,尝试重新创建Blob URL
|
||||
if (displayUrl.startsWith('blob:')) {
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
(e.target as HTMLImageElement).src = newUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-gray-100 flex items-center justify-center">
|
||||
<ImageIcon className="h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -1074,11 +1176,36 @@ export const HistoryPanel: React.FC<{
|
||||
const fullGen = dbGenerations.find(item => item.id === gen.id) || gen;
|
||||
const outputAssetsCount = fullGen.outputAssets?.length || 0;
|
||||
|
||||
const uploadedUrl = gen.uploadResults && gen.uploadResults[outputAssetsCount + index] && gen.uploadResults[outputAssetsCount + index].success
|
||||
? `${gen.uploadResults[outputAssetsCount + index].url}?x-oss-process=image/quality,q_30`
|
||||
// 确保索引在有效范围内
|
||||
const uploadResultIndex = outputAssetsCount + index;
|
||||
const uploadedUrl = fullGen.uploadResults && fullGen.uploadResults[uploadResultIndex] && fullGen.uploadResults[uploadResultIndex].success
|
||||
? `${fullGen.uploadResults[uploadResultIndex].url}?x-oss-process=image/quality,q_30`
|
||||
: null;
|
||||
|
||||
const displayUrl = uploadedUrl || asset.url;
|
||||
// 如果没有上传的URL,则使用asset中的URL
|
||||
const displayUrl = uploadedUrl || asset.url || asset.blobUrl;
|
||||
|
||||
// 如果URL是blob:开头但已失效,尝试重新创建
|
||||
if (displayUrl && displayUrl.startsWith('blob:')) {
|
||||
// 检查blob是否仍然有效
|
||||
const img = new Image();
|
||||
img.onerror = () => {
|
||||
// Blob URL可能已失效,尝试重新创建
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
// 更新显示
|
||||
const imgElement = document.querySelector(`img[src="${displayUrl}"]`);
|
||||
if (imgElement) {
|
||||
imgElement.src = newUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
img.src = displayUrl;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -1094,11 +1221,30 @@ export const HistoryPanel: React.FC<{
|
||||
});
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`参考图像 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
{displayUrl ? (
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`参考图像 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
// 如果图像加载失败,尝试重新创建Blob URL
|
||||
if (displayUrl.startsWith('blob:')) {
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
(e.target as HTMLImageElement).src = newUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-gray-100 flex items-center justify-center">
|
||||
<ImageIcon className="h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
@@ -1166,6 +1312,95 @@ export const HistoryPanel: React.FC<{
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 编辑结果图像 */}
|
||||
{selectedEdit.outputAssets && selectedEdit.outputAssets.length > 0 && (
|
||||
<div className="pt-2 border-t border-gray-200">
|
||||
<h5 className="text-xs font-medium text-gray-500 mb-2">编辑结果</h5>
|
||||
<div className="text-xs text-gray-600 mb-2">
|
||||
{selectedEdit.outputAssets.length} 个编辑结果
|
||||
</div>
|
||||
<div className="flex flex-wrap gap-2">
|
||||
{selectedEdit.outputAssets.slice(0, 4).map((asset: any, index: number) => {
|
||||
// 获取上传后的远程链接(如果存在)
|
||||
const uploadedUrl = selectedEdit.uploadResults && selectedEdit.uploadResults[index] && selectedEdit.uploadResults[index].success
|
||||
? `${selectedEdit.uploadResults[index].url}?x-oss-process=image/quality,q_30`
|
||||
: null;
|
||||
|
||||
// 如果没有上传的URL,则使用asset中的URL
|
||||
const displayUrl = uploadedUrl || asset.url || asset.blobUrl;
|
||||
|
||||
// 如果URL是blob:开头但已失效,尝试重新创建
|
||||
if (displayUrl && displayUrl.startsWith('blob:')) {
|
||||
// 检查blob是否仍然有效
|
||||
const img = new Image();
|
||||
img.onerror = () => {
|
||||
// Blob URL可能已失效,尝试重新创建
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
// 更新显示
|
||||
const imgElement = document.querySelector(`img[src="${displayUrl}"]`);
|
||||
if (imgElement) {
|
||||
imgElement.src = newUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
img.src = displayUrl;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
key={asset.id}
|
||||
className="relative w-16 h-16 rounded border overflow-hidden cursor-pointer hover:ring-2 hover:ring-yellow-400"
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setPreviewModal({
|
||||
open: true,
|
||||
imageUrl: displayUrl,
|
||||
title: `编辑结果 ${index + 1}`,
|
||||
description: `${asset.width} × ${asset.height}`
|
||||
});
|
||||
}}
|
||||
>
|
||||
{displayUrl ? (
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`编辑结果 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
// 如果图像加载失败,尝试重新创建Blob URL
|
||||
if (displayUrl.startsWith('blob:')) {
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
(e.target as HTMLImageElement).src = newUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-gray-100 flex items-center justify-center">
|
||||
<ImageIcon className="h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{selectedEdit.outputAssets.length > 4 && (
|
||||
<div className="w-16 h-16 rounded border flex items-center justify-center bg-gray-100 text-xs text-gray-500">
|
||||
+{selectedEdit.outputAssets.length - 4}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 原始生成参考 */}
|
||||
{parentGen && (
|
||||
<div className="pt-2 border-t border-gray-200">
|
||||
@@ -1184,10 +1419,37 @@ export const HistoryPanel: React.FC<{
|
||||
// 获取上传后的远程链接(如果存在)
|
||||
// 参考图像在uploadResults中从索引outputAssets.length开始
|
||||
const outputAssetsCount = parentGen.outputAssets?.length || 0;
|
||||
const uploadedUrl = parentGen.uploadResults && parentGen.uploadResults[outputAssetsCount + index] && parentGen.uploadResults[outputAssetsCount + index].success
|
||||
? `${parentGen.uploadResults[outputAssetsCount + index].url}?x-oss-process=image/quality,q_30`
|
||||
|
||||
// 确保索引在有效范围内
|
||||
const uploadResultIndex = outputAssetsCount + index;
|
||||
const uploadedUrl = parentGen.uploadResults && parentGen.uploadResults[uploadResultIndex] && parentGen.uploadResults[uploadResultIndex].success
|
||||
? `${parentGen.uploadResults[uploadResultIndex].url}?x-oss-process=image/quality,q_30`
|
||||
: null;
|
||||
const displayUrl = uploadedUrl || asset.url;
|
||||
|
||||
// 如果没有上传的URL,则使用asset中的URL
|
||||
const displayUrl = uploadedUrl || asset.url || asset.blobUrl;
|
||||
|
||||
// 如果URL是blob:开头但已失效,尝试重新创建
|
||||
if (displayUrl && displayUrl.startsWith('blob:')) {
|
||||
// 检查blob是否仍然有效
|
||||
const img = new Image();
|
||||
img.onerror = () => {
|
||||
// Blob URL可能已失效,尝试重新创建
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
// 更新显示
|
||||
const imgElement = document.querySelector(`img[src="${displayUrl}"]`);
|
||||
if (imgElement) {
|
||||
imgElement.src = newUrl;
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
img.src = displayUrl;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -1203,11 +1465,30 @@ export const HistoryPanel: React.FC<{
|
||||
});
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`原始参考图像 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
{displayUrl ? (
|
||||
<img
|
||||
src={displayUrl}
|
||||
alt={`原始参考图像 ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
// 如果图像加载失败,尝试重新创建Blob URL
|
||||
if (displayUrl.startsWith('blob:')) {
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(displayUrl);
|
||||
if (blob) {
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
(e.target as HTMLImageElement).src = newUrl;
|
||||
}
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full bg-gray-100 flex items-center justify-center">
|
||||
<ImageIcon className="h-4 w-4 text-gray-400" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -119,6 +119,23 @@ export const ImageCanvas: React.FC = () => {
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
console.error('Blob URL无法访问:', response.status, response.statusText);
|
||||
// 尝试从AppStore重新获取Blob并创建新的URL
|
||||
import('../store/useAppStore').then((module) => {
|
||||
const useAppStore = module.useAppStore;
|
||||
const blob = useAppStore.getState().getBlob(canvasImage);
|
||||
if (blob) {
|
||||
console.log('从AppStore找到Blob,尝试重新创建URL...');
|
||||
// 重新创建Blob URL并重试加载
|
||||
const newUrl = URL.createObjectURL(blob);
|
||||
console.log('创建新的Blob URL:', newUrl);
|
||||
// 更新canvasImage为新的URL
|
||||
useAppStore.getState().setCanvasImage(newUrl);
|
||||
} else {
|
||||
console.error('AppStore中未找到Blob');
|
||||
}
|
||||
}).catch(err => {
|
||||
console.error('导入AppStore时出错:', err);
|
||||
});
|
||||
} else {
|
||||
console.log('Blob URL可以访问');
|
||||
}
|
||||
|
||||
@@ -69,6 +69,27 @@ export const PromptComposer: React.FC = () => {
|
||||
const blob = getBlob(img);
|
||||
if (blob) {
|
||||
referenceImageBlobs.push(blob);
|
||||
} else {
|
||||
// 如果在AppStore中找不到Blob,尝试重新创建
|
||||
try {
|
||||
const response = await fetch(img);
|
||||
if (response.ok) {
|
||||
const blob = await response.blob();
|
||||
// 重新添加到AppStore
|
||||
const newUrl = useAppStore.getState().addBlob(blob);
|
||||
referenceImageBlobs.push(blob);
|
||||
// 更新uploadedImages中的URL
|
||||
const index = uploadedImages.indexOf(img);
|
||||
if (index !== -1) {
|
||||
const newImages = [...uploadedImages];
|
||||
newImages[index] = newUrl;
|
||||
useAppStore.getState().clearUploadedImages();
|
||||
newImages.forEach(imageUrl => useAppStore.getState().addUploadedImage(imageUrl));
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.warn('无法重新获取参考图像:', img, error);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 从URL获取Blob
|
||||
|
||||
Reference in New Issue
Block a user