- settings.sections:显隐 / 顺序 / 标题覆盖 / 预览条数,HomeView 应用 - /admin 新增「首页卡片」Tab,卡片标题使用展示块标题(常用站点等) - 详情页 [编辑] 仅在登录后渲染(canEdit) - 测试:46 passed;页头禁用、卡片隐藏/改标题/限条数、编辑可见性均实测 - 文档:ADMIN-PLAN、README
77 lines
2.3 KiB
TypeScript
77 lines
2.3 KiB
TypeScript
import { Breadcrumb, Card, Paragraph, Text, Title } from '@stash/ui'
|
|
import type { ArticleItem } from '../../data/types'
|
|
import { viewPath } from '../../data/view'
|
|
import { ArticleBody } from './ArticleBody'
|
|
|
|
/**
|
|
* 文章详情页(对应模板图二):
|
|
* 面包屑 + 大标题 + [编辑] + 元信息行 + 白色正文卡。
|
|
*
|
|
* 正文是一整段 Markdown,交给 ArticleBody 解析渲染;
|
|
* 渲染细节(支持哪些语法)都收在那一个组件里。
|
|
*/
|
|
type ArticleDetailViewProps = {
|
|
article: ArticleItem
|
|
categoryId: string
|
|
categoryTitle: string
|
|
onNavigate: (href: string) => void
|
|
onEdit: () => void
|
|
/** 只有登录后才显示 [编辑] */
|
|
canEdit: boolean
|
|
}
|
|
|
|
export function ArticleDetailView({
|
|
article,
|
|
categoryId,
|
|
categoryTitle,
|
|
onNavigate,
|
|
onEdit,
|
|
canEdit,
|
|
}: ArticleDetailViewProps) {
|
|
const meta = article.meta ?? ['2 年前', categoryTitle]
|
|
const crumbs = [
|
|
{ label: '首页', href: '/' },
|
|
{ label: categoryTitle, href: viewPath({ type: 'detail', categoryId }) },
|
|
{ label: '文章' },
|
|
]
|
|
|
|
return (
|
|
<div className="detail-view article-view">
|
|
<Card padding="none" className="detail-nav">
|
|
<Breadcrumb className="detail-breadcrumb" items={crumbs} onNavigate={onNavigate} />
|
|
</Card>
|
|
|
|
<header className="article-head">
|
|
<Title level={1} as="h2" className="article-heading">
|
|
{article.title}
|
|
{canEdit && (
|
|
<button type="button" className="item-edit" title="编辑文章" onClick={onEdit}>
|
|
[编辑]
|
|
</button>
|
|
)}
|
|
</Title>
|
|
|
|
<div className="article-meta">
|
|
{meta.map((text, index) => (
|
|
<span className="article-meta-item" key={text}>
|
|
{index > 0 && <i className="article-meta-dot" aria-hidden="true" />}
|
|
<Text size="xs" tone="muted">
|
|
{text}
|
|
</Text>
|
|
</span>
|
|
))}
|
|
</div>
|
|
</header>
|
|
|
|
<Card padding="none" className="article-body-card">
|
|
<div className="article-body">
|
|
<Paragraph tone="main" size="md" leading="relaxed" className="article-lead">
|
|
{article.desc}
|
|
</Paragraph>
|
|
<ArticleBody markdown={article.body} />
|
|
</div>
|
|
</Card>
|
|
</div>
|
|
)
|
|
}
|