feat(ui): refactor EmptyState to accept dynamic string props and add empty state to archives page
This commit is contained in:
parent
824ad5a3d3
commit
178870427c
@ -14,7 +14,8 @@ use dioxus::router::components::Link;
|
||||
#[derive(Props, Clone, PartialEq)]
|
||||
pub struct EmptyStateAction {
|
||||
/// 按钮文案。
|
||||
pub label: &'static str,
|
||||
#[props(into)]
|
||||
pub label: String,
|
||||
/// 跳转目标路由。
|
||||
pub to: crate::router::Route,
|
||||
}
|
||||
@ -28,11 +29,14 @@ pub struct EmptyStateAction {
|
||||
#[component]
|
||||
pub fn EmptyState(
|
||||
/// 主标题(通常为「还没有文章」之类)。
|
||||
#[props(default)] title: Option<&'static str>,
|
||||
#[props(into, default = "还没有文章".to_string())]
|
||||
title: String,
|
||||
/// 副文案,说明当前状态或引导用户。
|
||||
#[props(default)] description: Option<&'static str>,
|
||||
#[props(into, default = String::new())]
|
||||
description: String,
|
||||
/// 可选的行动按钮。
|
||||
#[props(default)] action: Option<EmptyStateAction>,
|
||||
#[props(default)]
|
||||
action: Option<EmptyStateAction>,
|
||||
) -> Element {
|
||||
rsx! {
|
||||
div { class: "flex flex-col items-center justify-center text-center py-20 px-4 page-enter",
|
||||
@ -45,12 +49,12 @@ pub fn EmptyState(
|
||||
}
|
||||
// 主标题:衬线字体,与首页 H1 风格呼应但更轻量。
|
||||
h2 { class: "mt-8 text-2xl font-bold tracking-tight text-paper-primary",
|
||||
{title.unwrap_or("还没有文章")}
|
||||
"{title}"
|
||||
}
|
||||
// 副文案:次要色,限宽保证可读性。
|
||||
if let Some(desc) = description {
|
||||
if !description.is_empty() {
|
||||
p { class: "mt-3 text-sm leading-relaxed text-paper-secondary max-w-md",
|
||||
{desc}
|
||||
"{description}"
|
||||
}
|
||||
}
|
||||
// 行动按钮:药丸形,与搜索页主按钮一致。
|
||||
@ -58,7 +62,7 @@ pub fn EmptyState(
|
||||
Link {
|
||||
class: "mt-8 inline-flex items-center px-6 py-2 bg-paper-accent text-white rounded-full font-medium text-sm hover:brightness-110 active:scale-[0.98] transition-all duration-200",
|
||||
to: act.to,
|
||||
{act.label}
|
||||
"{act.label}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@ use dioxus::prelude::*;
|
||||
use dioxus::router::components::Link;
|
||||
|
||||
use crate::api::posts::{list_published_posts, PostListResponse};
|
||||
use crate::components::empty_state::EmptyState;
|
||||
use crate::components::skeletons::archive_skeleton::ArchiveSkeleton;
|
||||
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
|
||||
use crate::models::post::PostListItem;
|
||||
@ -119,6 +120,14 @@ fn ArchivesContent() -> Element {
|
||||
let posts_data = posts_res.read();
|
||||
match &*posts_data {
|
||||
Some(Ok(PostListResponse { posts, total })) => {
|
||||
if *total == 0 {
|
||||
rsx! {
|
||||
EmptyState {
|
||||
title: "还没有文章归档",
|
||||
description: "发布文章后,这里会自动按年月进行归档显示。",
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let grouped = group_posts(posts);
|
||||
rsx! {
|
||||
div { class: "mt-2 text-base text-paper-secondary",
|
||||
@ -134,6 +143,7 @@ fn ArchivesContent() -> Element {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Err(e)) => {
|
||||
rsx! {
|
||||
div { class: "text-center text-red-500 dark:text-red-400 py-20", "加载失败: {e}" }
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user