feat(router): wrap public routes in ErrorLayout with ErrorBoundary
This commit is contained in:
parent
b5a64f8dcf
commit
37e8f51fac
105
src/router.rs
105
src/router.rs
@ -29,35 +29,37 @@ use crate::theme::{use_theme_provider, ThemePreload};
|
|||||||
#[derive(Clone, Routable, Debug, PartialEq)]
|
#[derive(Clone, Routable, Debug, PartialEq)]
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
pub enum Route {
|
pub enum Route {
|
||||||
// 前台页面共享布局
|
// 前台页面共享布局,最外层嵌套错误边界布局以拦截报错
|
||||||
#[layout(FrontendLayout)]
|
#[layout(ErrorLayout)]
|
||||||
/// 首页
|
#[layout(FrontendLayout)]
|
||||||
#[route("/")]
|
/// 首页
|
||||||
Home {},
|
#[route("/")]
|
||||||
/// 首页分页
|
Home {},
|
||||||
#[route("/page/:page")]
|
/// 首页分页
|
||||||
HomePage { page: i32 },
|
#[route("/page/:page")]
|
||||||
/// 文章归档页
|
HomePage { page: i32 },
|
||||||
#[route("/archives")]
|
/// 文章归档页
|
||||||
Archives {},
|
#[route("/archives")]
|
||||||
/// 标签列表页
|
Archives {},
|
||||||
#[route("/tags")]
|
/// 标签列表页
|
||||||
Tags {},
|
#[route("/tags")]
|
||||||
/// 单个标签下的文章列表
|
Tags {},
|
||||||
#[route("/tags/:tag")]
|
/// 单个标签下的文章列表
|
||||||
TagDetail { tag: String },
|
#[route("/tags/:tag")]
|
||||||
/// 文章详情页,按 slug 匹配
|
TagDetail { tag: String },
|
||||||
#[route("/post/:slug")]
|
/// 文章详情页,按 slug 匹配
|
||||||
PostDetail { slug: String },
|
#[route("/post/:slug")]
|
||||||
/// 搜索页
|
PostDetail { slug: String },
|
||||||
#[route("/search")]
|
/// 搜索页
|
||||||
Search {},
|
#[route("/search")]
|
||||||
/// 关于页面
|
Search {},
|
||||||
#[route("/about")]
|
/// 关于页面
|
||||||
About {},
|
#[route("/about")]
|
||||||
/// 404 兜底路由,匹配所有未命中路径
|
About {},
|
||||||
#[route("/:..segments")]
|
/// 404 兜底路由,匹配所有未命中路径
|
||||||
NotFound { segments: Vec<String> },
|
#[route("/:..segments")]
|
||||||
|
NotFound { segments: Vec<String> },
|
||||||
|
#[end_layout]
|
||||||
#[end_layout]
|
#[end_layout]
|
||||||
|
|
||||||
// 后台管理路由嵌套在 `/admin` 下
|
// 后台管理路由嵌套在 `/admin` 下
|
||||||
@ -131,3 +133,48 @@ pub fn AppRouter() -> Element {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[component]
|
||||||
|
fn ErrorLayout() -> Element {
|
||||||
|
rsx! {
|
||||||
|
ErrorBoundary {
|
||||||
|
handle_error: move |err: ErrorContext| {
|
||||||
|
// Commit the status code on the server side
|
||||||
|
#[cfg(feature = "server")]
|
||||||
|
{
|
||||||
|
if let Some(captured_error) = err.error() {
|
||||||
|
let _ = dioxus::fullstack::FullstackContext::commit_error_status(captured_error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the captured error to detect 404 vs 500
|
||||||
|
let mut is_404 = false;
|
||||||
|
if let Some(captured_error) = err.error() {
|
||||||
|
let err_str = format!("{:?}", captured_error);
|
||||||
|
if err_str.contains("NotFound") || err_str.contains("404") || err_str.contains("not found") {
|
||||||
|
is_404 = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if is_404 {
|
||||||
|
rsx! {
|
||||||
|
NotFound { segments: vec![] }
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rsx! {
|
||||||
|
div { class: "flex flex-col items-center justify-center text-center min-h-[50vh] px-6",
|
||||||
|
h1 { class: "text-2xl font-bold text-red-500 mb-4", "加载失败" }
|
||||||
|
p { class: "text-paper-secondary mb-6", "抱歉,加载页面时出现了一些错误,请稍后再试。" }
|
||||||
|
dioxus::router::components::Link {
|
||||||
|
class: "px-5 py-2.5 bg-paper-entry border border-paper-border rounded-lg text-sm font-medium text-paper-primary hover:border-paper-secondary transition-all",
|
||||||
|
to: Route::Home {},
|
||||||
|
"返回首页"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Outlet::<Route> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user