diff --git a/script.js b/script.js index 3b05fc0..bb69957 100644 --- a/script.js +++ b/script.js @@ -1318,62 +1318,18 @@ const app = { } }, - // 发送消息 - 生成一张图像 + // 发送消息 - 生成一张图像(使用批量生成方法) sendMessage: async function() { - const messageInput = document.getElementById('messageInput'); - const message = messageInput.value.trim(); + // 临时设置批量数量为1 + const batchCountInput = document.getElementById('batchCount'); + const originalBatchCount = batchCountInput.value; + batchCountInput.value = 1; - if (!message) { - utils.showNotification('请输入消息', 'warning'); - return; - } - - const apiKey = document.getElementById('apiKey').value; - if (!apiKey) { - utils.showNotification(ERROR_MESSAGES.NO_API_KEY, 'warning'); - return; - } - - // 显示加载状态 - uiController.showLoading(true); + // 调用批量生成方法 + await this.sendBatchMessage(); - // 添加用户消息到聊天历史 - uiController.addChatMessage('user', message); - - try { - const response = await apiService.generateImage(message, uploadedImages, currentSettings); - - // 添加助手回复到聊天历史 - uiController.addChatMessage('assistant', response.content); - - // 显示生成的图像 - if (response.images && response.images.length > 0) { - response.images.forEach(img => { - uiController.addGeneratedImage(img); - }); - - // 检查存储空间 - await utils.checkAndCleanStorage(); - - // 提示用户存储空间有限 - utils.showNotification('已生成图像,但请注意本地存储空间有限,建议及时下载重要图像', 'info'); - } - - // 清空输入框 - messageInput.value = ''; - - // 显示使用统计 - if (response.usage) { - console.log('API Usage:', response.usage); - } - - } catch (error) { - console.error('生成图像失败:', error); - uiController.addChatMessage('assistant', `生成图像失败: ${error.message}`); - utils.showNotification(`生成图像失败: ${error.message}`, 'danger'); - } finally { - uiController.showLoading(false); - } + // 恢复原始批量数量 + batchCountInput.value = originalBatchCount; }, // 批量发送消息 @@ -1424,38 +1380,46 @@ const app = { const promises = []; for (let i = 0; i < batchCount; i++) { promises.push( - apiService.generateImage(message, uploadedImages, currentSettings) - .then(response => { - // 保存第一个响应用于添加聊天消息 - if (!firstResponse) { - firstResponse = response; - uiController.addChatMessage('assistant', response.content); - } - - // 显示生成的图像 - if (response.images && response.images.length > 0) { - // 如果返回多个图像,为每个图像创建新的占位符 - if (response.images.length > 1) { - // 移除原始占位符 - const originalPlaceholder = document.getElementById(`placeholder-${i}`); - if (originalPlaceholder) { - originalPlaceholder.remove(); - } - - // 为每个图像添加新的图像项 - response.images.forEach((img, imgIndex) => { - uiController.addGeneratedImage(img); - }); - } else { - // 只有一个图像,直接替换占位符 - uiController.replacePlaceholderWithImage(`placeholder-${i}`, response.images[0]); + this.generateImageWithRetry(message, uploadedImages, currentSettings, i, batchCount) + .then(result => { + if (result.success) { + // 保存第一个响应用于添加聊天消息 + if (!firstResponse) { + firstResponse = result.response; + uiController.addChatMessage('assistant', result.response.content); + } + + // 显示生成的图像 + if (result.response.images && result.response.images.length > 0) { + // 如果返回多个图像,为每个图像创建新的占位符 + if (result.response.images.length > 1) { + // 移除原始占位符 + const originalPlaceholder = document.getElementById(`placeholder-${i}`); + if (originalPlaceholder) { + originalPlaceholder.remove(); + } + + // 为每个图像添加新的图像项 + result.response.images.forEach((img, imgIndex) => { + uiController.addGeneratedImage(img); + }); + } else { + // 只有一个图像,直接替换占位符 + uiController.replacePlaceholderWithImage(`placeholder-${i}`, result.response.images[0]); + } + successCount++; + } else { + // 没有图像数据,但请求成功,这种情况应该不会发生,因为generateImageWithRetry已经检查了 + failCount++; } - successCount++; } else { - // 移除占位符 - const placeholder = document.getElementById(`placeholder-${i}`); - if (placeholder) { - placeholder.remove(); + // 生成失败,检查是否需要保留占位符 + if (!result.keepPlaceholder) { + // 移除占位符(旧的行为) + const placeholder = document.getElementById(`placeholder-${i}`); + if (placeholder) { + placeholder.remove(); + } } failCount++; } @@ -1464,24 +1428,7 @@ const app = { completedCount++; uiController.showBatchStatus(`已完成 ${completedCount}/${batchCount} 张图像...`); - return { index: i, response }; - }) - .catch(error => { - console.error(`生成第 ${i + 1} 张图像失败:`, error); - - // 移除占位符 - const placeholder = document.getElementById(`placeholder-${i}`); - if (placeholder) { - placeholder.remove(); - } - - failCount++; - - // 更新完成计数和状态 - completedCount++; - uiController.showBatchStatus(`已完成 ${completedCount}/${batchCount} 张图像...`); - - return { index: i, error }; + return { index: i, success: result.success }; }) ); } @@ -1508,6 +1455,62 @@ const app = { } }, + // 带重试机制的图像生成方法 + generateImageWithRetry: async function(message, images, settings, imageIndex, totalImages) { + const maxRetries = 5; + let retryCount = 0; + + while (retryCount <= maxRetries) { + try { + const response = await apiService.generateImage(message, images, settings); + + // 检查响应中是否包含图像 + if (!response.images || response.images.length === 0) { + throw new Error('生成响应中没有图像数据'); + } + + return { success: true, response: response }; + } catch (error) { + retryCount++; + console.error(`生成第 ${imageIndex + 1} 张图像失败,重试次数 ${retryCount}/${maxRetries}:`, error); + + if (retryCount <= maxRetries) { + // 更新占位符状态,显示重试信息 + const placeholder = document.getElementById(`placeholder-${imageIndex}`); + if (placeholder) { + const placeholderText = placeholder.querySelector('.image-placeholder-text'); + if (placeholderText) { + placeholderText.textContent = `正在重试生成图像 ${imageIndex + 1}/${totalImages} (${retryCount}/${maxRetries})`; + } + } + + // 等待一段时间后重试,使用指数退避策略 + const delayTime = 1000 * Math.pow(2, retryCount - 1); + await new Promise(resolve => setTimeout(resolve, delayTime)); + } else { + // 重试次数用完,返回失败,但不要移除占位符 + // 更新占位符显示最终失败状态 + const placeholder = document.getElementById(`placeholder-${imageIndex}`); + if (placeholder) { + const placeholderText = placeholder.querySelector('.image-placeholder-text'); + if (placeholderText) { + placeholderText.textContent = `生成图像 ${imageIndex + 1}/${totalImages} 失败,已重试 ${maxRetries} 次`; + } + const placeholderIcon = placeholder.querySelector('.image-placeholder-icon'); + if (placeholderIcon) { + placeholderIcon.className = 'fas fa-exclamation-triangle image-placeholder-icon'; + placeholderIcon.style.color = '#dc3545'; + } + } + return { success: false, error: error, keepPlaceholder: true }; + } + } + } + + // 重试次数用完,返回失败,但不要移除占位符 + return { success: false, error: new Error('重试次数用完'), keepPlaceholder: true }; + }, + // 移除上传的图像 removeImage: function(imageId) { uploadedImages = uploadedImages.filter(img => img.id !== imageId);