diff --git a/manifest.json b/manifest.json
index 328ad89..ec102af 100644
--- a/manifest.json
+++ b/manifest.json
@@ -1,7 +1,7 @@
{
"manifest_version": 3,
"name": "渠道应用开发部知识库",
- "version": "2.0.5",
+ "version": "2.0.6",
"description": "通过关键词快速搜索内部文档",
"permissions": ["storage"],
"host_permissions": [
diff --git a/pages/popup.html b/pages/popup.html
index 040c4aa..76992d6 100644
--- a/pages/popup.html
+++ b/pages/popup.html
@@ -19,6 +19,7 @@
+
上传文件到 MinIO/S3
+
可拖拽或点击选择,支持多文件上传
+
+
+
+
+
+
+
+
+
* 如 bucket 不存在请先在 MinIO 控制台创建
+
+
+
+
+
+
diff --git a/readme.md b/readme.md
index 164c963..d062c17 100644
--- a/readme.md
+++ b/readme.md
@@ -9,4 +9,5 @@
| 2025.06.06 | V2.0.3 | Luke.Ye | 添加跳转页面权限校验 |
| 2025.06.09 | V2.0.4 | Luke.Ye | 优化es搜索展示页面 |
| 2025.06.10 | V2.0.5 | Luke.Ye | 移除自动请求智能助手逻辑 |
+| 2025.06.16 | V2.0.6 | Luke.Ye | 添加上传文件到对象存储功能 |
diff --git a/scripts/popup.js b/scripts/popup.js
index eaf80bc..35852a3 100644
--- a/scripts/popup.js
+++ b/scripts/popup.js
@@ -1,3 +1,4 @@
+// popup.js
document.addEventListener("DOMContentLoaded", async () => {
const panel = document.getElementById("draggablePanel");
const header = document.querySelector(".header");
@@ -45,6 +46,7 @@ document.addEventListener("DOMContentLoaded", async () => {
const userDropdown = document.getElementById("userDropdown");
const openTabBtn = document.getElementById("openTabBtn");
const settingsBtn = document.getElementById("settingsBtn");
+ const openUploaderMenu = document.getElementById("openUploaderMenu");
const tabEs = document.getElementById("tabEs");
const tabAi = document.getElementById("tabAi");
const tabContentEs = document.getElementById("tabContentEs");
@@ -263,6 +265,11 @@ document.addEventListener("DOMContentLoaded", async () => {
settingsBtn?.addEventListener("click", () => {
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) => {
if (!userDropdown.contains(e.target) && e.target !== userAvatar) {
@@ -299,3 +306,15 @@ document.addEventListener("DOMContentLoaded", async () => {
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");
+}
diff --git a/scripts/uploader.js b/scripts/uploader.js
new file mode 100644
index 0000000..e720ed4
--- /dev/null
+++ b/scripts/uploader.js
@@ -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 = `
+