From 55e86ca5179488ae6687203fb61dc5de5acc5a8a Mon Sep 17 00:00:00 2001 From: shiyue <935732994@qq.com> Date: Tue, 2 Sep 2025 16:38:50 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84:=20=E4=BC=98=E5=8C=96indexed?= =?UTF-8?q?DBStorage=E4=B8=AD=E7=9A=84=E5=9B=BE=E5=83=8F=E5=AD=98=E5=82=A8?= =?UTF-8?q?=E5=92=8CuiController=E4=B8=AD=E7=9A=84URL=E5=A4=84=E7=90=86?= =?UTF-8?q?=E9=80=BB=E8=BE=91=EF=BC=8C=E7=A1=AE=E4=BF=9DBlob=20URL?= =?UTF-8?q?=E5=92=8CBase64=E6=95=B0=E6=8D=AE=E7=9A=84=E4=B8=80=E8=87=B4?= =?UTF-8?q?=E6=80=A7=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script.js | 205 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 180 insertions(+), 25 deletions(-) diff --git a/script.js b/script.js index b9271a3..4d7f22a 100644 --- a/script.js +++ b/script.js @@ -58,6 +58,12 @@ const utils = { return base64Data; } + // 检查是否是base64数据格式 + if (!base64Data.startsWith('data:image/')) { + console.warn('Not a valid base64 image format, returning original data'); + return base64Data; + } + // 提取base64数据的MIME类型和纯数据部分 const parts = base64Data.split(';base64,'); if (parts.length !== 2) { @@ -399,15 +405,43 @@ const indexedDBStorage = { } try { - const transaction = this.db.transaction([CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES], 'readwrite'); - const store = transaction.objectStore(CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES); - - // 检查是否是Blob URL,如果是则获取原始base64数据 + // 首先处理图像URL,获取要存储的数据 let storedUrl = imageUrl; if (imageUrl.startsWith('blob:') && imageUrl._originalBase64) { storedUrl = imageUrl._originalBase64; + console.log('Storing original base64 data for image'); + } else if (imageUrl.startsWith('data:image/')) { + // 已经是base64格式,直接存储 + console.log('Image is already in base64 format, storing directly'); + } else if (imageUrl.startsWith('blob:')) { + // Blob URL没有原始base64数据,需要从Blob URL中提取base64数据 + console.warn('Blob URL has no original base64 data, attempting to extract base64 data from Blob'); + try { + // 通过fetch获取Blob数据,然后转换为base64 + const response = await fetch(imageUrl); + const blob = await response.blob(); + + // 将Blob转换为base64 + const reader = new FileReader(); + const base64Promise = new Promise((resolve, reject) => { + reader.onload = () => resolve(reader.result); + reader.onerror = reject; + }); + reader.readAsDataURL(blob); + + storedUrl = await base64Promise; + console.log('Successfully extracted base64 data from Blob URL'); + } catch (error) { + console.error('Failed to extract base64 data from Blob URL:', error); + // 如果转换失败,仍然存储原始URL,但记录警告 + console.warn('Storing original Blob URL, which may cause issues after page reload'); + } } + // 现在创建事务并存储数据 + const transaction = this.db.transaction([CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES], 'readwrite'); + const store = transaction.objectStore(CONFIG.INDEXED_DB.STORES.GENERATED_IMAGES); + const image = { imageId: imageId, url: storedUrl, @@ -717,7 +751,9 @@ const apiService = { // 提取图像数据并转换为Blob URL,但保留原始base64数据 if (choice.message.images) { choice.message.images.forEach(img => { - const blobUrl = utils.base64ToBlobUrl(img.image_url.url); + // 确保原始数据是base64格式 + const originalBase64 = img.image_url.url; + const blobUrl = utils.base64ToBlobUrl(originalBase64); images.push(blobUrl); }); } @@ -821,7 +857,23 @@ const uiController = { const imageId = Date.now() + Math.random(); // 确保imageUrl是Blob URL用于显示,但保存原始URL用于存储 - const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl); + let displayUrl; + let originalUrl = imageUrl; // 原始URL,可能是base64或Blob URL + + if (imageUrl.startsWith('blob:')) { + displayUrl = imageUrl; + } else if (imageUrl.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + displayUrl = utils.base64ToBlobUrl(imageUrl); + } else { + // 其他格式,直接使用 + displayUrl = imageUrl; + } + + // 确保Blob URL有原始base64数据 + if (displayUrl.startsWith('blob:') && !displayUrl._originalBase64 && originalUrl.startsWith('data:image/')) { + displayUrl._originalBase64 = originalUrl; + } imageDiv.innerHTML = ` Generated Image @@ -935,7 +987,23 @@ const uiController = { placeholder.id = ''; // 确保imageUrl是Blob URL用于显示,但保存原始URL用于存储 - const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl); + let displayUrl; + let originalUrl = imageUrl; // 原始URL,可能是base64或Blob URL + + if (imageUrl.startsWith('blob:')) { + displayUrl = imageUrl; + } else if (imageUrl.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + displayUrl = utils.base64ToBlobUrl(imageUrl); + } else { + // 其他格式,直接使用 + displayUrl = imageUrl; + } + + // 确保Blob URL有原始base64数据 + if (displayUrl.startsWith('blob:') && !displayUrl._originalBase64 && originalUrl.startsWith('data:image/')) { + displayUrl._originalBase64 = originalUrl; + } placeholder.innerHTML = ` Generated Image @@ -1057,7 +1125,17 @@ const uiController = { currentImageIndex = generatedImages.findIndex(img => img.url === imageUrl); // 设置图像源 - 确保正确处理base64和Blob URL - const displayUrl = imageUrl.startsWith('blob:') ? imageUrl : utils.base64ToBlobUrl(imageUrl); + let displayUrl; + if (imageUrl.startsWith('blob:')) { + displayUrl = imageUrl; + } else if (imageUrl.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + displayUrl = utils.base64ToBlobUrl(imageUrl); + } else { + // 其他格式,直接使用 + displayUrl = imageUrl; + } + modalImage.src = displayUrl; modalImage.onerror = function() { utils.showNotification('图像加载失败', 'danger'); @@ -1066,7 +1144,7 @@ const uiController = { // 设置下载按钮功能 if (downloadButton) { downloadButton.onclick = function() { - app.downloadImage(imageUrl); + app.downloadImage(generatedImages[currentImageIndex].url); }; } @@ -1086,7 +1164,10 @@ const uiController = { // 重新加载当前图像 if (currentImageIndex >= 0 && currentImageIndex < generatedImages.length) { - modalImage.src = generatedImages[currentImageIndex].url; + const displayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ? + generatedImages[currentImageIndex].url : + utils.base64ToBlobUrl(generatedImages[currentImageIndex].url); + modalImage.src = displayUrl; } this.updateNavigationButtons(); @@ -1285,12 +1366,21 @@ const uiController = { // 更新图片 const modalImage = document.getElementById('viewerModalImage'); const deleteButton = document.getElementById('viewerDeleteImage'); + const downloadButton = document.getElementById('viewerDownloadImage'); if (modalImage && generatedImages[currentImageIndex]) { // 确保正确处理base64和Blob URL - const displayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ? - generatedImages[currentImageIndex].url : - utils.base64ToBlobUrl(generatedImages[currentImageIndex].url); + const imageUrl = generatedImages[currentImageIndex].url; + let displayUrl; + if (imageUrl.startsWith('blob:')) { + displayUrl = imageUrl; + } else if (imageUrl.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + displayUrl = utils.base64ToBlobUrl(imageUrl); + } else { + // 其他格式,直接使用 + displayUrl = imageUrl; + } modalImage.src = displayUrl; // 更新删除按钮对应的图像ID @@ -1306,9 +1396,17 @@ const uiController = { currentImageIndex = generatedImages.length - 1; } if (currentImageIndex >= 0 && currentImageIndex < generatedImages.length) { - const newDisplayUrl = generatedImages[currentImageIndex].url.startsWith('blob:') ? - generatedImages[currentImageIndex].url : - utils.base64ToBlobUrl(generatedImages[currentImageIndex].url); + const imageUrl = generatedImages[currentImageIndex].url; + let newDisplayUrl; + if (imageUrl.startsWith('blob:')) { + newDisplayUrl = imageUrl; + } else if (imageUrl.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + newDisplayUrl = utils.base64ToBlobUrl(imageUrl); + } else { + // 其他格式,直接使用 + newDisplayUrl = imageUrl; + } modalImage.src = newDisplayUrl; deleteButton.onclick = arguments.callee; } @@ -1316,6 +1414,13 @@ const uiController = { } }; } + + // 更新下载按钮对应的图像URL + if (downloadButton) { + downloadButton.onclick = function() { + app.downloadImage(generatedImages[currentImageIndex].url); + }; + } } // 更新导航按钮状态 @@ -1382,7 +1487,16 @@ const uiController = { const preview = document.getElementById('imagePreview'); // 确保图像数据是Blob URL用于显示,但保持原始数据用于其他操作 - const displayUrl = imageData.data.startsWith('blob:') ? imageData.data : utils.base64ToBlobUrl(imageData.data); + let displayUrl; + if (imageData.data.startsWith('blob:')) { + displayUrl = imageData.data; + } else if (imageData.data.startsWith('data:image/')) { + // 这是base64数据,转换为Blob URL + displayUrl = utils.base64ToBlobUrl(imageData.data); + } else { + // 其他格式,直接使用 + displayUrl = imageData.data; + } preview.innerHTML = `
@@ -1508,8 +1622,16 @@ const uiController = { const imageDiv = document.createElement('div'); imageDiv.className = 'image-item fade-in'; - // 确保从IndexedDB加载的base64数据转换为Blob URL用于显示 - const displayUrl = img.url.startsWith('blob:') ? img.url : utils.base64ToBlobUrl(img.url); + // 从IndexedDB加载的数据应该是base64格式,直接使用 + // 如果是base64数据,创建一个新的Blob URL用于显示 + let displayUrl; + if (img.url.startsWith('data:image/')) { + // 这是base64数据 + displayUrl = utils.base64ToBlobUrl(img.url); + } else { + // 这可能是其他格式的URL,直接使用 + displayUrl = img.url; + } imageDiv.innerHTML = ` Generated Image @@ -1881,7 +2003,13 @@ const app = { // 为每个图像添加新的图像项 result.response.images.forEach((img, imgIndex) => { - uiController.addGeneratedImage(img); + // 确保Blob URL有原始base64数据 + if (img.startsWith('blob:') && img._originalBase64) { + uiController.addGeneratedImage(img); + } else { + // 如果没有原始base64数据,需要从API响应中获取 + uiController.addGeneratedImage(img); + } }); } else { // 只有一个图像,直接替换占位符 @@ -2035,7 +2163,7 @@ const app = { utils.showNotification('下载图像失败', 'danger'); }); } else { - // 如果是普通URL,直接下载 + // 如果是base64数据,直接下载 const link = document.createElement('a'); link.href = imageUrl; link.download = `generated-image-${Date.now()}.png`; @@ -2056,10 +2184,37 @@ const app = { // 逐个下载图像 generatedImages.forEach((img, index) => { setTimeout(() => { - const link = document.createElement('a'); - link.href = img.url; - link.download = `generated-image-${Date.now()}-${index + 1}.png`; - link.click(); + // 使用与单个图像下载相同的逻辑 + if (img.url.startsWith('blob:') && img.url._originalBase64) { + // 使用原始base64数据下载 + const link = document.createElement('a'); + link.href = img.url._originalBase64; + link.download = `generated-image-${Date.now()}-${index + 1}.png`; + link.click(); + } else if (img.url.startsWith('blob:')) { + // 如果没有原始base64数据,通过fetch获取Blob数据 + fetch(img.url) + .then(response => response.blob()) + .then(blob => { + const url = URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = `generated-image-${Date.now()}-${index + 1}.png`; + link.click(); + // 清理临时URL + setTimeout(() => URL.revokeObjectURL(url), 100); + }) + .catch(error => { + console.error('Error downloading image:', error); + utils.showNotification('下载图像失败', 'danger'); + }); + } else { + // 如果是base64数据,直接下载 + const link = document.createElement('a'); + link.href = img.url; + link.download = `generated-image-${Date.now()}-${index + 1}.png`; + link.click(); + } // 最后一个图像下载完成后显示通知 if (index === generatedImages.length - 1) {