2025-07-11 00:47:28 +08:00

213 lines
7.8 KiB
JavaScript

// uploader.js
const dropArea = document.getElementById("drop-area");
const fileElem = document.getElementById("fileElem");
const uploadList = document.getElementById("uploadList");
const folderNameInput = document.getElementById("folderName");
const editFolderBtn = document.getElementById("editFolderBtn");
const searchableSelect = document.getElementById("searchableSelect");
const bucketNameInput = document.getElementById("bucketName");
const jsonResult = document.getElementById("jsonResult");
const API_UPLOAD = "http://app.wisdompulse.cn/api/v1/doc/upload-files";
// =========== 目标路径输入可编辑/不可编辑切换 ==============
function getDefaultFolderPath() {
const now = new Date();
const yyyy = now.getFullYear();
const mm = (now.getMonth() + 1).toString().padStart(2, "0");
const dd = now.getDate().toString().padStart(2, "0");
return `Year-${yyyy}/${yyyy}${mm}${dd}`;
}
let isEditing = false;
folderNameInput.value = getDefaultFolderPath();
editFolderBtn.onclick = function () {
if (!isEditing) {
folderNameInput.readOnly = false;
folderNameInput.style.background = "#fff";
folderNameInput.focus();
editFolderBtn.textContent = "完成";
isEditing = true;
} else {
folderNameInput.readOnly = true;
folderNameInput.style.background = "#f7fafb";
editFolderBtn.textContent = "修改";
isEditing = false;
}
};
folderNameInput.addEventListener("blur", function () {
if (isEditing) {
folderNameInput.readOnly = true;
folderNameInput.style.background = "#f7fafb";
editFolderBtn.textContent = "修改";
isEditing = false;
}
});
// =========== 拖拽、选择文件 ==============
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() {
return (folderNameInput.value || getDefaultFolderPath()).trim().replace(/^\/+|\/+$/g, "");
}
function getSearchable() {
return searchableSelect?.value === "true";
}
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);
}
// =========== 主上传逻辑 ===========
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 searchable = getSearchable();
const fileArr = Array.from(fileList);
const progressItems = {};
fileArr.forEach(f => {
progressItems[f.name] = createProgressItem(f.name);
});
const form = new FormData();
form.append("bucket", bucket);
form.append("targetFolder", folder);
form.append("searchable", searchable);
fileArr.forEach(f => form.append("files", f, f.name));
const xhr = new XMLHttpRequest();
xhr.open("POST", API_UPLOAD);
xhr.upload.onprogress = function (e) {
if (e.lengthComputable) {
let percent = Math.round((e.loaded / e.total) * 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";
});
}
} 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);
}
// ======== Bucket切换提示 ========
const bucketTip = document.getElementById("bucketTip");
bucketNameInput.addEventListener("change", function () {
if (bucketNameInput.value === "kbase-share-priv") {
bucketTip.innerHTML = "私有 bucket 中,文件的可访问链接有效期为 <b>7天</b>";
bucketTip.style.color = "#ec0924";
} else {
bucketTip.innerHTML = "";
bucketTip.style.color = "";
}
});
bucketNameInput.dispatchEvent(new Event("change"));