diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..f8f9e51 Binary files /dev/null and b/.DS_Store differ diff --git a/manifest.json b/manifest.json index aa80ec3..63d9417 100644 --- a/manifest.json +++ b/manifest.json @@ -1,9 +1,9 @@ { "manifest_version": 3, "name": "渠道应用开发部知识库", - "version": "1.0.1", + "version": "1.0.2", "description": "通过关键词快速搜索内部文档", - "permissions": [], + "permissions": ["storage"], "host_permissions": [ "http://app.wisdompulse.cn/*", "http://share.wisdompulse.cn/*" @@ -27,4 +27,4 @@ "128": "icon.png" } } -} +} \ No newline at end of file diff --git a/popup.html b/popup.html index c18a1b8..cc6b129 100644 --- a/popup.html +++ b/popup.html @@ -1,27 +1,30 @@ - - 渠道应用开发部知识库 - + + 渠道应用开发部知识库 + -
- +
+
-

渠道应用开发部知识库

- 跳转OA +

渠道应用开发部知识库

+ 跳转OA
-
+
-
+
- -
- + + + +
+ + - + \ No newline at end of file diff --git a/popup.js b/popup.js index c76a61b..cd2cc60 100644 --- a/popup.js +++ b/popup.js @@ -1,120 +1,155 @@ -const searchBtn = document.getElementById("searchBtn"); -const input = document.getElementById("searchInput"); -const resultBox = document.getElementById("results"); +document.addEventListener("DOMContentLoaded", () => { + const input = document.getElementById("searchInput"); + const searchBtn = document.getElementById("searchBtn"); + const resultBox = document.getElementById("results"); + const historyBox = document.getElementById("historyTags"); -let currentPage = 1; -let totalPages = 1; -let lastKeywords = []; + let currentPage = 1; + let totalPages = 1; + let lastKeywords = []; -function showLoading() { + function log(...args) { + console.log("[v1.0.2]", ...args); + } + + function showLoading() { resultBox.innerHTML = "
  • 加载中...
  • "; -} + } -function renderPagination() { + function renderPagination() { const pagination = document.createElement("div"); pagination.className = "pagination"; if (currentPage > 1) { - const prevBtn = document.createElement("button"); - prevBtn.textContent = "上一页"; - prevBtn.onclick = () => fetchResults(lastKeywords, currentPage - 1); - pagination.appendChild(prevBtn); + const prevBtn = document.createElement("button"); + prevBtn.textContent = "上一页"; + prevBtn.onclick = () => fetchResults(lastKeywords, currentPage - 1); + pagination.appendChild(prevBtn); } if (currentPage < totalPages) { - const nextBtn = document.createElement("button"); - nextBtn.textContent = "下一页"; - nextBtn.onclick = () => fetchResults(lastKeywords, currentPage + 1); - pagination.appendChild(nextBtn); + const nextBtn = document.createElement("button"); + nextBtn.textContent = "下一页"; + nextBtn.onclick = () => fetchResults(lastKeywords, currentPage + 1); + pagination.appendChild(nextBtn); } resultBox.appendChild(pagination); -} + } -async function fetchResults(keywords, page) { + function updateHistory(keyword) { + if (!chrome?.storage?.local) { + log("chrome.storage.local 不可用,跳过历史记录"); + return; + } + chrome.storage.local.get(["searchHistory"], (res) => { + let history = res.searchHistory || []; + history = [keyword, ...history.filter(item => item !== keyword)]; + if (history.length > 5) history = history.slice(0, 5); + chrome.storage.local.set({ searchHistory: history }); + }); + } + + function renderHistoryTags() { + if (!chrome?.storage?.local) return; + chrome.storage.local.get(["searchHistory"], (res) => { + const history = res.searchHistory || []; + historyBox.innerHTML = ""; + if (history.length === 0) { + historyBox.classList.add("hidden"); + return; + } + + history.forEach(tagText => { + const tag = document.createElement("span"); + tag.className = "tag"; + tag.textContent = tagText; + tag.onclick = () => { + input.value = tagText; + triggerSearch(); + }; + historyBox.appendChild(tag); + }); + + historyBox.classList.remove("hidden"); + }); + } + + async function fetchResults(keywords, page) { currentPage = page; lastKeywords = keywords; const keywordGroups = keywords.map(k => [k]); const requestBody = { - keywordGroups, - page: currentPage, - size: 10 + keywordGroups, + page: currentPage, + size: 10 }; - console.log("[INFO] 请求地址: http://app.wisdompulse.cn/search"); - console.log("[INFO] 请求方法: POST"); - console.log("[INFO] 请求体:", JSON.stringify(requestBody, null, 2)); - + log("触发搜索:", requestBody); showLoading(); try { - const response = await fetch("http://app.wisdompulse.cn/search", { - method: "POST", - headers: { - "Content-Type": "application/json" - }, - body: JSON.stringify(requestBody) - }); + const response = await fetch("http://app.wisdompulse.cn/search", { + method: "POST", + headers: { + "Content-Type": "application/json" + }, + body: JSON.stringify(requestBody) + }); - console.log("[INFO] 响应状态:", response.status, response.statusText); - const data = await response.json(); - console.log("[INFO] 响应体:", data); + const data = await response.json(); + resultBox.innerHTML = ""; - resultBox.innerHTML = ""; + if (!data.results || data.results.length === 0) { + resultBox.innerHTML = "
  • 未找到相关文档
  • "; + return; + } - if (!data.results || data.results.length === 0) { - console.log("[INFO] 未返回结果数据"); - resultBox.innerHTML = "
  • 未找到相关文档
  • "; - return; - } + totalPages = Math.ceil(data.total / data.size); - totalPages = Math.ceil(data.total / data.size); + data.results.forEach(doc => { + const li = document.createElement("li"); + const cleanPath = doc.filepath.replace(/^import-data\//, "").replace(/\.md$/, ".html"); + const link = document.createElement("a"); + link.href = `http://share.wisdompulse.cn/public/${cleanPath}`; + link.target = "_blank"; + link.textContent = doc.filename; - data.results.forEach(doc => { - const li = document.createElement("li"); + const snippet = document.createElement("div"); + snippet.className = "summary"; + snippet.innerHTML = doc.summary?.slice(0, 300) + "..."; - const cleanPath = doc.filepath.replace(/^import-data\//, "").replace(/\.md$/, ".html"); - const link = document.createElement("a"); - link.href = `http://share.wisdompulse.cn/public/${cleanPath}`; - link.target = "_blank"; - link.textContent = doc.filename; + li.appendChild(link); + li.appendChild(snippet); + resultBox.appendChild(li); + }); - const snippet = document.createElement("div"); - snippet.className = "summary"; - snippet.innerHTML = doc.summary?.slice(0, 300) + "..."; - - li.appendChild(link); - li.appendChild(snippet); - resultBox.appendChild(li); - }); - - renderPagination(); + renderPagination(); } catch (err) { - console.error("[ERROR] 搜索失败:", err); - resultBox.innerHTML = "
  • 搜索失败,请检查网络或服务状态。
  • "; + console.error("[ERROR] 搜索失败:", err); + resultBox.innerHTML = "
  • 搜索失败,请检查网络或服务状态。
  • "; } -} + } -function triggerSearch() { + function triggerSearch() { const inputValue = input.value.trim(); - console.log("[INFO] 用户输入关键词:", inputValue); - - if (!inputValue) { - console.warn("[WARN] 输入为空"); - return; - } - + if (!inputValue) return; const keywords = inputValue.split(/\s+/).filter(Boolean); + updateHistory(inputValue); fetchResults(keywords, 1); -} + } -searchBtn.addEventListener("click", triggerSearch); + searchBtn.addEventListener("click", triggerSearch); + input.addEventListener("keydown", e => { + if (e.key === "Enter") triggerSearch(); + }); -// 支持按回车键直接搜索 -input.addEventListener("keydown", e => { - if (e.key === "Enter") { - triggerSearch(); - } -}); + input.addEventListener("focus", renderHistoryTags); + input.addEventListener("blur", () => { + setTimeout(() => historyBox.classList.add("hidden"), 200); + }); + + log("插件初始化完成"); +}); \ No newline at end of file diff --git a/styles.css b/styles.css index 8664889..4e70952 100644 --- a/styles.css +++ b/styles.css @@ -1,125 +1,149 @@ body { - font-family: "Microsoft YaHei", sans-serif; - width: 600px; - padding: 20px; - background-color: #fefefe; + font-family: "Microsoft YaHei", sans-serif; + width: 600px; + padding: 20px; + background-color: #fefefe; } .header { - display: flex; - align-items: center; - justify-content: center; - margin-bottom: 15px; + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 15px; } .logo { - width: 32px; - height: 32px; - margin-right: 10px; + width: 32px; + height: 32px; + margin-right: 10px; } .title-box { - display: flex; - align-items: center; - gap: 12px; + display: flex; + align-items: center; + gap: 12px; } h1 { - font-size: 18px; - color: #2c3e50; - margin: 0; + font-size: 18px; + color: #2c3e50; + margin: 0; } .oa-link { - font-size: 13px; - text-decoration: none; - color: #007bff; - background-color: #f2f2f2; - padding: 4px 8px; - border-radius: 4px; + font-size: 13px; + text-decoration: none; + color: #007bff; + background-color: #f2f2f2; + padding: 4px 8px; + border-radius: 4px; } .oa-link:hover { - background-color: #e0e0e0; + background-color: #e0e0e0; } .container { - display: flex; - flex-direction: column; + display: flex; + flex-direction: column; } .search-bar { - display: flex; - gap: 10px; - margin-bottom: 15px; + display: flex; + gap: 10px; + margin-bottom: 15px; } .search-bar input { - flex: 1; - padding: 8px; - font-size: 14px; - border: 1px solid #ccc; - border-radius: 4px; + flex: 1; + padding: 8px; + font-size: 14px; + border: 1px solid #ccc; + border-radius: 4px; } .search-bar button { - padding: 8px 16px; - font-size: 14px; - background-color: #007bff; - color: white; - border: none; - border-radius: 4px; - cursor: pointer; + padding: 8px 16px; + font-size: 14px; + background-color: #007bff; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; } .search-bar button:hover { - background-color: #0056b3; + background-color: #0056b3; +} + +.tag-history { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-bottom: 15px; +} + +.tag-history .tag { + background-color: #f0f0f0; + color: #333; + padding: 4px 10px; + border-radius: 12px; + font-size: 12px; + cursor: pointer; +} + +.tag-history .tag:hover { + background-color: #dcdcdc; +} + +.hidden { + display: none; } #results { - list-style: none; - padding: 0; + list-style: none; + padding: 0; } #results li { - margin-bottom: 14px; - border-bottom: 1px solid #ddd; - padding-bottom: 10px; + margin-bottom: 14px; + border-bottom: 1px solid #ddd; + padding-bottom: 10px; } #results a { - font-weight: bold; - color: #007bff; - text-decoration: none; - font-size: 15px; + font-weight: bold; + color: #007bff; + text-decoration: none; + font-size: 15px; } #results a:hover { - text-decoration: underline; + text-decoration: underline; } #results .summary { - font-size: 13px; - color: #444; - margin-top: 4px; + font-size: 13px; + color: #444; + margin-top: 4px; } .pagination { - margin-top: 15px; - display: flex; - justify-content: center; - gap: 10px; + margin-top: 15px; + display: flex; + justify-content: center; + gap: 10px; } .pagination button { - padding: 6px 12px; - font-size: 13px; - background-color: #eee; - border: 1px solid #ccc; - border-radius: 3px; - cursor: pointer; + padding: 6px 12px; + font-size: 13px; + background-color: #eee; + border: 1px solid #ccc; + border-radius: 3px; + cursor: pointer; } .pagination button:hover { - background-color: #ddd; -} + background-color: #ddd; +} \ No newline at end of file