feat: cut over rust web main shell

This commit is contained in:
lix-2026
2026-04-29 12:24:44 +08:00
parent 7965c6c107
commit 048fe28a4d
97 changed files with 9396 additions and 1263 deletions
@@ -0,0 +1,80 @@
//! MNOTE 搜索页面组件 (SSR)
//!
//! 提供搜索页面的服务器端渲染壳。
//! 由 `<body>` 外层包装、搜索契约 JSON 嵌入脚本由路由 handler 处理。
use leptos::prelude::*;
use crate::ssr::pages::layout::PageLayout;
/// MNOTE 搜索页面
///
/// 渲染搜索页面的 SSR 壳结构:
/// - `<main id="mnote-search-shell" data-island-host="react_search_palette">`
/// - 搜索标题区域
/// - 搜索岛占位区
#[component]
pub fn SearchPage(
/// 工作区 ID
#[prop(into)]
workspace_id: String,
/// 搜索查询
#[prop(into)]
search_query: String,
/// 侧栏页面树 HTML(可选)
#[prop(optional)]
sidebar_tree_html: Option<String>,
/// 工作区名称(可选)
#[prop(optional)]
workspace_name: Option<String>,
) -> impl IntoView {
view! {
<PageLayout current_nav="search" sidebar_tree_html={sidebar_tree_html.unwrap_or_default()} workspace_name={workspace_name.unwrap_or_default()}>
<main id="mnote-search-shell" data-island-host="react_search_palette">
<header class="search-header">
<h1>{"搜索"}</h1>
<p class="search-meta">
{format!("工作区: {}", workspace_id)}
</p>
<p class="search-query">
{if search_query.is_empty() {
"请输入关键词".to_string()
} else {
format!("查询: {}", search_query)
}}
</p>
</header>
<section id="mnote-search-island" data-react-island="search_palette"></section>
</main>
</PageLayout>
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::ssr::render_view;
#[test]
fn search_page_renders_correct_structure() {
let html = render_view(view! {
<SearchPage workspace_id="ws_demo" search_query="Rust" />
});
assert!(html.contains("mnote-search-shell"));
assert!(html.contains("data-island-host=\"react_search_palette\""));
assert!(html.contains("mnote-search-island"));
assert!(html.contains("data-react-island=\"search_palette\""));
assert!(html.contains("搜索"));
}
#[test]
fn search_page_contains_layout() {
let html = render_view(view! {
<SearchPage workspace_id="ws_demo" search_query="" />
});
assert!(html.contains("mnote-shell"));
assert!(html.contains("mnote-sidebar"));
assert!(html.contains("mnote-sidebar-brand"));
assert!(html.contains("mnote-sidebar-nav"));
assert!(html.contains("mnote-content"));
}
}