Skip to main content

yggdrasil/components/comments/
pending_item.rs

1//! 待审核评论项组件
2//!
3//! 展示用户刚提交、尚未通过审核的评论占位项,
4//! 视觉上使用较低的透明度并标注"审核中"状态。
5
6use dioxus::prelude::*;
7
8use crate::components::comments::card::CommentCardShell;
9use crate::utils::comment_storage::{render_pending_content, PendingComment};
10use crate::utils::time::format_relative_time_iso;
11
12/// 待审核评论项组件。
13///
14/// Props:
15/// - `comment`:待审核评论数据
16/// - `post_id`:所属文章 ID(当前未使用,保留用于未来扩展)
17///
18/// 展示内容包括:作者头像/链接、基于创建时间动态计算的相对时间、审核中徽章、Markdown 渲染内容。
19/// 深度最大展示 6 层缩进,孤儿评论深度会被修正为 0。
20#[component]
21#[allow(unused_variables)]
22pub fn PendingCommentItem(comment: PendingComment, post_id: i32) -> Element {
23    // 孤儿评论(parent_id 为 None 但 depth > 0)按顶层展示
24    let depth = if comment.parent_id.is_none() && comment.depth > 0 {
25        0
26    } else {
27        comment.depth
28    };
29
30    let content_html = render_pending_content(&comment.content_md);
31    // 基于创建时间实时计算相对时间,避免"刚刚"永久显示。
32    let relative_time = format_relative_time_iso(&comment.created_at);
33
34    // 作者名展示为链接或普通文本
35    let author_element = match &comment.author_url {
36        Some(url) if !url.is_empty() => rsx! {
37            a {
38                href: "{url}",
39                rel: "nofollow noopener",
40                target: "_blank",
41                class: "font-semibold text-paper-primary hover:text-paper-accent transition-colors",
42                "{comment.author_name}"
43            }
44        },
45        _ => rsx! {
46            span { class: "font-semibold text-paper-primary", "{comment.author_name}" }
47        },
48    };
49
50    let status_badge = rsx! {
51        span { class: "inline-flex items-center px-1.5 py-0.5 rounded-full text-[10px] font-medium bg-amber-500/10 text-amber-600 dark:text-amber-400 border border-amber-500/20",
52            "审核中"
53        }
54    };
55
56    let timestamp = rsx! {
57        span {
58            class: "text-paper-tertiary",
59            title: "{comment.created_at}",
60            "{relative_time}"
61        }
62    };
63
64    rsx! {
65        CommentCardShell {
66            depth,
67            muted: true,
68            avatar_url: comment.avatar_url.clone(),
69            author_name: comment.author_name.clone(),
70            author_element,
71            author_badge: rsx! {},
72            timestamp,
73            status_badge,
74            content_html,
75        }
76    }
77}