重构: sendMessage复用批量生成逻辑,并添加generateImageWithRetry方法实现API请求重试

This commit is contained in:
2025-08-29 13:19:05 +08:00
parent 431e231730
commit 8cfa2a8ac9

205
script.js
View File

@@ -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);