From d0388066a5c0ddf9c22745822e3a7fb673ab4297 Mon Sep 17 00:00:00 2001 From: Your Name Date: Wed, 21 Jan 2026 11:13:21 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E5=84=AA=E5=8C=96=E5=85=A8=E9=A0=81?= =?UTF-8?q?=E6=8B=96=E6=9B=B3=E4=B8=8A=E5=82=B3=E6=94=AF=E6=8F=B4=EF=BC=8C?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E9=98=B2=E9=87=8D=E8=A4=87=E6=AA=A2=E6=9F=A5?= =?UTF-8?q?=E6=A9=9F=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/script.js | 84 +++++++++++++++--------------------------------- 1 file changed, 26 insertions(+), 58 deletions(-) diff --git a/public/script.js b/public/script.js index ec2931c..aaac8a9 100644 --- a/public/script.js +++ b/public/script.js @@ -29,18 +29,27 @@ const getTranslation = (category, key, params) => { return text; }; -dropZone.addEventListener("dragover", (e) => { +// ===== 全頁拖曳上傳支援(UI 零變動版)===== +// 只監聽 dragover 和 drop,不操作任何 UI class +// 這樣虛線框不會變粗、不會閃爍 + +// 防重複機制:記錄最近處理的檔案 +const recentlyProcessedFiles = new Set(); +const getFileKey = (file) => `${file.name}_${file.size}_${file.lastModified}`; +const clearRecentFiles = () => { + setTimeout(() => recentlyProcessedFiles.clear(), 100); +}; + +// 全頁 dragover:只做 preventDefault,防止瀏覽器開啟檔案 +document.addEventListener("dragover", (e) => { e.preventDefault(); - dropZone.classList.add("dragover"); + e.stopPropagation(); }); -dropZone.addEventListener("dragleave", () => { - dropZone.classList.remove("dragover"); -}); - -dropZone.addEventListener("drop", (e) => { +// 全頁 drop:處理檔案上傳 +document.addEventListener("drop", (e) => { e.preventDefault(); - dropZone.classList.remove("dragover"); + e.stopPropagation(); const files = e.dataTransfer.files; @@ -54,60 +63,19 @@ dropZone.addEventListener("drop", (e) => { handleFile(file); } }); - -// ===== 全頁拖曳上傳支援 ===== -// 允許使用者將檔案拖曳到頁面任何位置即可上傳 -// UI 完全不變,只是擴大拖曳的偵測範圍 - -let dragCounter = 0; - -document.addEventListener("dragenter", (e) => { - e.preventDefault(); - dragCounter++; - // 當檔案進入頁面時,顯示 dropzone 的 dragover 效果 - if (e.dataTransfer.types.includes("Files")) { - dropZone.classList.add("dragover"); - } -}); - -document.addEventListener("dragleave", (e) => { - e.preventDefault(); - dragCounter--; - // 只有當完全離開頁面時才移除效果 - if (dragCounter === 0) { - dropZone.classList.remove("dragover"); - } -}); - -document.addEventListener("dragover", (e) => { - e.preventDefault(); - // 保持 dragover 效果 - if (e.dataTransfer.types.includes("Files")) { - dropZone.classList.add("dragover"); - } -}); - -document.addEventListener("drop", (e) => { - e.preventDefault(); - dragCounter = 0; - dropZone.classList.remove("dragover"); - - const files = e.dataTransfer.files; - - if (files.length === 0) { - console.warn("No files dropped — likely a URL or unsupported source."); - return; - } - - for (const file of files) { - console.log("Handling dropped file (page-level):", file.name); - handleFile(file); - } -}); // ===== 全頁拖曳上傳支援結束 ===== // Extracted handleFile function for reusability in drag-and-drop and file input function handleFile(file) { + // 防重複檢查:如果這個檔案剛剛已經處理過,直接跳過 + const fileKey = getFileKey(file); + if (recentlyProcessedFiles.has(fileKey)) { + console.log("Skipping duplicate file:", file.name); + return; + } + recentlyProcessedFiles.add(fileKey); + clearRecentFiles(); + const fileList = document.querySelector("#file-list"); const removeText = getTranslation("common", "remove");