41 lines
1.5 KiB
React
41 lines
1.5 KiB
React
import { useEffect, useState } from 'react'
|
|
import { useParams, useNavigate } from 'react-router-dom'
|
|
import { NavBar } from 'antd-mobile'
|
|
import { api } from '../../api/client.js'
|
|
|
|
// 文章详情: /macro/articles/:slug
|
|
// 使用 antd-mobile NavBar 提供原生风格的返回按钮
|
|
export default function ArticleDetail() {
|
|
const { slug } = useParams()
|
|
const navigate = useNavigate()
|
|
const [article, setArticle] = useState(null)
|
|
const [err, setErr] = useState('')
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
useEffect(() => {
|
|
let cancelled = false
|
|
setLoading(true)
|
|
api('/articles/' + encodeURIComponent(slug))
|
|
.then((data) => { if (!cancelled) setArticle(data.article) })
|
|
.catch((e) => !cancelled && setErr(e.message))
|
|
.finally(() => !cancelled && setLoading(false))
|
|
return () => { cancelled = true }
|
|
}, [slug])
|
|
|
|
return (
|
|
<div className="article-page">
|
|
<NavBar onBack={() => navigate(-1)}>文章详情</NavBar>
|
|
{loading && <div className="loading">加载中...</div>}
|
|
{err && <div className="error-banner">{err}</div>}
|
|
{!loading && !err && !article && <div className="empty">文章不存在</div>}
|
|
{!loading && !err && article && (
|
|
<div className="article-detail">
|
|
<h1>{article.title}</h1>
|
|
<div className="meta">{article.date}</div>
|
|
<div className="article-content" dangerouslySetInnerHTML={{ __html: article.contentHtml }} />
|
|
</div>
|
|
)}
|
|
</div>
|
|
)
|
|
}
|