feat(web): use history routing and preserve scroll on filter changes

This commit is contained in:
kairee committed 2026-11-01 01:55:37 +08:00
1 parent 1b08854b25
commit 52a8d90c47
9 files changed
+113 -33

No files matched your search

+7 -7
View File
@@ -17,7 +17,7 @@ function heatStrip(items) {
if (!items.length) return emptyState("暂无热度数据", "完成一次快照后这里会出现榜单。");
return `<div class="heat-strip">
${items.map((item, index) => `
<a class="heat-card" href="#/video/${item.aid}">
<a class="heat-card" href="/video/${item.aid}">
<span class="heat-rank">${index + 1}</span>
${cover(item, "heat-thumb")}
<strong class="heat-title">${escapeHtml(item.title)}</strong>
@@ -82,7 +82,7 @@ export async function renderHome(root) {
${statChip("待确认候选", formatCount(pending), pending ? "warning" : "")}
</div>
${pending ? `<a class="notice-row" href="#/candidates">
${pending ? `<a class="notice-row" href="/candidates">
<strong>${formatCount(pending)} 条候选待确认</strong>
<span>请在 Telegram 中处理 →</span>
</a>` : ""}
@@ -90,7 +90,7 @@ export async function renderHome(root) {
<section class="panel">
<div class="section-head">
<h2>最新入库</h2>
<a class="text-link" href="#/rank?scope=video&sort=added&within_days=7">查看全部</a>
<a class="text-link" href="/rank?scope=video&sort=added&within_days=7">查看全部</a>
</div>
${addedNote}
<div class="video-list">
@@ -102,7 +102,7 @@ export async function renderHome(root) {
<section class="panel">
<div class="section-head">
<h2>最近发布</h2>
<a class="text-link" href="#/rank?scope=video&sort=published&within_days=14">查看全部</a>
<a class="text-link" href="/rank?scope=video&sort=published&within_days=14">查看全部</a>
</div>
<p class="section-note">按视频发布时间排序,与入库时间无关。</p>
<div class="video-list">
@@ -114,7 +114,7 @@ export async function renderHome(root) {
<section class="panel">
<div class="section-head">
<h2>增长动态</h2>
<a class="text-link" href="#/rank?scope=video&sort=growth&growth_days=7">增长榜</a>
<a class="text-link" href="/rank?scope=video&sort=growth&growth_days=7">增长榜</a>
</div>
${growth.available && growth.items.length
? `<div class="video-list">${growth.items.map((item, index) => videoCard(item, { rank: index + 1 })).join("")}</div>`
@@ -124,7 +124,7 @@ export async function renderHome(root) {
<section class="panel">
<div class="section-head">
<h2>热度速览</h2>
<a class="text-link" href="#/rank?scope=video&sort=heat">完整榜单</a>
<a class="text-link" href="/rank?scope=video&sort=heat">完整榜单</a>
</div>
${heatStrip(heat.items)}
</section>
@@ -141,7 +141,7 @@ export async function renderHome(root) {
<div><span>最近快照</span><strong>${escapeHtml(formatDateTime(overview.tasks?.snapshot?.finished_at))}</strong></div>
<div><span>最近发现</span><strong>${escapeHtml(formatDateTime(overview.tasks?.discovery?.finished_at))}</strong></div>
</div>
<a class="text-link" href="#/system">查看系统状态 →</a>
<a class="text-link" href="/system">查看系统状态 →</a>
</section>
</section>`;
+1 -1
View File
@@ -35,7 +35,7 @@ export async function renderUp(root, { params, query }) {
root.innerHTML = `<section class="page up-page">
<header class="page-head">
<a class="back-link" href="#/rank?scope=up&sort=avg_views">← 返回 UP 榜</a>
<a class="back-link" href="/rank?scope=up&sort=avg_views">← 返回 UP 榜</a>
<a class="button ghost" href="${escapeAttr(up.space_url)}" target="_blank" rel="noreferrer">B 站空间</a>
</header>
+3 -3
View File
@@ -46,7 +46,7 @@ export async function renderVideo(root, { params, query }) {
root.innerHTML = `<section class="page video-page">
<header class="page-head">
<a class="back-link" href="#/rank?scope=video&sort=heat">← 返回榜单</a>
<a class="back-link" href="/rank?scope=video&sort=heat">← 返回榜单</a>
<div class="head-actions">
${detail.url ? `<a class="button ghost" href="${escapeAttr(detail.url)}" target="_blank" rel="noreferrer">打开 B 站</a>` : ""}
</div>
@@ -57,7 +57,7 @@ export async function renderVideo(root, { params, query }) {
<div class="detail-hero-body">
<h1>${escapeHtml(detail.title)}</h1>
<div class="detail-meta">
${detail.up_mid ? `<a class="inline-link" href="#/up/${detail.up_mid}">${escapeHtml(detail.up_name || "未知 UP")}</a>` : escapeHtml(detail.up_name || "未知 UP")}
${detail.up_mid ? `<a class="inline-link" href="/up/${detail.up_mid}">${escapeHtml(detail.up_name || "未知 UP")}</a>` : escapeHtml(detail.up_name || "未知 UP")}
<span>${escapeHtml(formatDate(detail.pubdate))}</span>
<span>${escapeHtml(formatDuration(detail.duration))}</span>
${detail.folder_title ? badge(detail.folder_title) : ""}
@@ -98,7 +98,7 @@ export async function renderVideo(root, { params, query }) {
${up ? `<section class="panel">
<div class="section-head">
<h2>该 UP 的其他视频</h2>
<a class="text-link" href="#/up/${detail.up_mid}">查看 UP 页 →</a>
<a class="text-link" href="/up/${detail.up_mid}">查看 UP 页 →</a>
</div>
<div class="video-list">
${others.length ? others.map((item) => videoCard(item)).join("") : emptyState("没有其他视频")}