v1.2.13 人物页增强:分页控件(12条/页),与角色筛选/搜索组合
This commit is contained in:
@@ -211,12 +211,9 @@ def api_news_detail(nid):
|
||||
def api_persons():
|
||||
q = request.args.get("q", "")
|
||||
role = request.args.get("role", "")
|
||||
limit = int(request.args.get("limit", 50))
|
||||
r = tools.search_persons(q, limit=limit)
|
||||
results = r.get("results", [])
|
||||
if role:
|
||||
results = [p for p in results if p["role"] == role]
|
||||
return jsonify(results)
|
||||
page = max(1, int(request.args.get("page", 1)))
|
||||
size = min(30, max(1, int(request.args.get("size", 12))))
|
||||
return jsonify(tools.list_persons(q, role=role, page=page, size=size))
|
||||
|
||||
|
||||
@app.route("/api/persons/<int:pid>")
|
||||
|
||||
+17
-9
@@ -98,7 +98,12 @@ function loadView(v) {
|
||||
$$("#view-news .btn.small").forEach((x) => x.classList.toggle("active", !x.dataset.kind && !x.dataset.tag));
|
||||
loadNews();
|
||||
}
|
||||
else if (v === "persons") loadPersons("");
|
||||
else if (v === "persons") {
|
||||
personsPage = 1; personsQ = ""; personsRole = "";
|
||||
$("#search-persons").value = "";
|
||||
$$("#view-persons .btn.small").forEach((x) => x.classList.toggle("active", x.dataset.role === ""));
|
||||
loadPersons();
|
||||
}
|
||||
else if (v === "standings") {
|
||||
if ($("#season-select").options.length) { loadStandings(); loadPlayoffs(); }
|
||||
else loadSeasons();
|
||||
@@ -417,6 +422,7 @@ function goPage(key, p) {
|
||||
if (key === "players") { playersPage = p; loadPlayers(); }
|
||||
else if (key === "games") { gamesPage = p; loadGames(); }
|
||||
else if (key === "news") { newsPage = p; loadNews(); }
|
||||
else if (key === "persons") { personsPage = p; loadPersons(); }
|
||||
}
|
||||
|
||||
$("#btn-players").addEventListener("click", () => { playersQ = $("#search-players").value.trim(); playersPage = 1; loadPlayers(); });
|
||||
@@ -539,24 +545,26 @@ async function openNews(id) {
|
||||
}
|
||||
|
||||
/* ================= 人物 ================= */
|
||||
let personRoleFilter = "";
|
||||
async function loadPersons(q) {
|
||||
const persons = await getJSON(`/api/persons?q=${encodeURIComponent(q)}&limit=60`);
|
||||
const list = persons.filter((p) => !personRoleFilter || p.role === personRoleFilter);
|
||||
$("#grid-persons").innerHTML = list.map((p) => `
|
||||
let personsPage = 1, personsQ = "", personsRole = "";
|
||||
async function loadPersons() {
|
||||
const d = await getJSON(`/api/persons?q=${encodeURIComponent(personsQ)}&role=${personsRole}&page=${personsPage}&size=12`);
|
||||
const persons = d.results || [];
|
||||
$("#grid-persons").innerHTML = persons.map((p) => `
|
||||
<div class="card" onclick="openPerson(${p.id})">
|
||||
<h3>${esc(p.name)} <span class="en">${esc(p.name_en || "")}</span></h3>
|
||||
<div class="meta"><span class="tag">${esc(p.role_cn)}</span>${esc(p.title || "")}${p.team ? " · " + esc(p.team) : ""}</div>
|
||||
<div class="meta">${esc((p.bio || "").slice(0, 60))}…</div>
|
||||
</div>`).join("");
|
||||
renderPager(d, "persons");
|
||||
}
|
||||
$$("#view-persons .btn.small").forEach((b) => b.addEventListener("click", () => {
|
||||
$$("#view-persons .btn.small").forEach((x) => x.classList.remove("active"));
|
||||
b.classList.add("active");
|
||||
personRoleFilter = b.dataset.role;
|
||||
loadPersons($("#search-persons").value.trim());
|
||||
personsRole = b.dataset.role;
|
||||
personsPage = 1;
|
||||
loadPersons();
|
||||
}));
|
||||
$("#btn-persons").addEventListener("click", () => loadPersons($("#search-persons").value.trim()));
|
||||
$("#btn-persons").addEventListener("click", () => { personsQ = $("#search-persons").value.trim(); personsPage = 1; loadPersons(); });
|
||||
$("#search-persons").addEventListener("keydown", (e) => { if (e.key === "Enter") $("#btn-persons").click(); });
|
||||
async function openPerson(id) {
|
||||
const p = await getJSON(`/api/persons/${id}`);
|
||||
|
||||
@@ -107,6 +107,7 @@
|
||||
<input class="search" id="search-persons" placeholder="搜索人物"><button class="btn" id="btn-persons">搜索</button>
|
||||
</div>
|
||||
<div class="grid" id="grid-persons"></div>
|
||||
<div class="pager" id="pager-persons"></div>
|
||||
</section>
|
||||
<section id="view-standings" class="view">
|
||||
<div class="toolbar">
|
||||
|
||||
@@ -433,6 +433,28 @@ def search_persons(query_text, limit=MAX_SHOW):
|
||||
"bio": r["bio"], "achievements": r["achievements"]} for r in rows]}
|
||||
|
||||
|
||||
# ================================================================== 人物列表(前台分页版)
|
||||
def list_persons(q="", role="", page=1, size=12):
|
||||
"""前台人物列表:关键词 + 角色筛选 + 分页"""
|
||||
conds, args = [], []
|
||||
if q:
|
||||
like = f"%{fuzzy(q)}%"
|
||||
conds.append("(p.name LIKE ? ESCAPE '\\' OR p.name_en LIKE ? ESCAPE '\\' OR p.role_cn LIKE ? ESCAPE '\\' OR t.name LIKE ? ESCAPE '\\' OR p.bio LIKE ? ESCAPE '\\')")
|
||||
args += [like] * 5
|
||||
if role:
|
||||
conds.append("p.role=?")
|
||||
args.append(role)
|
||||
where = ("WHERE " + " AND ".join(conds)) if conds else ""
|
||||
total = query_one(f"SELECT COUNT(*) AS c FROM persons p LEFT JOIN teams t ON p.team_id=t.id {where}", args)["c"]
|
||||
rows = query(f"""SELECT p.*, t.name AS team_name FROM persons p LEFT JOIN teams t ON p.team_id=t.id
|
||||
{where} ORDER BY p.id LIMIT ? OFFSET ?""", args + [size, (page - 1) * size])
|
||||
return {"results": [
|
||||
{"id": r["id"], "name": r["name"], "name_en": r["name_en"], "role": r["role"],
|
||||
"role_cn": r["role_cn"], "title": r["title"], "team": r["team_name"],
|
||||
"bio": r["bio"], "achievements": r["achievements"]} for r in rows],
|
||||
"total": total, "page": page, "size": size}
|
||||
|
||||
|
||||
# ================================================================== 知识百科(纯向量检索)
|
||||
def search_knowledge(query_text, limit=3):
|
||||
q = (query_text or "").strip()
|
||||
|
||||
Reference in New Issue
Block a user