// 图片数据管理
class ImageManager {
constructor() {
this.images = JSON.parse(localStorage.getItem('images')) || [];
this.currentView = 'grid';
}
addImage(file, name, description) {
const image = {
id: Date.now().toString(),
name: name || file.name,
description: description || '',
url: URL.createObjectURL(file),
uploadTime: new Date().toLocaleString(),
fileSize: this.formatFileSize(file.size),
originalFile: file
};
this.images.unshift(image);
this.saveToStorage();
return image;
}
deleteImage(id) {
this.images = this.images.filter(img => {
if (img.id === id) {
URL.revokeObjectURL(img.url);
return false;
}
return true;
});
this.saveToStorage();
}
updateImage(id, updates) {
const image = this.images.find(img => img.id === id);
if (image) {
Object.assign(image, updates);
this.saveToStorage();
}
}
searchImages(query) {
return this.images.filter(img =>
img.name.toLowerCase().includes(query.toLowerCase()) ||
img.description.toLowerCase().includes(query.toLowerCase())
);
}
sortImages(criteria) {
switch (criteria) {
case 'newest':
return [...this.images].sort((a, b) => b.id - a.id);
case 'oldest':
return [...this.images].sort((a, b) => a.id - b.id);
case 'name':
return [...this.images].sort((a, b) => a.name.localeCompare(b.name));
default:
return this.images;
}
}
saveToStorage() {
localStorage.setItem('images', JSON.stringify(this.images));
}
formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
}
}
// UI控制器
class UIController {
constructor() {
this.imageManager = new ImageManager();
this.selectedFiles = [];
this.init();
}
init() {
this.bindEvents();
this.renderImages();
}
bindEvents() {
// 上传按钮事件
document.getElementById('uploadBtn').addEventListener('click', () => this.showUploadModal());
document.getElementById('firstUploadBtn').addEventListener('click', () => this.showUploadModal());
// 模态框关闭事件
document.getElementById('closeModal').addEventListener('click', () => this.hideUploadModal());
document.getElementById('closeDetail').addEventListener('click', () => this.hideDetailModal());
document.getElementById('cancelUpload').addEventListener('click', () => this.hideUploadModal());
// 文件选择事件
document.getElementById('fileInput').addEventListener('change', (e) => this.handleFileSelect(e));
document.getElementById('uploadArea').addEventListener('click', () => document.getElementById('fileInput').click());
// 拖放事件
this.setupDragAndDrop();
// 搜索和排序事件
document.getElementById('searchInput').addEventListener('input', (e) => this.handleSearch(e.target.value));
document.getElementById('sortSelect').addEventListener('change', (e) => this.handleSort(e.target.value));
document.getElementById('viewSelect').addEventListener('change', (e) => this.handleViewChange(e.target.value));
// 确认上传事件
document.getElementById('confirmUpload').addEventListener('click', () => this.handleUpload());
// 点击外部关闭模态框
document.getElementById('uploadModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) this.hideUploadModal();
});
document.getElementById('detailModal').addEventListener('click', (e) => {
if (e.target === e.currentTarget) this.hideDetailModal();
});
}
setupDragAndDrop() {
const uploadArea = document.getElementById('uploadArea');
['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, this.preventDefaults, false);
});
['dragenter', 'dragover'].forEach(eventName => {
uploadArea.addEventListener(eventName, () => this.highlightArea(), false);
});
['dragleave', 'drop'].forEach(eventName => {
uploadArea.addEventListener(eventName, () => this.unhighlightArea(), false);
});
uploadArea.addEventListener('drop', (e) => this.handleDrop(e), false);
}
preventDefaults(e) {
e.preventDefault();
e.stopPropagation();
}
highlightArea() {
document.getElementById('uploadArea').classList.add('dragover');
}
unhighlightArea() {
document.getElementById('uploadArea').classList.remove('dragover');
}
handleDrop(e) {
const dt = e.dataTransfer;
const files = dt.files;
this.handleFiles(files);
}
handleFileSelect(e) {
this.handleFiles(e.target.files);
}
handleFiles(files) {
this.selectedFiles = Array.from(files);
this.showPreviews();
}
showPreviews() {
const previewContainer = document.getElementById('previewContainer');
const imagePreviews = document.getElementById('imagePreviews');
imagePreviews.innerHTML = '';
this.selectedFiles.forEach((file, index) => {
if (!file.type.startsWith('image/')) return;
const reader = new FileReader();
reader.onload = (e) => {
const previewDiv = document.createElement('div');
previewDiv.className = 'bg-gray-50 rounded-lg p-3';
previewDiv.innerHTML = `
class="789af9988ffb9287 w-full px-2 py-1 text-sm border border-gray-300 rounded focus:ring-2 focus:ring-blue-500 preview-name"
`;
imagePreviews.appendChild(previewDiv);
};
reader.readAsDataURL(file);
});
previewContainer.classList.remove('hidden');
}
showUploadModal() {
document.getElementById('uploadModal').classList.remove('hidden');
}
hideUploadModal() {
document.getElementById('uploadModal').classList.add('hidden');
this.selectedFiles = [];
document.getElementById('previewContainer').classList.add('hidden');
document.getElementById('fileInput').value = '';
}
showDetailModal(image) {
document.getElementById('detailImage').src = image.url;
document.getElementById('detailImage').alt = image.name;
document.getElementById('detailName').value = image.name;
document.getElementById('detailDescription').value = image.description;
document.getElementById('detailUploadTime').textContent = image.uploadTime;
document.getElementById('detailFileSize').textContent = image.fileSize;
document.getElementById('detailModal').classList.remove('hidden');
// 绑定保存和删除事件
document.getElementById('saveDetails').onclick = () => this.saveImageDetails(image.id);
document.getElementById('deleteImage').onclick = () => this.deleteSelectedImage(image.id);
}
hideDetailModal() {
document.getElementById('detailModal').classList.add('hidden');
}
handleUpload() {
const nameInputs = document.getElementsByClassName('preview-name');
const descInputs = document.getElementsByClassName('preview-desc');
this.selectedFiles.forEach((file, index) => {
const name = nameInputs[index]?.value || file.name;
const description = descInputs[index]?.value || '';
this.imageManager.addImage(file, name, description);
});
this.hideUploadModal();
this.renderImages();
this.showNotification('图片上传成功!', 'success');
}
saveImageDetails(id) {
const name = document.getElementById('detailName').value;
const description = document.getElementById('detailDescription').value;
this.imageManager.updateImage(id, { name, description });
this.hideDetailModal();
this.renderImages();
this.showNotification('修改已保存!', 'success');
}
deleteSelectedImage(id) {
if (confirm('确定要删除这张图片吗?此操作不可撤销。')) {
this.imageManager.deleteImage(id);
this.hideDetailModal();
this.renderImages();
this.showNotification('图片已删除!', 'success');
}
}
handleSearch(query) {
const filteredImages = query ? this.imageManager.searchImages(query) : this.imageManager.images;
this.renderImageList(filteredImages);
}
handleSort(criteria) {
const sortedImages = this.imageManager.sortImages(criteria);
this.renderImageList(sortedImages);
}
handleViewChange(view) {
this.currentView = view;
this.renderImages();
}
renderImages() {
this.renderImageList(this.imageManager.images);
}
renderImageList(images) {
const container = document.getElementById('imageContainer');
const emptyState = document.getElementById('emptyState');
if (images.length === 0) {
container.classList.add('hidden');
emptyState.classList.remove('hidden');
return;
}
container.classList.remove('hidden');
emptyState.classList.add('hidden');
container.innerHTML = images.map(image => `
${image.fileSize}
`).join('');
}
showNotification(message, type = 'info') {
// 简单的通知实现
alert(message); // 在实际应用中可替换为更优雅的通知组件
}
}
// 初始化应用
const uiController = new UIController();