yggdrasil/src/components/admin_layout.rs
xfy 8b9c6aa83d 重构 admin 模块,新增共享组件和文章撰写页面
- 将 monolithic admin.rs 拆分为 admin/ 目录模块(dashboard、write)
- 新增 components 模块:Header、Footer、AdminLayout
- 新增 /admin/write 文章撰写页面,支持 Markdown 实时预览
- 添加 pulldown-cmark 依赖用于 Markdown 渲染
- .env 移出版本控制,新增 .env.example 模板
- Home、Archives、Tags、Login、Register 等页面适配新组件

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 16:13:18 +08:00

93 lines
2.9 KiB
Rust

use dioxus::prelude::*;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen::JsCast;
use crate::api::auth::{get_current_user, logout};
use crate::components::header::{Header, NavItemConfig};
use crate::components::footer::Footer;
use crate::router::Route;
#[component]
pub fn AdminLayout(children: Element) -> Element {
let user_resource =
use_resource(|| async move { get_current_user().await.ok().and_then(|r| r.user) });
let navigator = dioxus::router::navigator();
let route = use_route::<Route>();
let admin_nav_items = vec![
NavItemConfig {
href: "/admin",
label: "仪表盘",
is_active: matches!(route, Route::AdminPage {}),
},
NavItemConfig {
href: "/admin/write",
label: "写文章",
is_active: matches!(route, Route::WritePage {}),
},
NavItemConfig {
href: "/",
label: "前台",
is_active: false,
},
];
let nav = navigator;
let logout_button = rsx! {
button {
class: "text-sm text-gray-600 dark:text-[#9b9c9d] hover:text-gray-900 dark:hover:text-[#dadadb] transition-colors",
onclick: move |_| {
let nav = nav;
spawn(async move {
let _ = logout().await;
#[cfg(target_arch = "wasm32")]
{
let cookie = "session=; path=/; max-age=0";
if let Some(window) = web_sys::window() {
if let Some(document) = window.document() {
let _ = document.dyn_into::<web_sys::HtmlDocument>()
.map(|d| d.set_cookie(cookie));
}
}
}
let _ = nav.push("/login");
});
},
"登出"
}
};
let user_data = user_resource.read().clone();
let should_redirect = matches!(user_data.as_ref(), Some(None));
use_effect(move || {
if should_redirect {
navigator.push("/login");
}
});
match user_data.as_ref() {
Some(Some(_user)) => {
rsx! {
div { class: "min-h-screen flex flex-col bg-white dark:bg-[#1d1e20]",
Header { nav_items: admin_nav_items, right_content: logout_button }
main { class: "flex-1 w-full max-w-5xl mx-auto px-6 py-8",
{children}
}
Footer {}
}
}
}
_ => {
rsx! {
div { class: "min-h-screen flex items-center justify-center bg-white dark:bg-[#1d1e20]",
p { class: "text-gray-600 dark:text-[#9b9c9d]", "加载中..." }
}
}
}
}
}