/** * upload.js — Generic file upload handler for Portal admin pages. * * Usage: * setupUpload(inputSelector, uploadType) * - inputSelector: CSS selector for the target input field * - uploadType: "icon" or "background" — determines thumbnail dimensions * * Adds a hidden file input and a visible "上传图片" button next to the target input. * After successful upload, the target input value is set to the returned URL. */ (function () { "use strict"; /** * Sets up an upload button next to the specified input field. * @param {string} inputSelector - CSS selector for the input to fill with the URL * @param {string} uploadType - "icon" or "background" */ function setupUpload(inputSelector, uploadType) { var input = document.querySelector(inputSelector); if (!input) return; // Create container for the upload button group var wrapper = document.createElement("div"); wrapper.className = "upload-btn-wrapper"; // Create the visible upload button var btn = document.createElement("button"); btn.type = "button"; btn.className = "upload-btn"; btn.textContent = "上传图片"; // Create the hidden file input var fileInput = document.createElement("input"); fileInput.type = "file"; fileInput.accept = "image/jpeg,image/png,image/gif"; fileInput.style.display = "none"; // Create status message element var status = document.createElement("span"); status.className = "upload-status"; // Insert wrapper after the input input.parentNode.insertBefore(wrapper, input.nextSibling); wrapper.appendChild(btn); wrapper.appendChild(fileInput); wrapper.appendChild(status); // Click button -> open file dialog btn.addEventListener("click", function () { fileInput.click(); }); // File selected -> upload fileInput.addEventListener("change", function () { if (fileInput.files.length === 0) return; var file = fileInput.files[0]; // Validate file size (5MB) if (file.size > 5 * 1024 * 1024) { status.textContent = "文件太大,最大允许 5MB"; status.className = "upload-status upload-error"; return; } // Validate file type var validTypes = ["image/jpeg", "image/png", "image/gif"]; if (validTypes.indexOf(file.type) === -1) { status.textContent = "不支持的文件格式"; status.className = "upload-status upload-error"; return; } // Start upload btn.disabled = true; btn.textContent = "上传中..."; status.textContent = ""; status.className = "upload-status"; var formData = new FormData(); formData.append("file", file); formData.append("type", uploadType); var xhr = new XMLHttpRequest(); xhr.open("POST", "/admin/upload", true); xhr.onload = function () { btn.disabled = false; btn.textContent = "上传图片"; if (xhr.status === 200) { try { var resp = JSON.parse(xhr.responseText); if (resp.url) { input.value = resp.url; status.textContent = "上传成功!"; status.className = "upload-status upload-success"; // If there's a preview element, update it var preview = input.parentNode.querySelector(".upload-preview"); if (preview) { preview.src = resp.url + "?thumb=1"; preview.style.display = "block"; } } else { status.textContent = resp.error || "上传失败"; status.className = "upload-status upload-error"; } } catch (e) { status.textContent = "上传失败"; status.className = "upload-status upload-error"; } } else { try { var resp = JSON.parse(xhr.responseText); status.textContent = resp.error || "上传失败"; } catch (e) { status.textContent = "上传失败 (" + xhr.status + ")"; } status.className = "upload-status upload-error"; } }; xhr.onerror = function () { btn.disabled = false; btn.textContent = "上传图片"; status.textContent = "网络错误"; status.className = "upload-status upload-error"; }; xhr.send(formData); }); } // Expose globally window.setupUpload = setupUpload; })();