Files
nba-fan-hub/static/detail.js
T

137 lines
8.6 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.
/* NBA球迷大全 独立详情页渲染(/team/1 /player/1 /game/1 /news/1 /person/1 */
const $ = (s) => document.querySelector(s);
const esc = (s) => String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
const STATUS_CN = { scheduled: "未开始", live: "进行中", finished: "已结束" };
async function getJSON(url) { const r = await fetch(url); if (!r.ok) throw new Error("记录不存在或已删除"); return r.json(); }
/* 交叉链接 */
const T = (id, name) => `<a class="xlink" href="/team/${id}">${esc(name)}</a>`;
const P = (id, name) => `<a class="xlink" href="/player/${id}">${esc(name)}</a>`;
const G = (id, text) => `<a class="xlink" href="/game/${id}">${esc(text)}</a>`;
const N = (id, title) => `<a class="xlink" href="/news/${id}">${esc(title)}</a>`;
const PER = (id, name) => `<a class="xlink" href="/person/${id}">${esc(name)}</a>`;
/* ================= 球队 ================= */
function renderTeam(d) {
const t = d.team;
const standings = (d.standings || []).map((s) =>
`<span class="season-pill">${esc(s.season)} ${esc(s.conference)}${s.rank}名 · ${s.wins}-${s.losses}</span>`).join("");
const roster = (d.roster || []).map((p) => `
<div class="row-item">
<span>${P(p.id, p.name)} <span class="en">#${p.number} · ${esc(p.position)}</span></span>
<span>本季场均 <span class="num-badge">${p.season.pts}</span> 分 / ${p.season.reb} 板 / ${p.season.ast} 助</span>
</div>`).join("") || '<div class="txt">暂无球员数据</div>';
const games = (d.recent_games || []).map((g) => {
const score = g.status === "finished" ? `<span class="num-badge">${g.away_score} : ${g.home_score}</span>` : "VS";
return `<div class="row-item">
<span>${G(g.id, `${g.away_team} ${score} ${g.home_team}`)}</span>
<span class="en">${esc(g.round_name)} · ${esc(g.game_time.slice(0, 16))} · ${STATUS_CN[g.status]}</span>
</div>`;
}).join("") || '<div class="txt">暂无比赛</div>';
$("#crumb").innerHTML = `<span class="en">🏟️ 球队 / ${esc(t.name)}</span>`;
$("#detail-body").innerHTML = `
<div class="hero">
<div class="big">${esc(t.name)}</div>
<div class="detail-sub">${esc(t.name_en)} · ${esc(t.city)} · ${esc(t.arena)} · 建队 ${t.founded} 年 · 总冠军 ×${t.champion_count}</div>
</div>
<div class="section"><h3>📈 各赛季战绩</h3>${standings || '<span class="txt">暂无排名数据</span>'}</div>
<div class="section"><h3>📝 球队简介</h3><div class="txt">${esc(t.intro || "暂无简介")}</div></div>
<div class="section"><h3>🧑‍🏫 主教练</h3><div class="txt">${esc(t.head_coach || "未知")}</div></div>
<div class="section"><h3>⭐ 主要球员(本赛季场均)</h3>${roster}</div>
<div class="section"><h3>📅 近期比赛</h3>${games}</div>`;
}
/* ================= 球员 ================= */
function renderPlayer(p) {
const logs = (p.game_logs || []).map((g) => {
const score = g.home_score !== null ? `${g.away_score} : ${g.home_score}` : "VS";
return `<div class="row-item">
<span>${G(g.game_id, `${g.away_team} ${score} ${g.home_team}`)} <span class="en">${esc(g.round_name)} · ${esc(g.game_time.slice(0, 10))}</span></span>
<span><span class="num-badge">${g.pts}</span>分 ${g.reb}${g.ast}${g.stl}${g.blk}${g.min}分钟</span>
</div>`;
}).join("") || '<div class="txt">暂无比赛记录</div>';
$("#crumb").innerHTML = `<span class="en">⭐ 球员 / ${esc(p.name)}</span>`;
$("#detail-body").innerHTML = `
<div class="hero">
<div class="big">${esc(p.name)}</div>
<div class="detail-sub">${esc(p.name_en || "")} · ${p.team ? T(p.team_id ?? 0, p.team) : "自由球员"} · ${esc(p.position)} · #${p.number} · ${esc(p.country)}</div>
</div>
<div class="section"><h3>📋 基本信息</h3>
<div class="kv">
<div><span class="k">身高</span><span class="v">${p.height_cm} cm</span></div>
<div><span class="k">体重</span><span class="v">${p.weight_kg} kg</span></div>
<div><span class="k">选秀</span><span class="v">${esc(p.draft)}</span></div>
<div><span class="k">年薪</span><span class="v">$${(p.salary_m / 100).toFixed(2)} 亿</span></div>
<div><span class="k">本季场均</span><span class="v">${p.season.pts}${p.season.reb}${p.season.ast}助</span></div>
<div><span class="k">本季防守</span><span class="v">${p.season.stl}${p.season.blk}帽</span></div>
<div><span class="k">生涯场均</span><span class="v">${p.career.pts}${p.career.reb}${p.career.ast}助</span></div>
<div><span class="k">生涯场次</span><span class="v">${p.career.games} 场</span></div>
</div>
</div>
<div class="section"><h3>🏅 主要荣誉</h3><div class="txt">${esc(p.awards || "暂无")}</div></div>
<div class="section"><h3>📝 球员简介</h3><div class="txt">${esc(p.bio || "暂无")}</div></div>
<div class="section"><h3>🏀 近期比赛记录</h3>${logs}</div>`;
}
/* ================= 比赛 ================= */
function renderGame(g) {
const finished = g.status === "finished";
const head = finished
? `<div class="score-head">${T(g.home_team_id, g.home_team)} <span class="s">${g.home_score}</span> : <span class="s">${g.away_score}</span> ${T(g.away_team_id, g.away_team)}</div>`
: `<div class="score-head">${T(g.home_team_id, g.home_team)} VS ${T(g.away_team_id, g.away_team)}</div>`;
const stats = (g.box_score || []).map((s) => `
<tr><td>${esc(s.team_name)}</td><td>${P(s.player_id, s.player_name)}</td>
<td class="num">${s.points}</td><td class="num">${s.rebounds}</td><td class="num">${s.assists}</td>
<td class="num">${s.steals}</td><td class="num">${s.blocks}</td><td class="num">${s.minutes}</td></tr>`).join("");
$("#crumb").innerHTML = `<span class="en">📅 比赛 / ${esc(g.round_name)}</span>`;
$("#detail-body").innerHTML = `
<div class="hero">
<div style="text-align:center;color:var(--sub);font-size:13px">${esc(g.round_name)} · ${STATUS_CN[g.status]}</div>
${head}
<div style="text-align:center;color:var(--sub);font-size:13px;margin-top:6px">🕐 ${esc(g.game_time)} · ${esc(g.venue)} · ${esc(g.broadcast)}</div>
</div>
${stats ? `<div class="section"><h3>📊 球员技术统计</h3>
<table><tr><th>球队</th><th>球员</th><th>得分</th><th>篮板</th><th>助攻</th><th>抢断</th><th>盖帽</th><th>分钟</th></tr>${stats}</table>
</div>` : '<div class="section"><h3>📊 球员技术统计</h3><div class="txt">暂无统计</div></div>'}`;
}
/* ================= 新闻/百科 ================= */
function renderNews(n) {
$("#crumb").innerHTML = `<span class="en">📰 ${n.kind === "wiki" ? "百科" : "新闻"} / ${esc(n.title)}</span>`;
$("#detail-body").innerHTML = `
<div class="hero">
<div class="big">${esc(n.title)}</div>
<div class="detail-sub">🕐 ${esc(n.publish_time || "")} · ${esc(n.source || "")}${n.author ? " · " + esc(n.author) : ""} · ${n.kind === "wiki" ? "百科词条" : "新闻"}${n.tags ? " · " + esc(n.tags) : ""}</div>
</div>
<div class="section"><h3>📄 正文</h3><div class="news-body">${esc(n.content || "")}</div></div>`;
}
/* ================= 人物 ================= */
function renderPerson(p) {
$("#crumb").innerHTML = `<span class="en">👥 人物 / ${esc(p.name)}</span>`;
$("#detail-body").innerHTML = `
<div class="hero">
<div class="big">${esc(p.name)}</div>
<div class="detail-sub">${esc(p.role_cn || p.role || "")} · ${esc(p.title || "")}${p.team_id ? " · " + T(p.team_id, p.team_name || "相关球队") : ""}</div>
</div>
<div class="section"><h3>📝 人物简介</h3><div class="txt">${esc(p.bio || "暂无")}</div></div>
<div class="section"><h3>🏅 主要成就</h3><div class="txt">${esc(p.achievements || "暂无")}</div></div>`;
}
/* ================= 路由 ================= */
const ROUTERS = { team: renderTeam, player: renderPlayer, game: renderGame, news: renderNews, person: renderPerson };
const APIS = { team: "/api/teams/", player: "/api/players/", game: "/api/games/", news: "/api/news/", person: "/api/persons/" };
(async function init() {
const m = location.pathname.match(/^\/(team|player|game|news|person)\/(\d+)\/?$/);
if (!m) { $("#detail-body").innerHTML = '<div class="loading">❌ 地址无效</div>'; return; }
const [etype, eid] = [m[1], parseInt(m[2])];
try {
const d = await getJSON(APIS[etype] + eid);
ROUTERS[etype](d);
} catch (e) {
$("#detail-body").innerHTML = `<div class="loading">❌ ${esc(e.message)}<br><br><a class="tab" href="/">← 返回首页</a></div>`;
}
})();