优化OS上传前端
This commit is contained in:
parent
d8b6b7b689
commit
23b7fd5bf9
@ -1,7 +1,7 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "渠道应用开发部知识库",
|
||||
"version": "2.0.7",
|
||||
"version": "2.0.8",
|
||||
"description": "通过关键词快速搜索内部文档",
|
||||
"permissions": ["storage"],
|
||||
"host_permissions": [
|
||||
|
||||
@ -8,9 +8,26 @@
|
||||
.main-flex { display: flex; justify-content: center; align-items: flex-start; gap: 36px; min-height: 90vh;}
|
||||
.uploader-main { flex: none; width: 410px; margin: 60px 0 0; background: #fff; border-radius: 13px; box-shadow: 0 6px 26px #ccc4; padding: 32px 38px 28px; }
|
||||
.uploader-main h2 { text-align: center; font-size: 1.28rem; color: #1a2557; margin-bottom: 22px; }
|
||||
.input-row { margin-bottom: 14px; }
|
||||
.input-row label { font-size: 15px; color: #444; margin-right: 7px; }
|
||||
.input-row input, .input-row select { width: 70%; padding: 6px 10px; border-radius: 6px; border: 1px solid #b8c7df; font-size: 15px; }
|
||||
.input-row {
|
||||
margin-bottom: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.input-row label {
|
||||
font-size: 15px;
|
||||
color: #444;
|
||||
width: 110px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.input-row input,
|
||||
.input-row select {
|
||||
flex: 1;
|
||||
padding: 6px 10px;
|
||||
border-radius: 6px;
|
||||
border: 1px solid #b8c7df;
|
||||
font-size: 15px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#drop-area {
|
||||
width: 100%; min-height: 120px; border: 2px dashed #b7c7de; border-radius: 9px;
|
||||
background: #f5f7fa; text-align: center; line-height: 120px; font-size: 15px; color: #98a8c7; margin-bottom: 16px; cursor: pointer; transition: border-color .18s;
|
||||
@ -29,9 +46,8 @@
|
||||
/* 右侧json面板 */
|
||||
.result-panel { flex: none; width: 380px; margin: 60px 0 0; background: #fff; border-radius: 13px; box-shadow: 0 6px 26px #ccc4; padding: 28px 25px 22px;}
|
||||
.result-panel h3 { font-size: 1rem; margin-bottom: 9px; color: #1a2557;}
|
||||
/*#jsonResult { font-family: 'JetBrains Mono', 'Menlo', 'Consolas', monospace; background: #f7fafc; border-radius: 7px; padding: 13px 10px; font-size: 14px; color: #354f7d; white-space: pre; min-height: 62px; border:1px solid #e4e9f0;}*/
|
||||
.json-box {
|
||||
word-break: break-all;
|
||||
word-break: break-word;
|
||||
white-space: pre-wrap;
|
||||
overflow-x: auto;
|
||||
background: #f8fbfd;
|
||||
@ -52,6 +68,7 @@
|
||||
<div class="uploader-main">
|
||||
<h2>上传文件到 MinIO/S3</h2>
|
||||
<div class="desc">可拖拽或点击选择,支持多文件上传</div>
|
||||
|
||||
<div class="input-row">
|
||||
<label for="bucketName">Bucket 名称:</label>
|
||||
<select id="bucketName">
|
||||
@ -59,18 +76,41 @@
|
||||
<option value="kbase-priv">kbase-priv(私有)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div id="bucketTip" class="tip" style="margin-bottom:8px;"></div>
|
||||
|
||||
<div id="bucketTip" class="tip" style="margin-bottom:8px; color:red"></div>
|
||||
|
||||
<!-- 目标文件夹选择 -->
|
||||
<div class="input-row">
|
||||
<label for="folderName">目标文件夹:</label>
|
||||
<input type="text" id="folderName" placeholder="默认 default,可留空" />
|
||||
<label for="folderSelect">目标路径:</label>
|
||||
<select id="folderSelect">
|
||||
<option value="" disabled selected>请选择</option>
|
||||
<option id="defaultFolderOption" value="">yyyyMMdd</option>
|
||||
<option value="custom">自定义</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="input-row" id="customFolderRow" style="display: none;">
|
||||
<label for="folderName">自定义路径:</label>
|
||||
<input type="text" id="folderName" placeholder="请输入自定义路径" />
|
||||
</div>
|
||||
|
||||
<!-- 是否可检索 -->
|
||||
<div class="input-row">
|
||||
<label for="searchableSelect">是否可检索:</label>
|
||||
<select id="searchableSelect">
|
||||
<option value="true" selected>允许检索</option>
|
||||
<option value="false">禁止检索</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="tip" style="margin-bottom:12px;">* 如 bucket 不存在请先在 MinIO 控制台创建</div>
|
||||
|
||||
<div id="drop-area">
|
||||
<div id="drop-msg">拖拽文件到此上传,或点击选择文件</div>
|
||||
<input type="file" id="fileElem" multiple />
|
||||
</div>
|
||||
<div id="uploadList"></div>
|
||||
</div>
|
||||
|
||||
<div class="result-panel">
|
||||
<h3>上传结果 JSON
|
||||
<a href="upload-history.html" target="_blank" style="font-size: 13px; color: #2563eb; text-decoration: none; padding: 10px">查看历史上传记录 ↗</a>
|
||||
|
||||
@ -11,4 +11,5 @@
|
||||
| 2025.06.10 | V2.0.5 | Luke.Ye | 移除自动请求智能助手逻辑 |
|
||||
| 2025.06.16 | V2.0.6 | Luke.Ye | 添加上传文件到对象存储功能 |
|
||||
| 2025.06.17 | V2.0.7 | Luke.Ye | 完成上传记录展示 |
|
||||
| 2025.06.19 | V2.0.8 | Luke.Ye | 对象存储上传优化,适配后端新接口 |
|
||||
|
||||
|
||||
@ -1,8 +1,9 @@
|
||||
// uploader.js
|
||||
const dropArea = document.getElementById("drop-area");
|
||||
const fileElem = document.getElementById("fileElem");
|
||||
const uploadList = document.getElementById("uploadList");
|
||||
const folderNameInput = document.getElementById("folderName");
|
||||
const folderSelect = document.getElementById("folderSelect");
|
||||
const searchableSelect = document.getElementById("searchableSelect");
|
||||
const bucketNameInput = document.getElementById("bucketName");
|
||||
const jsonResult = document.getElementById("jsonResult");
|
||||
|
||||
@ -22,11 +23,18 @@ dropArea.addEventListener("drop", e => {
|
||||
fileElem.addEventListener("change", () => handleFiles(fileElem.files));
|
||||
|
||||
function getTargetFolder() {
|
||||
let folder = (folderNameInput.value || "").trim();
|
||||
if (!folder) folder = "default";
|
||||
folder = folder.replace(/^\/+|\/+$/g, "");
|
||||
return folder;
|
||||
const selected = folderSelect?.value || "";
|
||||
if (selected === "custom") {
|
||||
return (folderNameInput.value || "default").trim().replace(/^\/+|\/+$/g, "");
|
||||
} else {
|
||||
return selected || "default";
|
||||
}
|
||||
}
|
||||
|
||||
function getSearchable() {
|
||||
return searchableSelect?.value === "true";
|
||||
}
|
||||
|
||||
function getBucketName() {
|
||||
let bucket = (bucketNameInput.value || "").trim();
|
||||
return bucket.replace(/^\/+|\/+$/g, "");
|
||||
@ -64,28 +72,26 @@ function handleFiles(fileList) {
|
||||
}
|
||||
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);
|
||||
});
|
||||
|
||||
// 构造FormData,支持批量
|
||||
const form = new FormData();
|
||||
form.append("bucket", bucket);
|
||||
if (folder) form.append("folder", folder);
|
||||
form.append("targetFolder", folder);
|
||||
form.append("searchable", searchable);
|
||||
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留点余量
|
||||
let percent = Math.round((e.loaded / e.total) * 98);
|
||||
percent = Math.min(percent, 98);
|
||||
fileArr.forEach(f => {
|
||||
const pi = progressItems[f.name];
|
||||
@ -95,7 +101,6 @@ function handleFiles(fileList) {
|
||||
}
|
||||
};
|
||||
|
||||
// 新增处理中提示
|
||||
xhr.upload.onload = function () {
|
||||
fileArr.forEach(f => {
|
||||
const pi = progressItems[f.name];
|
||||
@ -113,7 +118,6 @@ function handleFiles(fileList) {
|
||||
pi.querySelector(".percent-label").textContent = "100%";
|
||||
});
|
||||
|
||||
// 成功
|
||||
if (xhr.status === 200) {
|
||||
try {
|
||||
const res = JSON.parse(xhr.responseText);
|
||||
@ -137,9 +141,7 @@ function handleFiles(fileList) {
|
||||
pi.querySelector(".upload-msg").className = "success upload-msg";
|
||||
});
|
||||
}
|
||||
}
|
||||
// Nginx/gateway 504/502等超时(后端可能还在处理)
|
||||
else if (xhr.status === 504 || xhr.status === 502) {
|
||||
} else if (xhr.status === 504 || xhr.status === 502) {
|
||||
jsonResult.textContent = "{}";
|
||||
fileArr.forEach(f => {
|
||||
const pi = progressItems[f.name];
|
||||
@ -147,9 +149,7 @@ function handleFiles(fileList) {
|
||||
msgSpan.innerHTML = "服务器处理中,请稍后在目标目录查看上传结果";
|
||||
msgSpan.className = "success upload-msg";
|
||||
});
|
||||
}
|
||||
// 其它错误
|
||||
else {
|
||||
} else {
|
||||
jsonResult.textContent = "{}";
|
||||
fileArr.forEach(f => {
|
||||
const pi = progressItems[f.name];
|
||||
@ -170,7 +170,6 @@ function handleFiles(fileList) {
|
||||
};
|
||||
|
||||
xhr.send(form);
|
||||
|
||||
}
|
||||
|
||||
// === 放在文件结尾,而不是 handleFiles 内部 ===
|
||||
@ -184,6 +183,24 @@ bucketNameInput.addEventListener("change", function () {
|
||||
bucketTip.style.color = "";
|
||||
}
|
||||
});
|
||||
// 页面加载时自动触发一次
|
||||
bucketNameInput.dispatchEvent(new Event("change"));
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
const defaultFolderPath = new Date().toISOString().slice(0, 10).replace(/-/g, "");
|
||||
const folderSelect = document.getElementById("folderSelect");
|
||||
const folderNameInput = document.getElementById("folderName");
|
||||
const customFolderRow = document.getElementById("customFolderRow");
|
||||
|
||||
const defaultOption = document.getElementById("defaultFolderOption");
|
||||
defaultOption.value = defaultFolderPath;
|
||||
defaultOption.textContent = defaultFolderPath;
|
||||
folderSelect.value = defaultFolderPath;
|
||||
|
||||
folderSelect.addEventListener("change", function () {
|
||||
if (this.value === "custom") {
|
||||
customFolderRow.style.display = "block";
|
||||
} else {
|
||||
customFolderRow.style.display = "none";
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user