initial: blog-app snapshot
This commit is contained in:
104
static/js/pages/search.js
Normal file
104
static/js/pages/search.js
Normal file
@@ -0,0 +1,104 @@
|
||||
/* 全局搜索页逻辑: 防抖搜索 + 项目/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("")
|
||||
: '<div class="empty-hint">无匹配项目</div>';
|
||||
|
||||
document.getElementById("resultReleases").innerHTML = data.releases.length
|
||||
? data.releases
|
||||
.map(
|
||||
(r) => `
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>
|
||||
<strong>${escapeHtml(r.tag_name || "")}</strong>
|
||||
<span class="text-muted"> ${escapeHtml(truncate(r.name, 60))}</span>
|
||||
</span>
|
||||
<a class="btn btn-sm btn-outline-primary" href="/projects/${r.project_id}">查看项目</a>
|
||||
</li>`
|
||||
)
|
||||
.join("")
|
||||
: '<li class="list-group-item empty-hint">无匹配 release</li>';
|
||||
|
||||
document.getElementById("resultIssues").innerHTML = data.issues.length
|
||||
? data.issues
|
||||
.map(
|
||||
(i) => `
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
<span>
|
||||
<span class="badge ${i.state === "open" ? "badge-state-open" : "badge-state-closed"} me-1">${escapeHtml(i.state || "")}</span>
|
||||
${escapeHtml(truncate(i.title, 80))}
|
||||
</span>
|
||||
<a class="btn btn-sm btn-outline-primary" href="/projects/${i.project_id}">查看项目</a>
|
||||
</li>`
|
||||
)
|
||||
.join("")
|
||||
: '<li class="list-group-item empty-hint">无匹配 issue</li>';
|
||||
}
|
||||
|
||||
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 =
|
||||
'加载失败, <button type="button" class="btn btn-sm btn-outline-danger" id="searchRetryBtn">点击重试</button>';
|
||||
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());
|
||||
}
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user