2025-06-01 11:34:10 +08:00

280 lines
9.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

document.addEventListener("DOMContentLoaded", async () => {
// ===== 自适应 / 拖拽 =====
const panel = document.getElementById("draggablePanel");
const header = document.querySelector(".header");
if (window.innerWidth > 900 && window.innerHeight > 700) {
document.body.classList.add("fullscreen");
if (panel) {
panel.style.left = "";
panel.style.top = "";
panel.style.position = "fixed";
}
} else if (panel && header) {
let dragging = false, offsetX = 0, offsetY = 0;
header.addEventListener("mousedown", (e) => {
dragging = true;
offsetX = e.clientX - panel.offsetLeft;
offsetY = e.clientY - panel.offsetTop;
document.body.style.userSelect = "none";
});
document.addEventListener("mousemove", (e) => {
if (dragging) {
panel.style.left = Math.max(0, e.clientX - offsetX) + "px";
panel.style.top = Math.max(0, e.clientY - offsetY) + "px";
}
});
document.addEventListener("mouseup", () => {
dragging = false;
document.body.style.userSelect = "";
});
}
// ===== 元素绑定 =====
const input = document.getElementById("searchInput");
const searchBtn = document.getElementById("searchBtn");
const clearBtn = document.getElementById("clearHistoryBtn");
const historyBox = document.getElementById("historyTags");
const historyWrapper = document.getElementById("historyWrapper");
const resultBox = document.getElementById("results");
const llmResultContainer = document.getElementById("llmResultContainer");
const llmResultContent = document.getElementById("llmResultContent");
const llmInput = document.getElementById("llmInput");
const llmSendBtn = document.getElementById("llmSendBtn");
const logoutBtn = document.getElementById("logoutBtn");
const userNameLabel = document.getElementById("userName");
const userAvatar = document.getElementById("userAvatar");
const userDropdown = document.getElementById("userDropdown");
const openTabBtn = document.getElementById("openTabBtn");
// ===== 标签切换 =====
const tabEs = document.getElementById("tabEs");
const tabAi = document.getElementById("tabAi");
const tabContentEs = document.getElementById("tabContentEs");
const tabContentAi = document.getElementById("tabContentAi");
tabEs.onclick = () => {
tabEs.classList.add("active");
tabAi.classList.remove("active");
tabContentEs.classList.add("active");
tabContentAi.classList.remove("active");
};
tabAi.onclick = () => {
tabEs.classList.remove("active");
tabAi.classList.add("active");
tabContentEs.classList.remove("active");
tabContentAi.classList.add("active");
setTimeout(() => {
llmResultContent.scrollTop = llmResultContent.scrollHeight;
}, 100);
};
// ===== 新标签页打开 popup.html =====
if (openTabBtn) {
openTabBtn.onclick = () => {
const url = chrome?.runtime?.getURL("pages/popup.html") || "popup.html";
try {
chrome?.tabs?.create({ url });
} catch {
window.open(url, "_blank");
}
};
}
// ===== 状态变量 =====
let token = null;
let currentPage = 1;
let totalPages = 1;
let lastKeywords = [];
// ===== 加载 token带用户名=====
const auth = await loadToken();
if (!auth) {
log("未认证,登出");
handleLogout();
return;
}
token = auth.token;
userNameLabel.textContent = auth.username;
log("用户认证成功:", auth.username);
// ===== 搜索触发函数 =====
async function triggerSearch() {
const raw = input?.value?.trim();
if (!token || !raw) return;
updateHistory(raw);
renderHistoryTags();
fetchLLMAnswer(raw, llmResultContainer, llmResultContent);
fetchResults(raw, 1);
}
// ===== 搜索实现(含 ES + 分页)=====
function parseKeywordGroups(inputStr) {
return inputStr
.trim()
.split("||")
.map(group => {
group = group.trim();
if (group.startsWith("(") && group.endsWith(")")) group = group.slice(1, -1);
return group.split(/\s+/).filter(Boolean);
})
.filter(g => g.length > 0);
}
function showLoading() {
resultBox.innerHTML = "<li>加载中...</li>";
}
function clearResults() {
resultBox.innerHTML = "";
llmResultContent.innerHTML = "";
llmResultContainer.classList.add("hidden");
historyWrapper.classList.add("hidden");
}
function renderPagination() {
const pagination = document.createElement("div");
pagination.className = "pagination";
if (currentPage > 1) {
const prev = document.createElement("button");
prev.textContent = "上一页";
prev.onclick = () => fetchResults(lastKeywords, currentPage - 1);
pagination.appendChild(prev);
}
if (currentPage < totalPages) {
const next = document.createElement("button");
next.textContent = "下一页";
next.onclick = () => fetchResults(lastKeywords, currentPage + 1);
pagination.appendChild(next);
}
resultBox.appendChild(pagination);
}
async function fetchResults(rawInput, page) {
currentPage = page;
lastKeywords = rawInput;
showLoading();
const keywordGroups = parseKeywordGroups(rawInput);
const requestBody = {
keywordGroups,
page: currentPage,
size: 10
};
try {
const response = await fetch("http://app.wisdompulse.cn/search", {
method: "POST",
headers: {
"Authorization": `${token}`,
"Content-Type": "application/json"
},
body: JSON.stringify(requestBody)
});
if (response.status === 401) return handleLogout();
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 path = doc.filepath.replace(/^import-data\//, "").replace(/\.md$/, ".html");
const link = document.createElement("a");
link.href = `http://share.wisdompulse.cn/public/${path}`;
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) {
resultBox.innerHTML = "<li>搜索失败,请检查网络或服务状态。</li>";
}
}
// ===== 历史记录 =====
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(show = false) {
chrome.storage.local.get(["searchHistory"], (res) => {
const history = res.searchHistory || [];
historyBox.innerHTML = "";
if (history.length === 0 || !show) {
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");
});
}
// ===== DOM 事件绑定 =====
searchBtn.addEventListener("click", triggerSearch);
input.addEventListener("keydown", e => e.key === "Enter" && triggerSearch());
input.addEventListener("focus", () => renderHistoryTags(true));
input.addEventListener("input", () => !input.value.trim() && clearResults());
input.addEventListener("blur", () => setTimeout(() => historyWrapper.classList.add("hidden"), 200));
clearBtn.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");
}
});
llmSendBtn?.addEventListener("click", () => {
const val = llmInput.value.trim();
if (!val) return;
llmInput.value = "";
fetchLLMAnswer(val, llmResultContainer, llmResultContent);
});
llmInput.addEventListener("keydown", (e) => {
if (e.key === "Enter") llmSendBtn.click();
});
// 首次展示历史
renderHistoryTags();
});