Skip to main content

yggdrasil/components/post/
post_cover.rs

1//! 文章封面组件
2//!
3//! 在文章详情页渲染封面大图,使用 blur-up 双层结构与 lightbox.js 灯箱。
4//! 封面为单张(data-single),不参与正文图集切换。
5
6use dioxus::prelude::*;
7
8/// 文章封面组件。
9///
10/// Props:
11/// - `src`:封面原图 URL
12///
13/// 渲染 `.blur-img` 结构,与正文图片一致;`data-single="true"` 标记为单张,
14/// 由 `lightbox.js` 接管点击放大(原地缩放飞出 + 原图展示)。
15/// 服务端读取真实尺寸写入 `--ar`,确保占位期间维持正确宽高比。
16#[component]
17pub fn PostCover(src: String) -> Element {
18    // SSR 时读真实尺寸算 --ar;WASM 端不读(HTML 已在 SSR 写入)。
19    let ar_style = {
20        #[cfg_attr(not(feature = "server"), allow(unused_mut))]
21        let mut s = String::new();
22        #[cfg(feature = "server")]
23        {
24            if let Some(rel) = src
25                .strip_prefix("/uploads/")
26                .map(|p| p.split('?').next().unwrap_or(p))
27            {
28                if let Some((w, h)) = crate::api::image::get_image_dimensions(rel) {
29                    // CSS aspect-ratio 用斜杠分隔(width / height)
30                    s = format!("--ar:{} / {};", w, h);
31                }
32            }
33        }
34        s
35    };
36
37    // 占位图 ?w=20,展示图 ?w=1200;灯箱原图由 lightbox.js 去 query 得到。
38    let placeholder_src = if src.contains('?') {
39        format!("{}&w=20", src.split('?').next().unwrap_or(&src))
40    } else {
41        format!("{}?w=20", src)
42    };
43    let full_src = if src.contains('?') {
44        format!("{}&w=1200", src.split('?').next().unwrap_or(&src))
45    } else {
46        format!("{}?w=1200", src)
47    };
48
49    rsx! {
50        figure { class: "entry-cover",
51            span {
52                class: "blur-img entry-cover-blur lightbox-single",
53                style: "{ar_style}",
54                img {
55                    class: "blur-img-placeholder",
56                    src: "{placeholder_src}",
57                    alt: "封面图片",
58                }
59                img {
60                    class: "blur-img-full",
61                    "data-src": "{full_src}",
62                    alt: "封面图片",
63                }
64            }
65        }
66    }
67}