Files
image-tools/templates/index.html
Julian Freeman e6b7c8d34d add basic files
2025-06-26 13:54:35 -04:00

341 lines
11 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>图像处理工具集</title>
<link rel="icon" href="/static/favicon.ico" type="image/x-icon">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<style>
body {
font-family: "Segoe UI", sans-serif;
background: linear-gradient(to right, #f0f2f5, #dfe4ea);
padding: 40px;
}
.container {
max-width: 600px;
margin: auto;
background: white;
padding: 30px 40px;
border-radius: 16px;
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.08);
animation: fadeIn 0.8s ease-in-out;
margin-bottom: 30px; /* 增加卡片之间的间隙 */
}
.logo {
text-align: center;
font-size: 28px;
color: #4a90e2;
margin-bottom: 20px;
}
.logo i {
margin-right: 10px;
}
h2 {
text-align: center;
font-size: 22px;
margin-bottom: 12px;
}
.notice {
font-size: 14px;
color: #666;
margin-bottom: 18px;
text-align: center;
}
.drop-zone {
border: 2px dashed #ccc;
border-radius: 12px;
padding: 30px;
text-align: center;
color: #888;
cursor: pointer;
margin-bottom: 16px;
transition: all 0.3s ease;
}
.drop-zone.dragover {
background: #eef6ff;
border-color: #4a90e2;
color: #4a90e2;
}
.drop-zone i {
font-size: 36px;
margin-bottom: 10px;
display: block;
color: #bbb;
}
button {
background-color: #4a90e2;
color: white;
padding: 10px 20px;
border: none;
border-radius: 8px;
font-size: 16px;
cursor: pointer;
display: flex;
align-items: center;
gap: 8px;
transition: background-color 0.3s, transform 0.2s;
}
button:hover {
background-color: #357abd;
transform: scale(1.02);
}
.progress-container {
margin-top: 15px;
height: 12px;
background: #e0e0e0;
border-radius: 8px;
overflow: hidden;
display: none;
}
.progress-bar {
width: 0%;
height: 100%;
background-color: #4a90e2;
transition: width 0.3s ease;
}
.spinner {
text-align: center;
font-size: 15px;
color: #555;
margin-top: 12px;
display: none;
}
.spinner i {
margin-right: 6px;
}
.download-link {
margin-top: 20px;
text-align: center;
font-size: 16px;
}
.download-link i {
margin-right: 6px;
}
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(20px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body>
<div class="container">
<div class="logo">
<i class="fas fa-image"></i> 边框背景图像调整尺寸
</div>
<h2>将不同比例的边框图片调整为 800x1000 尺寸</h2>
<p class="notice">支持批量上传 PNG / JPG / WebP 图片,推荐使用竖图(比例 9:16 或 3:4</p>
<div class="drop-zone" id="dropZone" title="支持拖拽上传图片或点击选择文件">
<i class="fas fa-cloud-upload-alt"></i>
拖拽图片到这里,或点击选择
</div>
<form id="uploadForm" enctype="multipart/form-data" style="display: none;">
<input type="file" id="fileInput" name="files" multiple accept="image/png, image/jpeg, image/webp">
</form>
<div class="progress-container" id="progressContainer">
<div class="progress-bar" id="progressBar"></div>
</div>
<div class="spinner" id="loadingSpinner">
<i class="fas fa-circle-notch fa-spin"></i> 正在处理,请稍候...
</div>
<div class="download-link" id="result"></div>
</div>
<div class="container">
<div class="logo">
<i class="fas fa-image"></i> 图像背景移除
</div>
<h2>批量移除图片背景</h2>
<p class="notice">支持批量上传 PNG / JPG 图片,移除背景后可下载结果</p>
<div class="drop-zone" id="bgRemoveDropZone" title="支持拖拽上传图片或点击选择文件">
<i class="fas fa-cloud-upload-alt"></i>
拖拽图片到这里,或点击选择
</div>
<form id="bgRemoveForm" enctype="multipart/form-data" style="display: none;">
<input type="file" id="bgRemoveFileInput" name="files" multiple accept="image/png, image/jpeg">
</form>
<div class="progress-container" id="bgRemoveProgressContainer">
<div class="progress-bar" id="bgRemoveProgressBar"></div>
</div>
<div class="spinner" id="bgRemoveLoadingSpinner">
<i class="fas fa-circle-notch fa-spin"></i> 正在处理,请稍候...
</div>
<div class="download-link" id="bgRemoveResult"></div>
</div>
<script>
const dropZone = document.getElementById("dropZone");
const fileInput = document.getElementById("fileInput");
const progressBar = document.getElementById("progressBar");
const progressContainer = document.getElementById("progressContainer");
const resultBox = document.getElementById("result");
const spinner = document.getElementById("loadingSpinner");
dropZone.addEventListener("click", () => fileInput.click());
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;
uploadFiles(fileInput.files);
});
fileInput.addEventListener("change", () => {
if (fileInput.files.length > 0) {
uploadFiles(fileInput.files);
}
});
async function uploadFiles(files) {
resultBox.innerHTML = "";
progressBar.style.width = "0%";
progressContainer.style.display = "block";
spinner.style.display = "block";
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
const xhr = new XMLHttpRequest();
xhr.open("POST", "/upload", true);
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
progressBar.style.width = percent + "%";
}
};
xhr.onload = function () {
spinner.style.display = "none";
progressContainer.style.display = "none";
if (xhr.status === 200) {
const res = JSON.parse(xhr.responseText);
if (res.download_url) {
resultBox.innerHTML = `<i class="fas fa-check-circle" style="color:green;"></i> <a href='${res.download_url}' download>点击下载处理结果</a>`;
} else {
resultBox.innerHTML = `<i class="fas fa-times-circle" style="color:red;"></i> 上传失败,请检查文件格式。`;
}
} else {
resultBox.innerHTML = `<i class="fas fa-exclamation-circle" style="color:orange;"></i> 上传错误,请稍后重试。`;
}
};
xhr.send(formData);
}
const bgRemoveDropZone = document.getElementById("bgRemoveDropZone");
const bgRemoveFileInput = document.getElementById("bgRemoveFileInput");
const bgRemoveProgressBar = document.getElementById("bgRemoveProgressBar");
const bgRemoveProgressContainer = document.getElementById("bgRemoveProgressContainer");
const bgRemoveResultBox = document.getElementById("bgRemoveResult");
const bgRemoveSpinner = document.getElementById("bgRemoveLoadingSpinner");
bgRemoveDropZone.addEventListener("click", () => bgRemoveFileInput.click());
bgRemoveDropZone.addEventListener("dragover", e => {
e.preventDefault();
bgRemoveDropZone.classList.add("dragover");
});
bgRemoveDropZone.addEventListener("dragleave", () => {
bgRemoveDropZone.classList.remove("dragover");
});
bgRemoveDropZone.addEventListener("drop", e => {
e.preventDefault();
bgRemoveDropZone.classList.remove("dragover");
bgRemoveFileInput.files = e.dataTransfer.files;
uploadBgRemoveFiles(bgRemoveFileInput.files);
});
bgRemoveFileInput.addEventListener("change", () => {
if (bgRemoveFileInput.files.length > 0) {
uploadBgRemoveFiles(bgRemoveFileInput.files);
}
});
async function uploadBgRemoveFiles(files) {
bgRemoveResultBox.innerHTML = "";
bgRemoveProgressBar.style.width = "0%";
bgRemoveProgressContainer.style.display = "block";
bgRemoveSpinner.style.display = "block";
const formData = new FormData();
for (let i = 0; i < files.length; i++) {
formData.append("files", files[i]);
}
const xhr = new XMLHttpRequest();
xhr.open("POST", "/remove-bg", true);
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
const percent = Math.round((e.loaded / e.total) * 100);
bgRemoveProgressBar.style.width = percent + "%";
}
};
xhr.onload = function () {
bgRemoveSpinner.style.display = "none";
bgRemoveProgressContainer.style.display = "none";
if (xhr.status === 200) {
const res = JSON.parse(xhr.responseText);
if (res.download_url) {
bgRemoveResultBox.innerHTML = `<i class="fas fa-check-circle" style="color:green;"></i> <a href='${res.download_url}' download>点击下载处理结果</a>`;
} else {
bgRemoveResultBox.innerHTML = `<i class="fas fa-times-circle" style="color:red;"></i> 上传失败,请检查文件格式。`;
}
} else {
bgRemoveResultBox.innerHTML = `<i class="fas fa-exclamation-circle" style="color:orange;"></i> 上传错误,请稍后重试。`;
}
};
xhr.send(formData);
}
</script>
</body>
</html>