Files
stash/stash-web/src/components/content/ArticleDetailView.tsx
T
stash 3c6c20e534 feat(admin): 首页卡片配置 + 页头开关验证 + 编辑按钮仅登录可见
- settings.sections:显隐 / 顺序 / 标题覆盖 / 预览条数,HomeView 应用
- /admin 新增「首页卡片」Tab,卡片标题使用展示块标题(常用站点等)
- 详情页 [编辑] 仅在登录后渲染(canEdit)
- 测试:46 passed;页头禁用、卡片隐藏/改标题/限条数、编辑可见性均实测
- 文档:ADMIN-PLAN、README
2026-10-29 19:21:34 +08:00

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>
)
}