feat: 在index.html和script.js中添加图像批量生成功能

This commit is contained in:
2025-08-29 13:05:22 +08:00
parent 960210d961
commit 431e231730
4 changed files with 390 additions and 145 deletions

254
script.js
View File

@@ -668,6 +668,12 @@ const uiController = {
loadingSpinner.style.display = show ? 'block' : 'none';
},
// 隐藏传统加载状态,用于批量生成模式
hideTraditionalLoading: function() {
const loadingSpinner = document.getElementById('loadingSpinner');
loadingSpinner.style.display = 'none';
},
// 添加聊天消息
addChatMessage: async function(role, content) {
const chatHistoryDiv = document.getElementById('chatHistory');
@@ -776,6 +782,119 @@ const uiController = {
await this.saveGeneratedImages(imageId, imageUrl);
},
// 添加占位图像
addImagePlaceholder: function(index, total) {
const gallery = document.getElementById('imageGallery');
const placeholderDiv = document.createElement('div');
placeholderDiv.className = 'image-placeholder fade-in';
placeholderDiv.id = `placeholder-${index}`;
placeholderDiv.innerHTML = `
<div class="image-placeholder-content">
<div class="image-placeholder-spinner"></div>
<i class="fas fa-image image-placeholder-icon"></i>
<div class="image-placeholder-text">
正在生成图像 ${index + 1}/${total}
</div>
</div>
`;
gallery.appendChild(placeholderDiv);
return placeholderDiv;
},
// 替换占位图像为实际图像
replacePlaceholderWithImage: function(placeholderId, imageUrl) {
const placeholder = document.getElementById(placeholderId);
if (!placeholder) return;
const imageId = Date.now() + Math.random();
placeholder.className = 'image-item fade-in';
placeholder.id = '';
placeholder.innerHTML = `
<img src="${imageUrl}" alt="Generated Image" loading="lazy" class="generated-image">
<div class="image-overlay">
<div class="btn-grid">
<div class="btn-grid-row">
<button class="btn btn-sm btn-outline-light view-large-btn" data-image-url="${imageUrl}" title="查看大图">
<i class="fas fa-search-plus"></i>
</button>
<button class="btn btn-sm btn-outline-light download-btn" data-image-url="${imageUrl}" title="下载图像">
<i class="fas fa-download"></i>
</button>
</div>
<div class="btn-grid-row">
<button class="btn btn-sm btn-outline-light copy-url-btn" data-image-url="${imageUrl}" title="复制URL">
<i class="fas fa-copy"></i>
</button>
<button class="btn btn-sm btn-outline-light remove-btn" data-image-id="${imageId}" title="删除">
<i class="fas fa-trash"></i>
</button>
</div>
</div>
</div>
`;
// 添加事件监听器
const viewLargeBtn = placeholder.querySelector('.view-large-btn');
const downloadBtn = placeholder.querySelector('.download-btn');
const copyBtn = placeholder.querySelector('.copy-url-btn');
const removeBtn = placeholder.querySelector('.remove-btn');
if (viewLargeBtn) {
viewLargeBtn.addEventListener('click', (e) => {
e.stopPropagation();
this.viewLargeImage(imageUrl);
});
}
if (downloadBtn) {
downloadBtn.addEventListener('click', (e) => {
e.stopPropagation();
app.downloadImage(imageUrl);
});
}
if (copyBtn) {
copyBtn.addEventListener('click', (e) => {
e.stopPropagation();
app.copyImageUrl(imageUrl);
});
}
if (removeBtn) {
removeBtn.addEventListener('click', (e) => {
e.stopPropagation();
app.removeGeneratedImage(imageId);
});
}
// 添加到内存中的图像记录
generatedImages.push({ id: imageId, url: imageUrl });
// 保存到存储 - 优先使用 IndexedDB
this.saveGeneratedImages(imageId, imageUrl);
},
// 显示批量生成状态
showBatchStatus: function(message, show = true) {
let statusDiv = document.getElementById('batchStatus');
if (!statusDiv) {
statusDiv = document.createElement('div');
statusDiv.id = 'batchStatus';
statusDiv.className = 'batch-status';
document.body.appendChild(statusDiv);
}
statusDiv.textContent = message;
if (show) {
statusDiv.classList.add('show');
} else {
statusDiv.classList.remove('show');
}
},
// 新的查看大图功能
viewLargeImage: function(imageUrl) {
@@ -1199,7 +1318,7 @@ const app = {
}
},
// 发送消息
// 发送消息 - 生成一张图像
sendMessage: async function() {
const messageInput = document.getElementById('messageInput');
const message = messageInput.value.trim();
@@ -1257,6 +1376,138 @@ const app = {
}
},
// 批量发送消息
sendBatchMessage: async function() {
const messageInput = document.getElementById('messageInput');
const batchCountInput = document.getElementById('batchCount');
const message = messageInput.value.trim();
const batchCount = parseInt(batchCountInput.value) || 6;
if (!message) {
utils.showNotification('请输入消息', 'warning');
return;
}
if (batchCount < 1 || batchCount > 10) {
utils.showNotification('请输入有效的生成数量1-10', 'warning');
return;
}
const apiKey = document.getElementById('apiKey').value;
if (!apiKey) {
utils.showNotification(ERROR_MESSAGES.NO_API_KEY, 'warning');
return;
}
// 隐藏传统加载状态,使用占位图像代替
uiController.hideTraditionalLoading();
// 添加用户消息到聊天历史
uiController.addChatMessage('user', message);
// 创建占位图像
const placeholders = [];
for (let i = 0; i < batchCount; i++) {
const placeholder = uiController.addImagePlaceholder(i, batchCount);
placeholders.push(placeholder);
}
// 显示批量生成状态
uiController.showBatchStatus(`正在批量生成 ${batchCount} 张图像...`);
let successCount = 0;
let failCount = 0;
let firstResponse = null;
let completedCount = 0;
// 同时发送所有请求,但每个请求完成后立即处理
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]);
}
successCount++;
} else {
// 移除占位符
const placeholder = document.getElementById(`placeholder-${i}`);
if (placeholder) {
placeholder.remove();
}
failCount++;
}
// 更新完成计数和状态
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 };
})
);
}
// 等待所有请求完成
await Promise.all(promises);
// 检查存储空间
await utils.checkAndCleanStorage();
// 清空输入框
messageInput.value = '';
// 隐藏批量生成状态
setTimeout(() => {
uiController.showBatchStatus('', false);
}, 3000);
// 显示最终结果
if (failCount === 0) {
utils.showNotification(`批量生成完成!成功生成 ${successCount} 张图像`, 'success');
} else {
utils.showNotification(`批量生成完成!成功 ${successCount} 张,失败 ${failCount}`, 'warning');
}
},
// 移除上传的图像
removeImage: function(imageId) {
uploadedImages = uploadedImages.filter(img => img.id !== imageId);
@@ -1338,6 +1589,7 @@ document.addEventListener('DOMContentLoaded', async () => {
// 全局函数供HTML调用
window.testConnection = () => app.testConnection();
window.sendMessage = () => app.sendMessage();
window.sendBatchMessage = () => app.sendBatchMessage();
window.downloadImage = (url) => app.downloadImage(url);
window.copyImageUrl = (url) => app.copyImageUrl(url);
window.removeImage = (id) => app.removeImage(id);