[add] 新增无人机模块后端项目

[refactor] 重构后端项目
This commit is contained in:
lcj
2025-05-21 11:30:59 +08:00
parent 4c238435d8
commit dc1de34116
1699 changed files with 54361 additions and 325 deletions

View File

@ -0,0 +1,189 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Download Files as ZIP</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
label {
font-weight: bold;
margin-bottom: 10px;
}
input[type="text"] {
width: 300px;
padding: 8px;
margin-bottom: 10px;
border: 1px solid #ccc;
border-radius: 4px;
}
button {
padding: 10px 20px;
background-color: #28a745;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background-color: #ccc;
cursor: not-allowed;
}
#progress-container {
display: none;
margin-top: 20px;
}
progress {
width: 100%;
height: 20px;
}
#progress-text {
margin-top: 5px;
}
.url-input-group {
margin-bottom: 10px;
}
</style>
</head>
<body>
<h1>Download Files as ZIP</h1>
<div id="url-container">
<div class="url-input-group">
<input type="text" class="url-input" placeholder="Enter file URL here">
</div>
</div>
<button id="add-url-btn">Add URL</button>
<br><br>
<button id="download-btn" onclick="downloadFilesAsZip()">Download All as ZIP</button>
<div id="progress-container">
<progress id="progress-bar" value="0" max="100"></progress>
<div id="progress-text">0%</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js"></script>
<script>
document.getElementById('add-url-btn').addEventListener('click', function() {
const urlContainer = document.getElementById('url-container');
const newInput = document.createElement('div');
newInput.className = 'url-input-group';
newInput.innerHTML = '<input type="text" class="url-input" placeholder="Enter file URL here">';
urlContainer.appendChild(newInput);
});
async function downloadFilesAsZip() {
const urlInputs = document.querySelectorAll('.url-input');
const urls = Array.from(urlInputs).map(input => input.value).filter(url => url !== '');
if (urls.length === 0) {
alert('Please enter at least one valid URL.');
return;
}
const downloadBtn = document.getElementById('download-btn');
const progressBar = document.getElementById('progress-bar');
const progressText = document.getElementById('progress-text');
const progressContainer = document.getElementById('progress-container');
downloadBtn.disabled = true;
progressContainer.style.display = 'block';
const zip = new JSZip();
let totalSize = 0;
let loaded = 0;
const progressMap = new Map(); // 记录每个文件的进度
// 更新总进度函数
const updateProgress = () => {
const totalLoaded = Array.from(progressMap.values()).reduce((acc, val) => acc + val, 0);
const totalProgress = totalLoaded / urls.length;
progressBar.value = totalProgress;
progressText.textContent = `${Math.round(totalProgress)}%`;
};
// 并行处理所有文件的下载
const fetchPromises = urls.map(async (url, index) => {
console.log(`Starting download for: ${url}`);
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to download file: ${url}`);
}
const contentLength = response.headers.get('content-length');
let fileSize = 0;
if (contentLength) {
fileSize = parseInt(contentLength, 10);
}
const reader = response.body.getReader();
const chunks = [];
let receivedLength = 0;
// 读取文件流并更新进度
while (true) {
const { done, value } = await reader.read();
if (done) break;
chunks.push(value);
receivedLength += value.length;
// 记录单个文件的下载进度
const fileProgress = (receivedLength / fileSize) * 100;
progressMap.set(index, fileProgress);
updateProgress(); // 更新总进度
}
const blob = new Blob(chunks); // 合并所有块生成一个Blob
const filename = encodeURIComponent(url.split('/').pop()); // 确保文件名安全
zip.file(filename, blob); // 将文件添加到ZIP中
});
try {
await Promise.all(fetchPromises); // 等待所有文件下载完成
// 强制进度到100%
progressBar.value = 100;
progressText.textContent = '100%';
// 生成 ZIP 文件并触发下载
progressText.textContent = 'Packing ZIP...';
const zipBlob = await zip.generateAsync({ type: 'blob' });
const zipName = 'downloaded_files.zip';
const zipUrl = URL.createObjectURL(zipBlob);
const a = document.createElement('a');
a.href = zipUrl;
a.download = zipName;
a.click();
URL.revokeObjectURL(zipUrl); // 清理 URL
// 重置 UI
progressBar.value = 0;
progressText.textContent = '0%';
progressContainer.style.display = 'none';
downloadBtn.disabled = false;
} catch (error) {
console.error('Error during file download or ZIP generation:', error);
alert('Error during file download or ZIP generation: ' + error.message);
downloadBtn.disabled = false;
}
}
</script>
</body>
</html>