feat: 首页热门区改为「社群常用资料」榜单(封面+名次,零数字)

- 新增 PopularRankList:前3名奖牌🥇🥈🥉 + 4·5灰序号,封面缩略图,
  类型·分类·更新时间,预览/下载按钮;与「最新更新」「官方推荐」版式区分
- 无封面时按资料类型渲染渐变+图标兜底(纯CSS),封面加载失败亦回退
- 分类名复用 cleanCategoryDisplayName,与全站一致(去掉括号后缀)
- i18n popularSection 改为 社群常用资料 / Community Favorites
- 新增后端接口契约文档 docs/specs/2026-05-29-popular-resources-section.md

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
TerryM
2026-05-29 14:53:52 +08:00
parent cfae09a7d3
commit 512fa53c2b
5 changed files with 486 additions and 24 deletions

View File

@@ -8,6 +8,7 @@ import {
ComingSoonLatestUpdateRow,
LatestUpdateRow,
} from "../../components/LatestUpdateRow";
import { PopularRankList } from "../../components/PopularRankList";
import { RecommendedCard } from "../../components/RecommendedCard";
import { SectionHeader } from "../../components/SectionHeader";
import { MessageBubble } from "../../components/messageStream/MessageBubble";
@@ -246,7 +247,6 @@ export function Home() {
const latestPlaceholderCount = Math.max(0, 5 - latest.length);
const hasPopular = popular.length > 0 || popularPosts.length > 0;
const popularPlaceholderCount = Math.max(0, 5 - popular.length);
const recommendedDotCount = rec.length;
const activeRecommendedDot =
recommendedDotCount > 0
@@ -513,27 +513,8 @@ export function Home() {
viewAllLabel={t("viewAll")}
/>
</div>
<div className="flex flex-col gap-3 md:hidden">
{popularPosts.slice(0, 5).map((post) => (
<MessageBubble key={post.id} post={post} />
))}
</div>
<div className="mt-7 hidden grid-cols-1 gap-3 min-[576px]:grid-cols-2 md:grid md:grid-cols-2 md:gap-4 lg:grid-cols-3 xl:grid-cols-5">
{popular.map((r) => (
<LatestUpdateRow
key={r.id}
r={r}
iconKey={iconKeyForResource(r)}
/>
))}
{Array.from({ length: popularPlaceholderCount }).map(
(_, index) => (
<ComingSoonLatestUpdateRow
key={`popular-coming-soon-${index}`}
index={popular.length + index}
/>
),
)}
<div className="mt-4 md:mt-7">
<PopularRankList posts={popularPosts} categories={cats} />
</div>
</section>
</Reveal>