Spaces:
Sleeping
Sleeping
File size: 9,653 Bytes
8b1c497 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 | <!DOCTYPE html>
<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>
|