refactor: remove PageLayout from all frontend pages, delegate to FrontendLayout

- Remove PageLayout wrapper from Home, HomePage, Archives, Tags,
  TagDetail, PostDetail, Search, and About components
- Remove unused imports: use_nav_items, use_route, PageLayout, Route
- Pages now render only their content; Header/Footer are provided by
  FrontendLayout via the router's #[layout] attribute
- Skeleton screens (DelayedSkeleton) remain in data-loading branches
- This eliminates redundant Header/Footer re-mounting on every route
  change, which was the primary source of page transition flicker

Files changed:
- src/pages/home.rs: remove PageLayout, keep HomeInfo + HomePosts
- src/pages/about.rs: remove PageLayout, render content directly
- src/pages/archives.rs: remove PageLayout, keep header + ArchivesContent
- src/pages/post_detail.rs: remove PageLayout, keep PostDetailContent
- src/pages/search.rs: remove PageLayout, keep search form + results
- src/pages/tags.rs: remove PageLayout from Tags and TagDetail
This commit is contained in:
xfy 2026-06-03 18:38:11 +08:00
parent 8845577958
commit 5d018864c2
6 changed files with 69 additions and 121 deletions

View File

@ -1,16 +1,8 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::router::Route;
#[component] #[component]
pub fn About() -> Element { pub fn About() -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
rsx! { rsx! {
PageLayout { nav_items,
header { class: "page-header mb-6", header { class: "page-header mb-6",
h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]", h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]",
"关于" "关于"
@ -38,4 +30,3 @@ pub fn About() -> Element {
} }
} }
} }
}

View File

