/* 全局搜索页逻辑: 防抖搜索 + 项目/release/issue 三段结果.
* renderProjectCard 由模板内联 module 注入.
*/
import { debounce, fetchJson, escapeHtml, truncate } from "../utils.js";
export function initSearchPage(renderProjectCard) {
function renderResults(data) {
const hint = document.getElementById("searchHint");
const results = document.getElementById("searchResults");
const total = data.projects.length + data.releases.length + data.issues.length;
if (!total) {
results.classList.add("d-none");
hint.classList.remove("d-none");
hint.textContent = "没有找到匹配结果";
return;
}
hint.classList.add("d-none");
results.classList.remove("d-none");
document.getElementById("projCount").textContent = data.projects.length;
document.getElementById("relCount").textContent = data.releases.length;
document.getElementById("issueCount").textContent = data.issues.length;
document.getElementById("resultProjects").innerHTML = data.projects.length
? data.projects
.map((p) =>
renderProjectCard(p, { showSubtitle: false, showForks: false })
)
.join("")
: '
无匹配项目
';
document.getElementById("resultReleases").innerHTML = data.releases.length
? data.releases
.map(
(r) => `
${escapeHtml(r.tag_name || "")}
${escapeHtml(truncate(r.name, 60))}
查看项目
`
)
.join("")
: '无匹配 release';
document.getElementById("resultIssues").innerHTML = data.issues.length
? data.issues
.map(
(i) => `
${escapeHtml(i.state || "")}
${escapeHtml(truncate(i.title, 80))}
查看项目
`
)
.join("")
: '无匹配 issue';
}
async function doSearch(keyword) {
const hint = document.getElementById("searchHint");
const results = document.getElementById("searchResults");
if (!keyword) {
results.classList.add("d-none");
hint.classList.remove("d-none");
hint.textContent = "输入关键词开始搜索";
return;
}
try {
hint.classList.remove("empty-hint-error");
const data = await fetchJson(`/api/search?q=${encodeURIComponent(keyword)}`);
renderResults(data);
} catch (err) {
console.error("搜索失败:", err);
results.classList.add("d-none");
hint.classList.remove("d-none");
hint.classList.add("empty-hint-error");
hint.innerHTML =
'加载失败, ';
const retryBtn = document.getElementById("searchRetryBtn");
if (retryBtn) retryBtn.addEventListener("click", () => doSearch(keyword));
}
}
const debouncedSearch = debounce(doSearch, 300);
document.addEventListener("DOMContentLoaded", () => {
const input = document.getElementById("searchInput");
input.addEventListener("input", (e) => debouncedSearch(e.target.value.trim()));
// Support ?q= from the navbar search box.
const params = new URLSearchParams(window.location.search);
const q = params.get("q");
if (q) {
input.value = q;
doSearch(q.trim());
}
});
}