骨架屏在两条渲染路径都被高度链断裂卡住,内容只占页面 40-50%, 底部大片空白。 根因:高度链在两处父容器断裂,导致骨架屏无法引用到确定高度: 1. 未登录态(admin_layout):骨架屏被包在 div.p-10.animate-pulse, 该 div 是普通块级元素,无 flex-1 不撑满 main、非 flex 容器使 骨架屏 flex-1 无效、无 h-full。SSR 初始态走这条。 2. 登录态(write.rs 覆盖层):absolute inset-0 虽撑满,但非 flex 容器,骨架屏 flex-1 无意义;改 h-full 又遇 height:100% 在 非显式高度父容器下解析不可靠的经典坑。 修复:统一让两条路径的父容器都成为 flex flex-col,骨架屏根用 flex-1(比 height:100% 可靠,不依赖父显式 height): - admin_layout 包裹层: p-10.animate-pulse → flex-1.min-h-0. flex.flex-col.animate-pulse(去掉对 write 不合适的 p-10, 非 write 页面 padding 由 main_class 自带) - write.rs 覆盖层: absolute inset-0 → absolute inset-0 flex flex-col - write_skeleton 根: h-full → flex-1
82 lines
4.2 KiB
Rust
82 lines
4.2 KiB
Rust
//! 文章编辑器页骨架屏
|
||
//!
|
||
//! 在写文章/编辑文章页面加载时展示,镜像 Write 页面的左右两栏结构:
|
||
//! 左栏(标题+摘要+编辑器) + 右栏(链接/标签/封面) + 底部操作栏。
|
||
|
||
use crate::components::skeletons::atoms::*;
|
||
use dioxus::prelude::*;
|
||
|
||
/// 文章编辑器页骨架屏组件。
|
||
///
|
||
/// 镜像 Write 页面的左右两栏布局:左栏主写作区(标题、摘要、编辑器),
|
||
/// 右栏侧边栏(链接、标签、封面图),底部贴底操作栏。
|
||
#[component]
|
||
pub fn WriteSkeleton() -> Element {
|
||
rsx! {
|
||
// 根:父层是 flex 容器(write.rs 覆盖层 / admin_layout 包裹层均为 flex flex-col),
|
||
// 用 flex-1 撑满父层高度(比 height:100% 更可靠,不依赖父显式 height)。
|
||
div { class: "relative flex-1 flex flex-col min-h-0 overflow-hidden",
|
||
// 两栏容器:与真实页面一致,左 flex-1 + 右 w-80
|
||
div { class: "flex-1 min-h-0 flex",
|
||
// 左栏(主写作区)
|
||
div { class: "flex-1 min-w-0 min-h-0 overflow-y-auto px-6 py-8 flex flex-col",
|
||
// 标题输入
|
||
SkeletonBox { class: "h-10 w-3/4 rounded-lg" }
|
||
// 摘要
|
||
SkeletonBox { class: "h-5 w-full rounded mt-6" }
|
||
|
||
// 编辑器区域:flex-1 撑满左栏剩余高度
|
||
div { class: "flex-1 min-h-[400px] flex flex-col my-4",
|
||
div { class: "flex-1 min-h-0 w-full border border-[var(--color-paper-border)] rounded-3xl overflow-hidden bg-[var(--color-paper-entry)] shadow-sm p-4",
|
||
// 工具栏
|
||
div { class: "flex gap-2 pb-3 border-b border-[var(--color-paper-border)]",
|
||
for _ in 0..8 {
|
||
SkeletonBox { class: "w-8 h-8 rounded" }
|
||
}
|
||
}
|
||
// 正文占位行
|
||
div { class: "space-y-3 pt-4",
|
||
SkeletonBox { class: "h-4 w-[90%] rounded" }
|
||
SkeletonBox { class: "h-4 w-full rounded" }
|
||
SkeletonBox { class: "h-4 w-[85%] rounded" }
|
||
SkeletonBox { class: "h-4 w-[95%] rounded" }
|
||
SkeletonBox { class: "h-4 w-[60%] rounded" }
|
||
SkeletonBox { class: "h-4 w-full rounded" }
|
||
SkeletonBox { class: "h-4 w-[75%] rounded" }
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 右栏(侧边栏):w-80 border-l,分节式
|
||
div { class: "w-80 flex-shrink-0 min-h-0 overflow-y-auto border-l border-[var(--color-paper-border)] flex flex-col",
|
||
// 链接节
|
||
div { class: "p-6 border-b border-[var(--color-paper-border)]",
|
||
SkeletonBox { class: "h-3 w-10 rounded mb-3" }
|
||
SkeletonBox { class: "h-8 w-full rounded-xl" }
|
||
}
|
||
// 标签节
|
||
div { class: "p-6 border-b border-[var(--color-paper-border)]",
|
||
SkeletonBox { class: "h-3 w-10 rounded mb-3" }
|
||
SkeletonBox { class: "h-8 w-full rounded-xl" }
|
||
}
|
||
// 封面图节
|
||
div { class: "p-6",
|
||
SkeletonBox { class: "h-3 w-12 rounded mb-3" }
|
||
SkeletonBox { class: "h-14 w-full rounded-2xl" }
|
||
}
|
||
}
|
||
}
|
||
|
||
// 底部操作栏:与真实页面 px-6 py-4 border-t 一致
|
||
div { class: "flex-shrink-0 px-6 py-4 flex items-center gap-4 border-t border-[var(--color-paper-border)]",
|
||
SkeletonBox { class: "h-9 w-[56px] rounded-full" }
|
||
div { class: "w-px h-5 bg-[var(--color-paper-border)]" }
|
||
SkeletonBox { class: "h-9 w-[96px] rounded-full" }
|
||
div { class: "w-px h-5 bg-[var(--color-paper-border)]" }
|
||
SkeletonBox { class: "h-9 w-[72px] rounded-full" }
|
||
}
|
||
}
|
||
}
|
||
}
|