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>&copy; 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>