feat: 在index.html和script.js中添加图像批量生成功能
This commit is contained in:
254
script.js
254
script.js
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user