// ========== 初始化二维码 ========== document.addEventListener('DOMContentLoaded', function () { new QRCode(document.getElementById('qrcode'), { text: SERVER_URL, width: 140, height: 140, colorDark: '#333333', colorLight: '#ffffff', correctLevel: QRCode.CorrectLevel.M }); loadFiles(); }); // ========== 复制链接 ========== function copyUrl() { const url = document.getElementById('urlValue').textContent; navigator.clipboard.writeText(url).then(() => { const btn = document.querySelector('.btn-copy'); const original = btn.textContent; btn.textContent = '已复制 ✓'; setTimeout(() => btn.textContent = original, 1500); }).catch(() => { // 兼容旧浏览器 const input = document.createElement('input'); input.value = url; document.body.appendChild(input); input.select(); document.execCommand('copy'); document.body.removeChild(input); }); } // ========== 上传相关 ========== const dropZone = document.getElementById('dropZone'); const fileInput = document.getElementById('fileInput'); const progressContainer = document.getElementById('progressContainer'); const progressFill = document.getElementById('progressFill'); const progressName = document.getElementById('progressName'); const progressPercent = document.getElementById('progressPercent'); // 点击触发文件选择 dropZone.addEventListener('click', () => fileInput.click()); // 文件选择 fileInput.addEventListener('change', (e) => { if (e.target.files.length) { uploadFiles(Array.from(e.target.files)); fileInput.value = ''; } }); // 拖拽事件 ['dragenter', 'dragover'].forEach(evt => { dropZone.addEventListener(evt, (e) => { e.preventDefault(); e.stopPropagation(); dropZone.classList.add('dragover'); }); }); ['dragleave', 'drop'].forEach(evt => { dropZone.addEventListener(evt, (e) => { e.preventDefault(); e.stopPropagation(); dropZone.classList.remove('dragover'); }); }); dropZone.addEventListener('drop', (e) => { const files = Array.from(e.dataTransfer.files); if (files.length) uploadFiles(files); }); // 批量上传 function uploadFiles(files) { let index = 0; const total = files.length; function next() { if (index >= total) { progressContainer.style.display = 'none'; loadFiles(); return; } const file = files[index]; index++; uploadSingle(file, () => next()); } next(); } // 单个文件上传 function uploadSingle(file, callback) { const formData = new FormData(); formData.append('file', file); const xhr = new XMLHttpRequest(); progressContainer.style.display = 'block'; progressName.textContent = file.name; progressFill.style.width = '0%'; progressPercent.textContent = '0%'; xhr.upload.addEventListener('progress', (e) => { if (e.lengthComputable) { const percent = Math.round((e.loaded / e.total) * 100); progressFill.style.width = percent + '%'; progressPercent.textContent = percent + '%'; } }); xhr.addEventListener('load', () => { progressFill.style.width = '100%'; progressPercent.textContent = '100%'; setTimeout(callback, 300); }); xhr.addEventListener('error', () => { alert('上传失败:' + file.name); callback(); }); xhr.open('POST', '/upload'); xhr.send(formData); } // ========== 文件列表 ========== function loadFiles() { fetch('/files') .then(res => res.json()) .then(files => renderFiles(files)) .catch(err => console.error('加载文件失败', err)); } function renderFiles(files) { const list = document.getElementById('fileList'); if (!files.length) { list.innerHTML = '