ä¿添加对è上传文件入å口
This commit is contained in:
parent
1b2debb4ea
commit
c98cf90704
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"manifest_version": 3,
|
"manifest_version": 3,
|
||||||
"name": "渠道应用开发部知识库",
|
"name": "渠道应用开发部知识库",
|
||||||
"version": "2.0.5",
|
"version": "2.0.6",
|
||||||
"description": "通过关键词快速搜索内部文档",
|
"description": "通过关键词快速搜索内部文档",
|
||||||
"permissions": ["storage"],
|
"permissions": ["storage"],
|
||||||
"host_permissions": [
|
"host_permissions": [
|
||||||
|
|||||||
@ -19,6 +19,7 @@
|
|||||||
<div class="user-avatar" id="userAvatar">👤</div>
|
<div class="user-avatar" id="userAvatar">👤</div>
|
||||||
<div class="user-dropdown hidden" id="userDropdown">
|
<div class="user-dropdown hidden" id="userDropdown">
|
||||||
<div id="userName">未登录</div>
|
<div id="userName">未登录</div>
|
||||||
|
<div class="dropdown-item" id="openUploaderMenu">上传文件</div>
|
||||||
<div id="settingsBtn" class="logout-option">设置</div>
|
<div id="settingsBtn" class="logout-option">设置</div>
|
||||||
<div id="logoutBtn" class="logout-option">退出登录</div>
|
<div id="logoutBtn" class="logout-option">退出登录</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
55
pages/uploader.html
Normal file
55
pages/uploader.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>上传文件到 MinIO/S3</title>
|
||||||
|
<style>
|
||||||
|
body { font-family: system-ui, sans-serif; background: #f7f9fb; margin: 0; }
|
||||||
|
.uploader-main { max-width: 480px; margin: 60px auto 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; }
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
#drop-area.dragover { border-color: #3b82f6; background: #f0f6ff; color: #234fa2; }
|
||||||
|
#uploadList { font-size: 13px; color: #888; margin-top: 7px; text-align: left;}
|
||||||
|
.desc { color: #99a; font-size: 13px; margin-bottom: 7px; }
|
||||||
|
#fileElem { display: none; }
|
||||||
|
.success { color: #2d974b; }
|
||||||
|
.error { color: #e64e4e; }
|
||||||
|
.tip { font-size:12px;color:#998; }
|
||||||
|
.progress-item { font-size: 14px; margin-bottom: 10px; color: #444; }
|
||||||
|
.file-label { display: inline-block; width: 110px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; vertical-align: middle; }
|
||||||
|
.percent-label { font-size: 12px; color: #888; }
|
||||||
|
.upload-msg { margin-left: 8px; }
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="uploader-main">
|
||||||
|
<h2>上传文件到 MinIO/S3</h2>
|
||||||
|
<div class="desc">可拖拽或点击选择,支持多文件上传</div>
|
||||||
|
<div class="input-row">
|
||||||
|
<label for="bucketName">Bucket 名称:</label>
|
||||||
|
<select id="bucketName">
|
||||||
|
<option value="kbase">kbase(公开)</option>
|
||||||
|
<option value="kbase-priv">kbase-priv(私有)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="input-row">
|
||||||
|
<label for="folderName">目标文件夹:</label>
|
||||||
|
<input type="text" id="folderName" placeholder="默认 default,可留空" />
|
||||||
|
</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>
|
||||||
|
<script src="../scripts/uploader.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -9,4 +9,5 @@
|
|||||||
| 2025.06.06 | V2.0.3 | Luke.Ye | 添加跳转页面权限校验 |
|
| 2025.06.06 | V2.0.3 | Luke.Ye | 添加跳转页面权限校验 |
|
||||||
| 2025.06.09 | V2.0.4 | Luke.Ye | 优化es搜索展示页面 |
|
| 2025.06.09 | V2.0.4 | Luke.Ye | 优化es搜索展示页面 |
|
||||||
| 2025.06.10 | V2.0.5 | Luke.Ye | 移除自动请求智能助手逻辑 |
|
| 2025.06.10 | V2.0.5 | Luke.Ye | 移除自动请求智能助手逻辑 |
|
||||||
|
| 2025.06.16 | V2.0.6 | Luke.Ye | 添加上传文件到对象存储功能 |
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
// popup.js
|
||||||
document.addEventListener("DOMContentLoaded", async () => {
|
document.addEventListener("DOMContentLoaded", async () => {
|
||||||
const panel = document.getElementById("draggablePanel");
|
const panel = document.getElementById("draggablePanel");
|
||||||
const header = document.querySelector(".header");
|
const header = document.querySelector(".header");
|
||||||
@ -45,6 +46,7 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
const userDropdown = document.getElementById("userDropdown");
|
const userDropdown = document.getElementById("userDropdown");
|
||||||
const openTabBtn = document.getElementById("openTabBtn");
|
const openTabBtn = document.getElementById("openTabBtn");
|
||||||
const settingsBtn = document.getElementById("settingsBtn");
|
const settingsBtn = document.getElementById("settingsBtn");
|
||||||
|
const openUploaderMenu = document.getElementById("openUploaderMenu");
|
||||||
const tabEs = document.getElementById("tabEs");
|
const tabEs = document.getElementById("tabEs");
|
||||||
const tabAi = document.getElementById("tabAi");
|
const tabAi = document.getElementById("tabAi");
|
||||||
const tabContentEs = document.getElementById("tabContentEs");
|
const tabContentEs = document.getElementById("tabContentEs");
|
||||||
@ -263,6 +265,11 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
settingsBtn?.addEventListener("click", () => {
|
settingsBtn?.addEventListener("click", () => {
|
||||||
chrome.tabs.create({ url: chrome.runtime.getURL("pages/settings.html") });
|
chrome.tabs.create({ url: chrome.runtime.getURL("pages/settings.html") });
|
||||||
});
|
});
|
||||||
|
openUploaderMenu?.addEventListener("click", () => {
|
||||||
|
const uploaderUrl = chrome.runtime ? chrome.runtime.getURL("pages/uploader.html") : "pages/uploader.html";
|
||||||
|
window.open(uploaderUrl, "_blank");
|
||||||
|
userDropdown.classList.add("hidden");
|
||||||
|
});
|
||||||
|
|
||||||
window.addEventListener("click", (e) => {
|
window.addEventListener("click", (e) => {
|
||||||
if (!userDropdown.contains(e.target) && e.target !== userAvatar) {
|
if (!userDropdown.contains(e.target) && e.target !== userAvatar) {
|
||||||
@ -299,3 +306,15 @@ document.addEventListener("DOMContentLoaded", async () => {
|
|||||||
|
|
||||||
renderHistoryTags();
|
renderHistoryTags();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 时间戳格式化辅助
|
||||||
|
function formatLocalTime(ts) {
|
||||||
|
if (!ts) return "";
|
||||||
|
const date = new Date(Number(ts));
|
||||||
|
if (isNaN(date.getTime())) return "";
|
||||||
|
return date.getFullYear() + "-" +
|
||||||
|
String(date.getMonth() + 1).padStart(2, "0") + "-" +
|
||||||
|
String(date.getDate()).padStart(2, "0") + " " +
|
||||||
|
String(date.getHours()).padStart(2, "0") + ":" +
|
||||||
|
String(date.getMinutes()).padStart(2, "0");
|
||||||
|
}
|
||||||
|
|||||||
129
scripts/uploader.js
Normal file
129
scripts/uploader.js
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
// 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 API_UPLOAD = "http://localhost:18081/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;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function handleFiles(files) {
|
||||||
|
uploadList.innerHTML = "";
|
||||||
|
const bucket = getBucketName();
|
||||||
|
if (!bucket) {
|
||||||
|
showMsg("请输入 Bucket 名称", false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!files || !files.length) return;
|
||||||
|
const folder = getTargetFolder();
|
||||||
|
|
||||||
|
// 多文件逐个上传,每个单独显示进度
|
||||||
|
for (const file of files) {
|
||||||
|
await uploadSingleFile(file, bucket, folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showMsg(msg, ok) {
|
||||||
|
const div = document.createElement("div");
|
||||||
|
div.className = ok ? "success" : "error";
|
||||||
|
div.innerHTML = msg;
|
||||||
|
uploadList.appendChild(div);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 单文件上传,带进度条
|
||||||
|
function uploadSingleFile(file, bucket, folder) {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
const form = new FormData();
|
||||||
|
form.append("bucket", bucket);
|
||||||
|
form.append("files", file, file.name);
|
||||||
|
|
||||||
|
const progressItem = createProgressItem(file.name);
|
||||||
|
const progressBar = progressItem.querySelector("progress");
|
||||||
|
const percentLabel = progressItem.querySelector(".percent-label");
|
||||||
|
const msgSpan = progressItem.querySelector(".upload-msg");
|
||||||
|
|
||||||
|
const xhr = new XMLHttpRequest();
|
||||||
|
xhr.open("POST", API_UPLOAD);
|
||||||
|
|
||||||
|
xhr.upload.onprogress = function (e) {
|
||||||
|
if (e.lengthComputable) {
|
||||||
|
const percent = Math.round((e.loaded / e.total) * 100);
|
||||||
|
progressBar.value = percent;
|
||||||
|
percentLabel.textContent = percent + "%";
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onload = function () {
|
||||||
|
progressBar.value = 100;
|
||||||
|
percentLabel.textContent = "100%";
|
||||||
|
if (xhr.status === 200) {
|
||||||
|
try {
|
||||||
|
const res = JSON.parse(xhr.responseText);
|
||||||
|
// 查找本文件上传结果
|
||||||
|
let link = "";
|
||||||
|
if (res.files && res.files[file.name]) {
|
||||||
|
link = `<a href="${res.files[file.name]}" target="_blank">${file.name}</a> 上传成功`;
|
||||||
|
msgSpan.innerHTML = link;
|
||||||
|
msgSpan.className = "success";
|
||||||
|
} else {
|
||||||
|
msgSpan.innerHTML = "上传成功";
|
||||||
|
msgSpan.className = "success";
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
msgSpan.innerHTML = "上传成功";
|
||||||
|
msgSpan.className = "success";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
msgSpan.innerHTML = "上传失败 " + xhr.status;
|
||||||
|
msgSpan.className = "error";
|
||||||
|
}
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.onerror = function () {
|
||||||
|
msgSpan.innerHTML = "上传异常";
|
||||||
|
msgSpan.className = "error";
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
|
||||||
|
xhr.send(form);
|
||||||
|
});
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user