import { Breadcrumb, Card, Empty, Space, Title } from '@stash/ui' import { categoryCount, type AppItem, type ArticleItem, type Category, type PosterItem, } from '../../data/types' import { viewPath } from '../../data/view' import { AppGrid } from './AppGrid' import { CesCardGrid } from './CesCardGrid' import { GroupBlock } from './GroupBlock' import { PosterGrid } from './PosterGrid' /** * 分类明细视图:面包屑 + hero(图标 / 标题 / 数量)+ 内容区。 * * 内容区按分类类型切换: * - apps:指定分组时只渲染该组,否则单组扁平渲染、多组带小标题分组渲染; * - posters:6 列海报; * - articles:上图下文白卡网格。 */ type DetailViewProps = { category: Category /** 从侧栏子菜单进入时指定的分组 */ groupId?: string /** 点击面包屑中间项(SPA 路由) */ onNavigate: (href: string) => void /** 点击卡片 / 海报进入条目详情 */ onOpenItem: (itemId: string) => void } export function DetailView({ category, groupId, onNavigate, onOpenItem }: DetailViewProps) { // 三种类型共用「分区 → 分组 → 条目」结构;这里抹平联合类型,渲染时再按 kind 分派 type RenderItem = AppItem | PosterItem | ArticleItem const groups = category.groups as { id: string name: string items: RenderItem[] }[] const activeGroup = groupId !== undefined ? groups.find((group) => group.id === groupId) : undefined const title = activeGroup?.name ?? category.title const count = activeGroup !== undefined ? activeGroup.items.length : categoryCount(category) const crumbs = activeGroup !== undefined ? [ { label: '首页', href: '/' }, { label: category.title, href: viewPath({ type: 'detail', categoryId: category.id }) }, { label: activeGroup.name }, ] : [ { label: '首页', href: '/' }, { label: category.title, href: viewPath({ type: 'detail', categoryId: category.id }) }, ] /** 按类型渲染一组条目 */ function renderItems(items: RenderItem[]) { if (category.kind === 'posters') { return } if (category.kind === 'articles') { return } return } function renderBody() { if (activeGroup !== undefined) { return renderItems(activeGroup.items) } const direct = (category.items ?? []) as RenderItem[] // 空分组不占篇幅(管理后台仍然保留,之后可以往里加条目) const filledGroups = groups.filter((group) => group.items.length > 0) if (filledGroups.length === 0) { return direct.length > 0 ? ( renderItems(direct) ) : ( ) } if (filledGroups.length === 1 && direct.length === 0) { return renderItems(filledGroups[0].items) } return ( {filledGroups.map((group) => ( {renderItems(group.items)} ))} {direct.length > 0 && ( {renderItems(direct)} )} ) } return (
{title} [{count}]
{renderBody()}
) }