diff --git a/src/components/HistoryPanel.tsx b/src/components/HistoryPanel.tsx
index dd2c7e2..6840157 100644
--- a/src/components/HistoryPanel.tsx
+++ b/src/components/HistoryPanel.tsx
@@ -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 (
-

+ {displayUrl ? (
+

{
+ // 如果图像加载失败,尝试重新创建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;
+ }
+ });
+ }
+ }}
+ />
+ ) : (
+
+
+
+ )}
);
})}
@@ -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 (
-

+ {displayUrl ? (
+

{
+ // 如果图像加载失败,尝试重新创建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;
+ }
+ });
+ }
+ }}
+ />
+ ) : (
+
+
+
+ )}
);
})}
@@ -1166,6 +1312,95 @@ export const HistoryPanel: React.FC<{
)}
+ {/* 编辑结果图像 */}
+ {selectedEdit.outputAssets && selectedEdit.outputAssets.length > 0 && (
+
+
编辑结果
+
+ {selectedEdit.outputAssets.length} 个编辑结果
+
+
+ {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 (
+
{
+ e.stopPropagation();
+ setPreviewModal({
+ open: true,
+ imageUrl: displayUrl,
+ title: `编辑结果 ${index + 1}`,
+ description: `${asset.width} × ${asset.height}`
+ });
+ }}
+ >
+ {displayUrl ? (
+

{
+ // 如果图像加载失败,尝试重新创建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;
+ }
+ });
+ }
+ }}
+ />
+ ) : (
+
+
+
+ )}
+
+ );
+ })}
+ {selectedEdit.outputAssets.length > 4 && (
+
+ +{selectedEdit.outputAssets.length - 4}
+
+ )}
+
+
+ )}
+
{/* 原始生成参考 */}
{parentGen && (
@@ -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 (
-

+ {displayUrl ? (
+

{
+ // 如果图像加载失败,尝试重新创建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;
+ }
+ });
+ }
+ }}
+ />
+ ) : (
+
+
+
+ )}
);
})}
diff --git a/src/components/ImageCanvas.tsx b/src/components/ImageCanvas.tsx
index 10e6f97..a79d6bd 100644
--- a/src/components/ImageCanvas.tsx
+++ b/src/components/ImageCanvas.tsx
@@ -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可以访问');
}
diff --git a/src/components/PromptComposer.tsx b/src/components/PromptComposer.tsx
index 6865fae..6f0dbd8 100644
--- a/src/components/PromptComposer.tsx
+++ b/src/components/PromptComposer.tsx
@@ -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
diff --git a/src/hooks/useImageGeneration.ts b/src/hooks/useImageGeneration.ts
index 0411cfe..6d4659d 100644
--- a/src/hooks/useImageGeneration.ts
+++ b/src/hooks/useImageGeneration.ts
@@ -275,6 +275,34 @@ export const useImageEditing = () => {
const blob = useAppStore.getState().getBlob(img);
if (blob) {
referenceImageBlobs.push(blob);
+ } else {
+ // 如果在AppStore中找不到Blob,尝试重新获取
+ try {
+ const response = await fetch(img);
+ if (response.ok) {
+ const blob = await response.blob();
+ referenceImageBlobs.push(blob);
+ // 重新添加到AppStore
+ const newUrl = useAppStore.getState().addBlob(blob);
+ // 更新editReferenceImages中的URL
+ const index = editReferenceImages.indexOf(img);
+ if (index !== -1) {
+ const { removeEditReferenceImage, addEditReferenceImage } = useAppStore.getState();
+ removeEditReferenceImage(index);
+ // 重新添加所有图像以保持顺序
+ const currentImages = [...editReferenceImages];
+ currentImages[index] = newUrl;
+ // 清空并重新添加
+ for (let i = 0; i < currentImages.length; i++) {
+ if (i < 2) { // 最多2张参考图像
+ addEditReferenceImage(currentImages[i]);
+ }
+ }
+ }
+ }
+ } catch (error) {
+ console.warn('无法重新获取参考图像:', img, error);
+ }
}
} else if (img.includes('base64,')) {
// 从base64数据创建Blob
diff --git a/src/store/useAppStore.ts b/src/store/useAppStore.ts
index c635875..e9bf353 100644
--- a/src/store/useAppStore.ts
+++ b/src/store/useAppStore.ts
@@ -637,8 +637,25 @@ export const useAppStore = create
()(
const isUsedInUploads = state.uploadedImages.includes(url);
const isUsedInEdits = state.editReferenceImages.includes(url);
+ // 检查是否是历史记录中的参考图像
+ const isUsedAsReference = state.currentProject && (
+ state.currentProject.generations.some(gen =>
+ gen.sourceAssets.some(asset => asset.blobUrl === url)
+ ) ||
+ state.currentProject.edits.some(edit =>
+ (edit.maskReferenceAssetBlobUrl === url)
+ )
+ );
+
+ // 检查是否是当前编辑操作中的参考图像
+ const isUsedInCurrentEdit = state.editReferenceImages.includes(url);
+
+ // 检查是否是当前生成操作中的参考图像
+ const isUsedInCurrentGeneration = state.uploadedImages.includes(url);
+
// 如果Blob没有被使用,则清理它
- if (!isUsedInProject && !isUsedInCanvas && !isUsedInUploads && !isUsedInEdits) {
+ // 但保留仍在作为参考图像使用的Blob
+ if (!isUsedInProject && !isUsedInCanvas && !isUsedInUploads && !isUsedInEdits && !isUsedAsReference && !isUsedInCurrentEdit && !isUsedInCurrentGeneration) {
URL.revokeObjectURL(url);
const newBlobStore = new Map(state.blobStore);
newBlobStore.delete(url);