2025-06-16 14:46:10 +08:00

190 lines
6.8 KiB
JavaScript
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.

// uploader.js
const dropArea = document.getElementById("drop-area");
const fileElem = document.getElementById("fileElem");
const uploadList = document.getElementById("uploadList");
const folderNameInput = document.getElementById("folderName");
const bucketNameInput = document.getElementById("bucketName");
const jsonResult = document.getElementById("jsonResult");
const API_UPLOAD = "http://app.wisdompulse.cn/api/v1/doc/upload-files";
dropArea.addEventListener("click", () => fileElem.click());
dropArea.addEventListener("dragover", e => {
e.preventDefault(); dropArea.classList.add("dragover");
});
dropArea.addEventListener("dragleave", e => {
e.preventDefault(); dropArea.classList.remove("dragover");
});
dropArea.addEventListener("drop", e => {
e.preventDefault(); dropArea.classList.remove("dragover");
handleFiles(e.dataTransfer.files);
});
fileElem.addEventListener("change", () => handleFiles(fileElem.files));
function getTargetFolder() {
let folder = (folderNameInput.value || "").trim();
if (!folder) folder = "default";
folder = folder.replace(/^\/+|\/+$/g, "");
return folder;
}
function getBucketName() {
let bucket = (bucketNameInput.value || "").trim();
return bucket.replace(/^\/+|\/+$/g, "");
}
// 工具:为单个文件显示进度
function createProgressItem(filename) {
const wrapper = document.createElement("div");
wrapper.className = "progress-item";
wrapper.innerHTML = `
<span class="file-label">${filename}</span>
<progress value="0" max="100" style="width:60%;margin:0 10px;"></progress>
<span class="percent-label">0%</span>
<span class="upload-msg"></span>
`;
uploadList.appendChild(wrapper);
return wrapper;
}
function showMsg(msg, ok) {
const div = document.createElement("div");
div.className = ok ? "success" : "error";
div.innerHTML = msg;
uploadList.appendChild(div);
}
// 批量上传单次FormData统一进度条管理JSON右侧展示
function handleFiles(fileList) {
uploadList.innerHTML = "";
jsonResult.textContent = "{}";
const bucket = getBucketName();
if (!bucket) {
showMsg("请输入 Bucket 名称", false);
return;
}
if (!fileList || !fileList.length) return;
const folder = getTargetFolder();
// 显示所有文件的进度条
const fileArr = Array.from(fileList);
const progressItems = {};
fileArr.forEach(f => {
progressItems[f.name] = createProgressItem(f.name);
});
// 构造FormData支持批量
const form = new FormData();
form.append("bucket", bucket);
if (folder) form.append("folder", folder);
fileArr.forEach(f => form.append("files", f, f.name));
// 单一xhr汇总进度
const xhr = new XMLHttpRequest();
xhr.open("POST", API_UPLOAD);
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
// 进度只到99%收到响应才到100%
let percent = Math.round((e.loaded / e.total) * 98); // 98留点余量
percent = Math.min(percent, 98);
fileArr.forEach(f => {
const pi = progressItems[f.name];
pi.querySelector("progress").value = percent;
pi.querySelector(".percent-label").textContent = percent + "%";
});
}
};
// 新增处理中提示
xhr.upload.onload = function () {
fileArr.forEach(f => {
const pi = progressItems[f.name];
pi.querySelector("progress").value = 99;
pi.querySelector(".percent-label").textContent = "99%";
const msgSpan = pi.querySelector(".upload-msg");
msgSpan.innerHTML = "<span style='color:#888;'>服务器处理中...</span>";
});
};
xhr.onload = function () {
fileArr.forEach(f => {
const pi = progressItems[f.name];
pi.querySelector("progress").value = 100;
pi.querySelector(".percent-label").textContent = "100%";
});
// 成功
if (xhr.status === 200) {
try {
const res = JSON.parse(xhr.responseText);
jsonResult.textContent = JSON.stringify(res.files, null, 2);
fileArr.forEach(f => {
const pi = progressItems[f.name];
const msgSpan = pi.querySelector(".upload-msg");
if (res.files && res.files[f.name]) {
msgSpan.innerHTML = `<a href="${res.files[f.name]}" target="_blank">${f.name}</a> 上传成功`;
msgSpan.className = "success upload-msg";
} else {
msgSpan.innerHTML = "上传成功";
msgSpan.className = "success upload-msg";
}
});
} catch (e) {
jsonResult.textContent = "{}";
fileArr.forEach(f => {
const pi = progressItems[f.name];
pi.querySelector(".upload-msg").innerHTML = "上传成功";
pi.querySelector(".upload-msg").className = "success upload-msg";
});
}
}
// Nginx/gateway 504/502等超时后端可能还在处理
else if (xhr.status === 504 || xhr.status === 502) {
jsonResult.textContent = "{}";
fileArr.forEach(f => {
const pi = progressItems[f.name];
const msgSpan = pi.querySelector(".upload-msg");
msgSpan.innerHTML = "服务器处理中,请稍后在目标目录查看上传结果";
msgSpan.className = "success upload-msg";
});
}
// 其它错误
else {
jsonResult.textContent = "{}";
fileArr.forEach(f => {
const pi = progressItems[f.name];
const msgSpan = pi.querySelector(".upload-msg");
msgSpan.innerHTML = "上传失败 " + xhr.status;
msgSpan.className = "error upload-msg";
});
}
};
xhr.onerror = function () {
fileArr.forEach(f => {
const pi = progressItems[f.name];
pi.querySelector(".upload-msg").innerHTML = "上传异常";
pi.querySelector(".upload-msg").className = "error upload-msg";
});
jsonResult.textContent = "{}";
};
xhr.send(form);
}
// === 放在文件结尾,而不是 handleFiles 内部 ===
const bucketTip = document.getElementById("bucketTip");
bucketNameInput.addEventListener("change", function () {
if (bucketNameInput.value === "kbase-priv") {
bucketTip.innerHTML = "私有 bucket 中,文件的可访问链接有效期为 <b>7天</b>";
bucketTip.style.color = "#ec0924";
} else {
bucketTip.innerHTML = "";
bucketTip.style.color = "";
}
});
// 页面加载时自动触发一次
bucketNameInput.dispatchEvent(new Event("change"));