Files
web_hghl_h5/src/components/more/more-page.tsx
T
2026-10-26 19:51:59 +07:00

118 lines
4.6 KiB
TypeScript

import { AdBannersSlot, AdIconsSlot, FriendLinksSlot, H5FriendLinksSlot } from "@/components/common/ads/slots";
import type { ReactNode } from "react";
import { ChannelHeader, H5ChannelHeader } from "@/components/common/channel-header";
import { Pagination } from "@/components/common/pagination";
import { buildPageHrefMap } from "@/components/common/pagination-map";
import { FloatingActions } from "@/components/home/floating-actions";
import { DownloadBanner } from "@/components/home/page-sections";
import { SeoBreadcrumb } from "@/components/seo/seo-breadcrumb";
import type { ShortDramaItem } from "@/components/short-drama/data";
import { H5ShortDramaCard, ShortDramaCard } from "@/components/short-drama/short-drama-card";
import { TopicListCard } from "@/components/topic/topic-list-card";
import { H5VideoCard, VideoCard } from "@/components/video/video-card";
import type { MorePageData } from "./data";
import { moreListHref } from "./route";
type CardRenderer = (item: ShortDramaItem) => ReactNode;
const layouts = {
短剧: {
gridClassName: "grid-cols-[repeat(auto-fill,266px)] gap-5",
h5GridClassName: "grid-cols-2 gap-x-[7px] gap-y-3",
renderCard: (item: ShortDramaItem) => <ShortDramaCard key={item.id} item={item} />,
renderH5Card: (item: ShortDramaItem) => <H5ShortDramaCard key={item.id} item={item} />,
},
视频: {
gridClassName: "grid-cols-[repeat(auto-fill,324px)] gap-5",
h5GridClassName: "grid-cols-2 gap-x-[7px] gap-y-3",
renderCard: (item: ShortDramaItem) => <VideoCard key={item.id} item={item} />,
renderH5Card: (item: ShortDramaItem) => <H5VideoCard key={item.id} item={item} />,
},
} satisfies Record<MorePageData["tab"], { gridClassName: string; h5GridClassName: string; renderCard: CardRenderer; renderH5Card: CardRenderer }>;
function TopicGrid({
topics,
dataType,
compact,
}: {
topics: MorePageData["topics"];
dataType: MorePageData["dataType"];
compact?: boolean;
}) {
if (!topics.length) return null;
return (
<div className={compact ? "grid grid-cols-2 gap-x-2.5 gap-y-4" : "grid grid-cols-2 gap-x-5 gap-y-7 lg:grid-cols-4"}>
{topics.map((topic) => (
<TopicListCard key={topic.id} topic={topic} dataType={dataType} compact={compact} />
))}
</div>
);
}
export function MorePage({ data }: { data: MorePageData }) {
const layout = layouts[data.tab];
const header = {
eyebrow: "MORE",
title: data.title,
subtitle: data.subtitle,
};
const hrefMap =
data.configId && data.totalPages > 1
? buildPageHrefMap(data.totalPages, (page) => moreListHref(data.configId, page))
: undefined;
return (
<>
<SeoBreadcrumb items={[{ name: "首页", href: "/" }, { name: data.title || "更多内容" }]} />
<main data-component="more-page" className="flex w-full min-w-0 flex-col gap-[18px] overflow-x-clip px-4 py-3 lg:hidden">
<H5ChannelHeader {...header} />
<AdIconsSlot variant="h5" />
<TopicGrid topics={data.topics} dataType={data.dataType} compact />
{data.items.length ? (
<div className={`grid ${layout.h5GridClassName}`}>{data.items.map((item) => layout.renderH5Card(item))}</div>
) : !data.topics.length ? (
<p className="py-16 text-center text-sm leading-5 text-white/45">暂无更多内容</p>
) : null}
{hrefMap ? <Pagination page={data.page} total={data.totalPages} hrefMap={hrefMap} className="[&_form]:hidden" /> : null}
<AdBannersSlot variant="h5" />
<H5FriendLinksSlot />
</main>
<main className="hidden lg:block">
<div className="design-frame flex flex-col gap-6 py-[43px]">
<ChannelHeader {...header} />
<AdIconsSlot variant="pc" />
<TopicGrid topics={data.topics} dataType={data.dataType} />
{data.items.length ? (
<div className={`grid scroll-mt-24 justify-between ${layout.gridClassName}`}>
{data.items.map((item) => layout.renderCard(item))}
</div>
) : !data.topics.length ? (
<p className="py-20 text-center text-sm leading-5 text-white/45">暂无更多内容</p>
) : null}
</div>
{/* 分页放在 design-frame 外,避免 Chrome CSS zoom 热区错位导致点击无响应 */}
{hrefMap ? (
<div className="flex justify-center px-6 py-6">
<Pagination page={data.page} total={data.totalPages} hrefMap={hrefMap} />
</div>
) : null}
<div className="design-frame flex flex-col gap-6 pb-[43px]">
<AdBannersSlot variant="pc" />
<DownloadBanner />
<FriendLinksSlot />
</div>
</main>
<FloatingActions />
</>
);
}