Skip to main content

yggdrasil/components/post/
post_header.rs

1//! 文章页眉组件
2//!
3//! 组合面包屑、标题、摘要与元信息,草稿状态会在标题旁显示草稿图标。
4
5use dioxus::prelude::*;
6
7use crate::components::post::breadcrumbs::Breadcrumbs;
8use crate::components::post::post_meta::PostMeta;
9use crate::models::post::{Post, PostStatus};
10
11/// 文章页眉组件。
12///
13/// Props:
14/// - `post`:文章数据模型
15/// - `full_reload`:面包屑 Home 链接走整页加载(默认 false)。仅当渲染在
16///   admin 布局内(`/admin/preview`)时传 true——跨 layout 分支的客户端
17///   导航会触发 dioxus 0.7.10 的 suspense 卸载双重回收 bug(详见
18///   `src/pages/admin/preview.rs` 模块文档)。
19///
20/// 展示内容包括:
21/// - 面包屑导航(Home → 文章标题)
22/// - 文章标题,草稿状态附加草稿图标
23/// - 文章摘要(如有)
24/// - 文章元信息
25#[component]
26pub fn PostHeader(post: Post, #[props(default = false)] full_reload: bool) -> Element {
27    rsx! {
28        header { class: "post-header",
29            Breadcrumbs { title: post.title.clone(), full_reload }
30            h1 { class: "post-title", "data-vt-post-id": "{post.id}", "data-vt-role": "title",
31                "{post.title}"
32                if post.status == PostStatus::Draft {
33                    span { class: "entry-hint", title: "Draft",
34                        svg {
35                            xmlns: "http://www.w3.org/2000/svg",
36                            height: "35",
37                            view_box: "0 -960 960 960",
38                            fill: "currentColor",
39                            path { d: "M160-410v-60h300v60H160Zm0-165v-60h470v60H160Zm0-165v-60h470v60H160Zm360 580v-123l221-220q9-9 20-13t22-4q12 0 23 4.5t20 13.5l37 37q9 9 13 20t4 22q0 11-4.5 22.5T862.09-380L643-160H520Zm300-263-37-37 37 37ZM580-220h38l121-122-18-19-19-18-122 121v38Zm141-141-19-18 37 37-18-19Z" }
40                        }
41                    }
42                }
43            }
44
45            if let Some(summary) = &post.summary {
46                div { class: "post-description", "{summary}" }
47            }
48
49            PostMeta { post: post.clone() }
50        }
51    }
52}