66 lines
2.2 KiB
JavaScript
66 lines
2.2 KiB
JavaScript
/* 项目列表页逻辑: 语言过滤 + 排序 + 项目卡片.
|
|
* renderProjectCard 由模板内联 module 注入.
|
|
*/
|
|
|
|
import { fetchJson } from "../utils.js";
|
|
|
|
export function initProjectsPage(renderProjectCard) {
|
|
let allProjects = [];
|
|
let currentLang = "all";
|
|
let currentSort = "stars";
|
|
|
|
function renderProjects() {
|
|
const container = document.getElementById("projectList");
|
|
let list = allProjects;
|
|
if (currentLang !== "all") {
|
|
list = list.filter((p) => (p.language || "") === currentLang);
|
|
}
|
|
list = [...list].sort((a, b) => {
|
|
if (currentSort === "stars") {
|
|
return (b.stars ?? 0) - (a.stars ?? 0);
|
|
}
|
|
return String(b.updated_at || "").localeCompare(String(a.updated_at || ""));
|
|
});
|
|
if (!list.length) {
|
|
container.innerHTML = '<div class="empty-hint">没有匹配的项目</div>';
|
|
return;
|
|
}
|
|
container.innerHTML = list
|
|
.map((p) =>
|
|
renderProjectCard(p, { showDescription: true, showUpdatedAt: true })
|
|
)
|
|
.join("");
|
|
}
|
|
|
|
async function loadProjects() {
|
|
try {
|
|
allProjects = await fetchJson("/api/projects");
|
|
renderProjects();
|
|
} catch (err) {
|
|
console.error("加载项目失败:", err);
|
|
document.getElementById("projectList").innerHTML =
|
|
'<div class="empty-hint empty-hint-error">加载失败, <button type="button" class="btn btn-sm btn-outline-danger js-retry-btn">点击重试</button></div>';
|
|
}
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
loadProjects();
|
|
|
|
document.querySelectorAll("[data-lang]").forEach((btn) => {
|
|
btn.addEventListener("click", () => {
|
|
document
|
|
.querySelectorAll("[data-lang]")
|
|
.forEach((b) => b.classList.remove("active"));
|
|
btn.classList.add("active");
|
|
currentLang = btn.dataset.lang;
|
|
renderProjects();
|
|
});
|
|
});
|
|
|
|
document.getElementById("sortSelect").addEventListener("change", (e) => {
|
|
currentSort = e.target.value;
|
|
renderProjects();
|
|
});
|
|
});
|
|
}
|