feat: 支持多图像上传和预览
This commit is contained in:
14
index.html
14
index.html
@@ -88,19 +88,21 @@
|
||||
<div class="mb-4">
|
||||
<h5><i class="fas fa-upload me-2"></i>上传参考图像</h5>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="col-md-4">
|
||||
<div class="border-2 border-dashed rounded p-4 text-center h-100 d-flex flex-column justify-content-center" id="dropZone">
|
||||
<i class="fas fa-cloud-upload-alt fa-3x text-muted mb-3"></i>
|
||||
<p class="text-muted">拖拽图像到此处或点击选择文件</p>
|
||||
<input type="file" class="d-none" id="imageInput" accept="image/*">
|
||||
<p class="text-muted">拖拽图像到此处或点击选择文件 (最多10张)</p>
|
||||
<input type="file" class="d-none" id="imageInput" accept="image/*" multiple>
|
||||
<button class="btn btn-outline-primary" onclick="document.getElementById('imageInput').click()">
|
||||
选择图像
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div id="imagePreview" class="h-100 d-flex align-items-center justify-content-center">
|
||||
<p class="text-muted">未选择图像</p>
|
||||
<div class="col-md-8">
|
||||
<div class="row" id="imagePreview" style="max-height: 250px; overflow-y: auto; border: 1px solid #dee2e6; border-radius: .25rem; padding-top: 1rem;">
|
||||
<div class="col-12 d-flex h-100 align-items-center justify-content-center">
|
||||
<p class="text-muted">未选择图像</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
44
script.js
44
script.js
@@ -17,7 +17,7 @@ let currentModalInstance = null; // 当前模态框实例
|
||||
// 配置常量
|
||||
const CONFIG = {
|
||||
MAX_FILE_SIZE: 10485760, // 10MB
|
||||
MAX_FILES_PER_UPLOAD: 1, // 限制为只上传一张图片
|
||||
MAX_FILES_PER_UPLOAD: 10, // 限制为最多上传10张图片
|
||||
SUPPORTED_IMAGE_FORMATS: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'],
|
||||
MAX_CHAT_HISTORY: 50, // 减少聊天历史记录数量以节省存储空间
|
||||
MAX_GENERATED_IMAGES: 20, // 减少存储的图像数量以防止存储空间溢出
|
||||
@@ -718,7 +718,8 @@ const apiService = {
|
||||
const payload = {
|
||||
model: settings.model,
|
||||
messages: messages,
|
||||
stream: false
|
||||
stream: false,
|
||||
"modalities": ["image","text"]
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
@@ -1485,6 +1486,10 @@ const uiController = {
|
||||
// 显示图像预览
|
||||
displayImagePreview: function(imageData) {
|
||||
const preview = document.getElementById('imagePreview');
|
||||
const placeholderContainer = preview.querySelector('.col-12.d-flex');
|
||||
if (placeholderContainer) {
|
||||
placeholderContainer.remove();
|
||||
}
|
||||
|
||||
// 确保图像数据是Blob URL用于显示,但保持原始数据用于其他操作
|
||||
let displayUrl;
|
||||
@@ -1498,19 +1503,25 @@ const uiController = {
|
||||
displayUrl = imageData.data;
|
||||
}
|
||||
|
||||
preview.innerHTML = `
|
||||
<div class="card h-100">
|
||||
<img src="${displayUrl}" class="card-img-top image-preview h-75" alt="${imageData.name}" loading="lazy" style="object-fit: contain;">
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'col-md-4 mb-3';
|
||||
wrapper.dataset.imageId = imageData.id; // Store imageId here
|
||||
|
||||
wrapper.innerHTML = `
|
||||
<div class="card h-100 uploaded-image-card">
|
||||
<img src="${displayUrl}" class="card-img-top image-preview" alt="${imageData.name}" loading="lazy" style="object-fit: contain; height: 100px;">
|
||||
<div class="card-body p-2">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<small class="text-muted">${utils.formatFileSize(imageData.size)}</small>
|
||||
<small class="text-muted text-truncate" title="${imageData.name}">${imageData.name}</small>
|
||||
<button class="btn btn-sm btn-outline-danger" onclick="app.removeImage(${imageData.id})" title="删除">
|
||||
<i class="fas fa-trash"></i>
|
||||
</button>
|
||||
</div>
|
||||
<small class="text-muted">${utils.formatFileSize(imageData.size)}</small>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
preview.appendChild(wrapper);
|
||||
},
|
||||
|
||||
// 保存聊天历史 - 新增消息时调用
|
||||
@@ -1783,11 +1794,12 @@ const fileHandler = {
|
||||
|
||||
// 处理文件
|
||||
handleFiles: function(files) {
|
||||
const preview = document.getElementById('imagePreview');
|
||||
preview.innerHTML = '';
|
||||
|
||||
// 限制文件数量
|
||||
const filesToProcess = Array.from(files).slice(0, CONFIG.MAX_FILES_PER_UPLOAD);
|
||||
if (uploadedImages.length + files.length > CONFIG.MAX_FILES_PER_UPLOAD) {
|
||||
utils.showNotification(`最多只能上传 ${CONFIG.MAX_FILES_PER_UPLOAD} 张图片。`, 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const filesToProcess = Array.from(files);
|
||||
|
||||
filesToProcess.forEach(file => {
|
||||
try {
|
||||
@@ -2123,11 +2135,13 @@ const app = {
|
||||
removeImage: function(imageId) {
|
||||
uploadedImages = uploadedImages.filter(img => img.id !== imageId);
|
||||
const preview = document.getElementById('imagePreview');
|
||||
const imageElement = preview.querySelector(`[data-image-id="${imageId}"]`);
|
||||
if (imageElement) {
|
||||
imageElement.remove();
|
||||
}
|
||||
|
||||
if (uploadedImages.length === 0) {
|
||||
preview.innerHTML = '<p class="text-muted">未选择图像</p>';
|
||||
} else {
|
||||
preview.innerHTML = '';
|
||||
uploadedImages.forEach(img => uiController.displayImagePreview(img));
|
||||
preview.innerHTML = '<div class="col-12 d-flex h-100 align-items-center justify-content-center"><p class="text-muted">未选择图像</p></div>';
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
Reference in New Issue
Block a user