fix(write): 元数据行移至封面上方 + 编辑器撑满修复

布局调整:
- 元数据行(Slug/标签)从封面图下方移到上方,顺序变为
  标题 → 摘要 → 元数据行 → 封面图 → 编辑器

- 滚动主体容器补 flex flex-col:此前 overflow-y-auto 容器内
  子项的 flex-1 失效,导致编辑器只剩 min-h 不撑满。
  加 flex flex-col 后,flex-1 编辑器在窗口够高时正常填充剩余空间。
This commit is contained in:
xfy 2026-06-24 15:35:52 +08:00
parent 198a9b292a
commit 66d29eaa62

View File

@ -17,10 +17,10 @@ use crate::api::posts::{
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use crate::tiptap_bridge::{consume_upload_event, upload_image_file, EditorHandle}; use crate::tiptap_bridge::{consume_upload_event, upload_image_file, EditorHandle};
// 共享上传状态类型两端都编译rsx 在 server SSR 时也要渲染这些结构)。 // 共享上传状态类型两端都编译rsx 在 server SSR 时也要渲染这些结构)。
use crate::tiptap_bridge::{UploadErrorEntry, UploadsInFlight};
use crate::components::write_skeleton::WriteSkeleton; use crate::components::write_skeleton::WriteSkeleton;
use crate::models::post::Post; use crate::models::post::Post;
use crate::router::Route; use crate::router::Route;
use crate::tiptap_bridge::{UploadErrorEntry, UploadsInFlight};
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
use wasm_bindgen::closure::Closure; use wasm_bindgen::closure::Closure;
// 封面图上传:从 Dioxus 事件拿底层 web_sys::File以及 paste 事件的原始 web 事件。 // 封面图上传:从 Dioxus 事件拿底层 web_sys::File以及 paste 事件的原始 web 事件。
@ -197,13 +197,8 @@ fn write_editor(post_id: Option<i32>) -> Element {
} }
editor_content_set.set(true); editor_content_set.set(true);
} }
let handle = EditorHandle::new( let handle =
inst, EditorHandle::new(inst, on_update, on_image_upload, on_ready, on_upload_event);
on_update,
on_image_upload,
on_ready,
on_upload_event,
);
editor.set(Some(handle)); editor.set(Some(handle));
} }
Ok(None) => { Ok(None) => {
@ -259,9 +254,15 @@ fn write_editor(post_id: Option<i32>) -> Element {
let in_flight = uploads_in_flight.read(); let in_flight = uploads_in_flight.read();
if in_flight.uploading > 0 || in_flight.error > 0 { if in_flight.uploading > 0 || in_flight.error > 0 {
let msg = if in_flight.uploading > 0 { let msg = if in_flight.uploading > 0 {
format!("{} 张图片正在上传,请等待完成后再保存", in_flight.uploading) format!(
"有 {} 张图片正在上传,请等待完成后再保存",
in_flight.uploading
)
} else { } else {
format!("{} 张图片上传失败,请移除或重试后再保存", in_flight.error) format!(
"有 {} 张图片上传失败,请移除或重试后再保存",
in_flight.error
)
}; };
error.set(Some(msg)); error.set(Some(msg));
return; return;
@ -429,7 +430,9 @@ fn write_editor(post_id: Option<i32>) -> Element {
// 可滚动主体:元信息 + 编辑器 + 内联错误提示。 // 可滚动主体:元信息 + 编辑器 + 内联错误提示。
// 底部操作栏留在此容器外(固定吸底),保证保存/状态按钮始终可见。 // 底部操作栏留在此容器外(固定吸底),保证保存/状态按钮始终可见。
div { class: "flex-1 min-h-0 overflow-y-auto", // flex flex-col让内部 flex-1 编辑器能撑满剩余高度;
// overflow-y-auto内容超出时滚动min-h-0 允许 flex 子项收缩触发滚动)。
div { class: "flex-1 min-h-0 overflow-y-auto flex flex-col",
// 顶部元信息区域 - 固定高度,不滚动 // 顶部元信息区域 - 固定高度,不滚动
div { class: "flex-shrink-0 space-y-5 pt-8", div { class: "flex-shrink-0 space-y-5 pt-8",
// 标题区域 - 大字号无框输入 // 标题区域 - 大字号无框输入
@ -444,13 +447,39 @@ fn write_editor(post_id: Option<i32>) -> Element {
// 摘要 // 摘要
textarea { textarea {
class: "w-full text-base bg-transparent text-[var(--color-paper-secondary)] placeholder-[var(--color-paper-tertiary)] focus:outline-none resize-none leading-relaxed", class: "w-full text-base bg-transparent text-[var(--color-paper-secondary)] placeholder-[var(--color-paper-tertiary)] focus:outline-none resize-none leading-relaxed mb-0",
placeholder: "摘要(留空则自动生成)", placeholder: "摘要(留空则自动生成)",
rows: "2", rows: "2",
value: "{summary}", value: "{summary}",
oninput: move |evt| summary.set(evt.value()), oninput: move |evt| summary.set(evt.value()),
} }
// 元数据行 - 紧凑精致
div { class: "flex flex-wrap items-end gap-x-8 gap-y-4 text-sm",
div { class: "flex-1 min-w-[140px]",
label { class: "{META_LABEL_CLASS}",
"Slug"
}
input {
class: "{META_INPUT_CLASS}",
placeholder: "自动生成",
value: "{slug}",
oninput: move |evt| slug.set(evt.value()),
}
}
div { class: "flex-1 min-w-[140px]",
label { class: "{META_LABEL_CLASS}",
"标签"
}
input {
class: "{META_INPUT_CLASS}",
placeholder: "逗号分隔",
value: "{tags}",
oninput: move |evt| tags.set(evt.value()),
}
}
}
// 封面图上传区:空态矮横条(不挤压编辑器),有图时展开 16:9 预览。 // 封面图上传区:空态矮横条(不挤压编辑器),有图时展开 16:9 预览。
// 容器统一绑定拖拽与粘贴事件;内部按 cover_image / cover_uploading 切换空态、上传中、预览。 // 容器统一绑定拖拽与粘贴事件;内部按 cover_image / cover_uploading 切换空态、上传中、预览。
div { div {
@ -691,32 +720,6 @@ fn write_editor(post_id: Option<i32>) -> Element {
} }
} }
} }
// 元数据行 - 紧凑精致
div { class: "flex flex-wrap items-end gap-x-8 gap-y-4 text-sm",
div { class: "flex-1 min-w-[140px]",
label { class: "{META_LABEL_CLASS}",
"Slug"
}
input {
class: "{META_INPUT_CLASS}",
placeholder: "自动生成",
value: "{slug}",
oninput: move |evt| slug.set(evt.value()),
}
}
div { class: "flex-1 min-w-[140px]",
label { class: "{META_LABEL_CLASS}",
"标签"
}
input {
class: "{META_INPUT_CLASS}",
placeholder: "逗号分隔",
value: "{tags}",
oninput: move |evt| tags.set(evt.value()),
}
}
}
} }
// 编辑器区域 - 沾满剩余高度,但保证最小编辑空间。 // 编辑器区域 - 沾满剩余高度,但保证最小编辑空间。