Spaces:
Sleeping
Sleeping
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>批量图片处理工坊 - Batch Image Workshop</title> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet"> | |
| <style> | |
| .drop-zone { | |
| border: 2px dashed #cbd5e1; | |
| transition: all 0.3s ease; | |
| } | |
| .drop-zone.dragover { | |
| border-color: #3b82f6; | |
| background-color: #eff6ff; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-gray-50 min-h-screen text-gray-800 font-sans"> | |
| <div class="container mx-auto px-4 py-8 max-w-4xl"> | |
| <!-- Header --> | |
| <header class="text-center mb-10"> | |
| <h1 class="text-4xl font-bold text-gray-900 mb-2"> | |
| <i class="fas fa-images text-blue-500 mr-2"></i>批量图片处理工坊 | |
| </h1> | |
| <p class="text-gray-600"> | |
| 完全本地运行(CPU),隐私安全。支持批量缩放、格式转换、水印添加。 | |
| </p> | |
| </header> | |
| <form action="/process" method="POST" enctype="multipart/form-data" id="processForm" class="bg-white rounded-xl shadow-lg p-6 md:p-8"> | |
| <!-- Upload Section --> | |
| <div class="mb-8"> | |
| <h2 class="text-xl font-semibold mb-4 flex items-center"> | |
| <span class="bg-blue-100 text-blue-600 rounded-full w-8 h-8 flex items-center justify-center mr-3 text-sm">1</span> | |
| 上传图片 | |
| </h2> | |
| <div id="dropZone" class="drop-zone rounded-lg p-10 text-center cursor-pointer hover:bg-gray-50"> | |
| <input type="file" name="files" id="fileInput" multiple accept="image/*" class="hidden"> | |
| <div class="space-y-3"> | |
| <i class="fas fa-cloud-upload-alt text-4xl text-gray-400"></i> | |
| <div class="text-lg text-gray-600">点击或拖拽图片到这里</div> | |
| <p class="text-sm text-gray-400" id="fileCount">支持 JPG, PNG, WEBP 等常见格式</p> | |
| </div> | |
| </div> | |
| <div id="fileList" class="mt-4 flex flex-wrap gap-2 text-sm text-gray-600"></div> | |
| </div> | |
| <!-- Settings Section --> | |
| <div class="mb-8"> | |
| <h2 class="text-xl font-semibold mb-4 flex items-center"> | |
| <span class="bg-blue-100 text-blue-600 rounded-full w-8 h-8 flex items-center justify-center mr-3 text-sm">2</span> | |
| 处理选项 | |
| </h2> | |
| <div class="grid grid-cols-1 md:grid-cols-2 gap-6"> | |
| <!-- Format --> | |
| <div class="space-y-2"> | |
| <label class="block font-medium text-gray-700">目标格式</label> | |
| <select name="target_format" class="w-full border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 p-2 border"> | |
| <option value="original">保持原格式</option> | |
| <option value="jpeg">JPG / JPEG</option> | |
| <option value="png">PNG</option> | |
| <option value="webp">WEBP</option> | |
| </select> | |
| </div> | |
| <!-- Resize --> | |
| <div class="space-y-2"> | |
| <label class="block font-medium text-gray-700">调整大小</label> | |
| <div class="flex gap-2"> | |
| <select name="resize_mode" id="resizeMode" class="w-1/2 border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 p-2 border"> | |
| <option value="none">不调整</option> | |
| <option value="percentage">按百分比缩放</option> | |
| <option value="width">固定宽度 (保持比例)</option> | |
| </select> | |
| <input type="number" name="resize_value" id="resizeValue" placeholder="100" class="w-1/2 border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 p-2 border hidden"> | |
| </div> | |
| </div> | |
| <!-- Watermark --> | |
| <div class="space-y-2"> | |
| <label class="block font-medium text-gray-700">文字水印 (可选)</label> | |
| <input type="text" name="watermark_text" placeholder="例如:@我的版权" class="w-full border-gray-300 rounded-md shadow-sm focus:border-blue-500 focus:ring focus:ring-blue-200 p-2 border"> | |
| </div> | |
| <!-- Extras --> | |
| <div class="space-y-2 flex items-center pt-6"> | |
| <label class="inline-flex items-center cursor-pointer"> | |
| <input type="checkbox" name="strip_exif" class="form-checkbox h-5 w-5 text-blue-600" checked> | |
| <span class="ml-2 text-gray-700">清除 EXIF 信息 (隐私保护)</span> | |
| </label> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Submit --> | |
| <div class="text-center"> | |
| <button type="submit" id="submitBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-3 px-10 rounded-full shadow-lg transition duration-200 transform hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed"> | |
| <i class="fas fa-magic mr-2"></i>开始处理并下载 | |
| </button> | |
| </div> | |
| </form> | |
| <footer class="mt-12 text-center text-gray-400 text-sm"> | |
| <p>© 2026 Batch Image Workshop. Open Source Project.</p> | |
| </footer> | |
| </div> | |
| <script> | |
| const dropZone = document.getElementById('dropZone'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const fileList = document.getElementById('fileList'); | |
| const fileCount = document.getElementById('fileCount'); | |
| const resizeMode = document.getElementById('resizeMode'); | |
| const resizeValue = document.getElementById('resizeValue'); | |
| const processForm = document.getElementById('processForm'); | |
| const submitBtn = document.getElementById('submitBtn'); | |
| // Drag & Drop interactions | |
| dropZone.addEventListener('dragover', (e) => { | |
| e.preventDefault(); | |
| dropZone.classList.add('dragover'); | |
| }); | |
| dropZone.addEventListener('dragleave', () => { | |
| dropZone.classList.remove('dragover'); | |
| }); | |
| dropZone.addEventListener('drop', (e) => { | |
| e.preventDefault(); | |
| dropZone.classList.remove('dragover'); | |
| fileInput.files = e.dataTransfer.files; | |
| updateFileList(); | |
| }); | |
| dropZone.addEventListener('click', () => { | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', updateFileList); | |
| function updateFileList() { | |
| const files = fileInput.files; | |
| if (files.length > 0) { | |
| fileCount.innerText = `已选择 ${files.length} 个文件`; | |
| fileList.innerHTML = ''; | |
| // Only show first 5 names | |
| Array.from(files).slice(0, 5).forEach(file => { | |
| const span = document.createElement('span'); | |
| span.className = 'bg-gray-100 px-2 py-1 rounded border'; | |
| span.innerText = file.name; | |
| fileList.appendChild(span); | |
| }); | |
| if (files.length > 5) { | |
| const more = document.createElement('span'); | |
| more.innerText = `... 等共 ${files.length} 个文件`; | |
| fileList.appendChild(more); | |
| } | |
| } else { | |
| fileCount.innerText = '支持 JPG, PNG, WEBP 等常见格式'; | |
| fileList.innerHTML = ''; | |
| } | |
| } | |
| // Resize inputs logic | |
| resizeMode.addEventListener('change', () => { | |
| if (resizeMode.value === 'none') { | |
| resizeValue.classList.add('hidden'); | |
| } else { | |
| resizeValue.classList.remove('hidden'); | |
| if (resizeMode.value === 'percentage') { | |
| resizeValue.placeholder = '缩放比例 % (例如 50)'; | |
| resizeValue.value = 50; | |
| } else { | |
| resizeValue.placeholder = '目标宽度 px (例如 800)'; | |
| resizeValue.value = 800; | |
| } | |
| } | |
| }); | |
| // Form Submit | |
| processForm.addEventListener('submit', () => { | |
| if (fileInput.files.length === 0) { | |
| alert('请先上传图片!'); | |
| event.preventDefault(); | |
| return; | |
| } | |
| // Show loading state | |
| submitBtn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>处理中...'; | |
| submitBtn.disabled = true; | |
| // Re-enable after a few seconds (since download doesn't trigger page reload) | |
| setTimeout(() => { | |
| submitBtn.innerHTML = '<i class="fas fa-magic mr-2"></i>开始处理并下载'; | |
| submitBtn.disabled = false; | |
| }, 3000); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |