236 lines
7.0 KiB
JavaScript
236 lines
7.0 KiB
JavaScript
document.addEventListener("DOMContentLoaded", async () => {
|
||
const input = document.getElementById("searchInput");
|
||
const searchBtn = document.getElementById("searchBtn");
|
||
const clearHistoryBtn = document.getElementById("clearHistoryBtn");
|
||
const resultBox = document.getElementById("results");
|
||
const historyBox = document.getElementById("historyTags");
|
||
const historyWrapper = document.getElementById("historyWrapper");
|
||
|
||
const userDropdown = document.getElementById("userDropdown");
|
||
const logoutBtn = document.getElementById("logoutBtn");
|
||
const userNameLabel = document.getElementById("userName");
|
||
const userAvatar = document.getElementById("userAvatar");
|
||
|
||
let token = null;
|
||
let currentPage = 1;
|
||
let totalPages = 1;
|
||
let lastKeywords = [];
|
||
|
||
const TOKEN_EXPIRE_MS = 24 * 60 * 60 * 1000;
|
||
|
||
function log(...args) {
|
||
const version = chrome?.runtime?.getManifest?.().version || "dev";
|
||
console.log(`[v${version}]`, ...args);
|
||
}
|
||
|
||
async function loadToken() {
|
||
return new Promise((resolve) => {
|
||
chrome.storage.local.get(["token", "loginAt", "username"], (res) => {
|
||
log("加载本地存储 token:", res);
|
||
const now = Date.now();
|
||
if (!res.token || !res.loginAt || (now - res.loginAt > TOKEN_EXPIRE_MS)) {
|
||
log("token 不存在或已过期");
|
||
resolve(null);
|
||
} else {
|
||
log("token 加载成功");
|
||
resolve({
|
||
token: res.token,
|
||
username: res.username || "用户"
|
||
});
|
||
}
|
||
});
|
||
});
|
||
}
|
||
|
||
function handleLogout() {
|
||
chrome.storage.local.remove(["token", "loginAt", "username"], () => {
|
||
window.location.href = chrome.runtime.getURL("pages/login.html");
|
||
});
|
||
}
|
||
|
||
|
||
function showLoading() {
|
||
resultBox.innerHTML = "<li>加载中...</li>";
|
||
}
|
||
|
||
function clearResults() {
|
||
resultBox.innerHTML = "";
|
||
historyWrapper.classList.add("hidden");
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
if (currentPage < totalPages) {
|
||
const nextBtn = document.createElement("button");
|
||
nextBtn.textContent = "下一页";
|
||
nextBtn.onclick = () => fetchResults(lastKeywords, currentPage + 1);
|
||
pagination.appendChild(nextBtn);
|
||
}
|
||
|
||
resultBox.appendChild(pagination);
|
||
}
|
||
|
||
function updateHistory(keyword) {
|
||
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() {
|
||
chrome.storage.local.get(["searchHistory"], (res) => {
|
||
const history = res.searchHistory || [];
|
||
historyBox.innerHTML = "";
|
||
if (history.length === 0) {
|
||
historyWrapper.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);
|
||
});
|
||
|
||
historyWrapper.classList.remove("hidden");
|
||
});
|
||
}
|
||
|
||
async function fetchResults(keywords, page) {
|
||
log("执行搜索:", keywords, "page:", page);
|
||
|
||
if (!token) {
|
||
log("token 未初始化,跳转 login");
|
||
handleLogout();
|
||
return;
|
||
}
|
||
|
||
currentPage = page;
|
||
lastKeywords = keywords;
|
||
|
||
const keywordGroups = keywords.map(k => [k]);
|
||
const requestBody = {
|
||
keywordGroups,
|
||
page: currentPage,
|
||
size: 10
|
||
};
|
||
|
||
showLoading();
|
||
|
||
try {
|
||
const response = await fetch("http://app.wisdompulse.cn/search", {
|
||
method: "POST",
|
||
headers: {
|
||
"Authorization": `${token}`,
|
||
"Content-Type": "application/json"
|
||
},
|
||
body: JSON.stringify(requestBody)
|
||
});
|
||
|
||
log("响应状态:", response.status);
|
||
|
||
if (response.status === 401) {
|
||
log("后端返回 401,token 无效,登出");
|
||
handleLogout();
|
||
return;
|
||
}
|
||
|
||
const data = await response.json();
|
||
resultBox.innerHTML = "";
|
||
|
||
if (!data.results || data.results.length === 0) {
|
||
resultBox.innerHTML = "<li>未找到相关文档</li>";
|
||
return;
|
||
}
|
||
|
||
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;
|
||
|
||
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();
|
||
|
||
} catch (err) {
|
||
console.error("搜索请求失败:", err);
|
||
resultBox.innerHTML = "<li>搜索失败,请检查网络或服务状态。</li>";
|
||
}
|
||
}
|
||
|
||
function triggerSearch() {
|
||
if (!token) {
|
||
log("triggerSearch 中 token 丢失,取消搜索");
|
||
return;
|
||
}
|
||
const val = input.value.trim();
|
||
if (!val) return clearResults();
|
||
const keywords = val.split(/\s+/);
|
||
updateHistory(val);
|
||
fetchResults(keywords, 1);
|
||
}
|
||
|
||
function bindEvents() {
|
||
log("绑定事件成功");
|
||
searchBtn.addEventListener("click", triggerSearch);
|
||
input.addEventListener("keydown", (e) => {
|
||
if (e.key === "Enter") {
|
||
log("用户按下回车 ⏎");
|
||
triggerSearch();
|
||
}
|
||
});
|
||
input.addEventListener("focus", renderHistoryTags);
|
||
input.addEventListener("input", () => !input.value.trim() && clearResults());
|
||
input.addEventListener("blur", () => setTimeout(() => historyWrapper.classList.add("hidden"), 200));
|
||
clearHistoryBtn.addEventListener("click", () => {
|
||
chrome.storage.local.remove("searchHistory", renderHistoryTags);
|
||
});
|
||
logoutBtn.addEventListener("click", handleLogout);
|
||
userAvatar.addEventListener("click", () => userDropdown.classList.toggle("hidden"));
|
||
window.addEventListener("click", (e) => {
|
||
if (!userDropdown.contains(e.target) && e.target !== userAvatar) {
|
||
userDropdown.classList.add("hidden");
|
||
}
|
||
});
|
||
}
|
||
|
||
const auth = await loadToken();
|
||
if (!auth) {
|
||
log("未通过认证,执行登出");
|
||
handleLogout();
|
||
} else {
|
||
token = auth.token;
|
||
userNameLabel.textContent = auth.username;
|
||
log("用户认证通过,用户名:", auth.username);
|
||
bindEvents();
|
||
}
|
||
});
|