@ -1,12 +1,9 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::api::posts::{list_published_posts, PostListResponse}; use crate::api::posts::{list_published_posts, PostListResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
use crate::components::skeletons::archive_skeleton::ArchiveSkeleton; use crate::components::skeletons::archive_skeleton::ArchiveSkeleton;
use crate::models::post::Post; use crate::models::post::Post;
use crate::router::Route;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq)]
struct YearGroup { struct YearGroup {
@ -80,11 +77,7 @@ fn group_posts(posts: &[Post]) -> Vec<YearGroup> {
#[component] #[component]
pub fn Archives() -> Element { pub fn Archives() -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
rsx! { rsx! {
PageLayout { nav_items,
header { class: "page-header mb-6", header { class: "page-header mb-6",
h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]", h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]",
"归档" "归档"
@ -93,7 +86,6 @@ pub fn Archives() -> Element {
ArchivesContent {} ArchivesContent {}
} }
} }
}
#[component] #[component]
fn ArchivesContent() -> Element { fn ArchivesContent() -> Element {

View File

@ -1,12 +1,9 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::api::posts::{list_published_posts, PostListResponse}; use crate::api::posts::{list_published_posts, PostListResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::components::post_card::PostCard; use crate::components::post_card::PostCard;
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
use crate::components::skeletons::home_skeleton::HomeSkeleton; use crate::components::skeletons::home_skeleton::HomeSkeleton;
use crate::router::Route;
const POSTS_PER_PAGE: i32 = 10; const POSTS_PER_PAGE: i32 = 10;
@ -17,17 +14,13 @@ pub fn Home() -> Element {
#[component] #[component]
pub fn HomePage(page: i32) -> Element { pub fn HomePage(page: i32) -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
let current_page = page.max(1); let current_page = page.max(1);
rsx! { rsx! {
PageLayout { nav_items,
HomeInfo {} HomeInfo {}
HomePosts { current_page } HomePosts { current_page }
} }
} }
}
#[component] #[component]
fn HomePosts(current_page: i32) -> Element { fn HomePosts(current_page: i32) -> Element {

View File

@ -1,8 +1,6 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::api::posts::{get_post_by_slug, SinglePostResponse}; use crate::api::posts::{get_post_by_slug, SinglePostResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::components::post::post_content::PostContent; use crate::components::post::post_content::PostContent;
use crate::components::post::post_cover::PostCover; use crate::components::post::post_cover::PostCover;
use crate::components::post::post_footer::PostFooter; use crate::components::post::post_footer::PostFooter;
@ -10,19 +8,13 @@ use crate::components::post::post_header::PostHeader;
use crate::components::post::post_toc::PostToc; use crate::components::post::post_toc::PostToc;
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
use crate::components::skeletons::post_detail_skeleton::PostDetailSkeleton; use crate::components::skeletons::post_detail_skeleton::PostDetailSkeleton;
use crate::router::Route;
#[component] #[component]
pub fn PostDetail(slug: String) -> Element { pub fn PostDetail(slug: String) -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
rsx! { rsx! {
PageLayout { nav_items,
PostDetailContent { slug: slug.clone() } PostDetailContent { slug: slug.clone() }
} }
} }
}
#[component] #[component]
fn PostDetailContent(slug: String) -> Element { fn PostDetailContent(slug: String) -> Element {

View File

@ -1,20 +1,15 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::api::posts::{search_posts, PostListResponse}; use crate::api::posts::{search_posts, PostListResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::components::post_card::PostCard; use crate::components::post_card::PostCard;
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
use crate::components::skeletons::search_skeleton::SearchSkeleton; use crate::components::skeletons::search_skeleton::SearchSkeleton;
use crate::router::Route;
#[component] #[component]
pub fn Search() -> Element { pub fn Search() -> Element {
let route = use_route::<Route>();
let mut query = use_signal(|| "".to_string()); let mut query = use_signal(|| "".to_string());
let mut search_res = use_signal(|| None::<Result<PostListResponse, ServerFnError>>); let mut search_res = use_signal(|| None::<Result<PostListResponse, ServerFnError>>);
let mut is_searching = use_signal(|| false); let mut is_searching = use_signal(|| false);
let nav_items = use_nav_items(route);
let mut on_search = move || { let mut on_search = move || {
let q = query().trim().to_string(); let q = query().trim().to_string();
if q.is_empty() { if q.is_empty() {
@ -30,7 +25,6 @@ pub fn Search() -> Element {
}; };
rsx! { rsx! {
PageLayout { nav_items,
header { class: "page-header mb-6", header { class: "page-header mb-6",
h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]", h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]",
"搜索" "搜索"
@ -72,4 +66,3 @@ pub fn Search() -> Element {
} }
} }
} }
}

View File

@ -1,20 +1,13 @@
use dioxus::prelude::*; use dioxus::prelude::*;
use crate::api::posts::{get_posts_by_tag, list_tags, PostListResponse, TagListResponse}; use crate::api::posts::{get_posts_by_tag, list_tags, PostListResponse, TagListResponse};
use crate::components::nav::use_nav_items;
use crate::components::page_layout::PageLayout;
use crate::components::post_card::PostCard; use crate::components::post_card::PostCard;
use crate::components::skeletons::delayed_skeleton::DelayedSkeleton; use crate::components::skeletons::delayed_skeleton::DelayedSkeleton;
use crate::components::skeletons::tags_skeleton::{TagsSkeleton, TagDetailSkeleton}; use crate::components::skeletons::tags_skeleton::{TagsSkeleton, TagDetailSkeleton};
use crate::router::Route;
#[component] #[component]
pub fn Tags() -> Element { pub fn Tags() -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
rsx! { rsx! {
PageLayout { nav_items,
header { class: "page-header mb-6", header { class: "page-header mb-6",
h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]", h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]",
"标签" "标签"
@ -23,7 +16,6 @@ pub fn Tags() -> Element {
TagsContent {} TagsContent {}
} }
} }
}
#[component] #[component]
fn TagsContent() -> Element { fn TagsContent() -> Element {
@ -80,11 +72,7 @@ fn TagsContent() -> Element {
#[component] #[component]
pub fn TagDetail(tag: String) -> Element { pub fn TagDetail(tag: String) -> Element {
let route = use_route::<Route>();
let nav_items = use_nav_items(route);
rsx! { rsx! {
PageLayout { nav_items,
header { class: "page-header mb-6", header { class: "page-header mb-6",
h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]", h1 { class: "text-[34px] font-bold text-gray-900 dark:text-[#dadadb]",
"{tag}" "{tag}"
@ -93,7 +81,6 @@ pub fn TagDetail(tag: String) -> Element {
TagDetailContent { tag: tag.clone() } TagDetailContent { tag: tag.clone() }
} }
} }
}
#[component] #[component]
fn TagDetailContent(tag: String) -> Element { fn TagDetailContent(tag: String) -> Element {