Skip to main content

yggdrasil/api/comments/
read.rs

1//! 前端评论读取接口:已审核评论列表。
2//!
3//! 结果按文章 id 缓存,Dioxus server function 注册在 `/api` 路径下。
4//! 仅在 `feature = "server"` 启用的服务端构建中查询数据库。
5
6use crate::api::comments::types::*;
7use dioxus::prelude::*;
8
9/// 获取指定文章的已审核评论列表。
10///
11/// 优先命中缓存;按 id 升序返回,便于前端构建嵌套树。
12#[server(GetComments, "/api")]
13pub async fn get_comments(post_id: i32) -> Result<CommentTreeResponse, ServerFnError> {
14    #[cfg(feature = "server")]
15    {
16        use crate::api::comments::helpers::row_to_public_comment;
17        use crate::api::error::AppError;
18        use crate::cache;
19        use crate::db::pool::get_conn;
20
21        if let Some(cached) = cache::get_comments_by_post(post_id).await {
22            let count = cached.len() as i64;
23            return Ok(CommentTreeResponse {
24                comments: cached,
25                count,
26            });
27        }
28
29        let client = get_conn().await.map_err(AppError::db_conn)?;
30
31        let rows = client
32            .query(
33                "SELECT c.id, c.parent_id, c.depth, c.author_name, c.author_email, c.author_url, c.content_html, c.created_at, \
34                        c.user_id, u.display_name AS user_display_name, u.avatar_url AS user_avatar \
35                 FROM comments c \
36                 LEFT JOIN users u ON c.user_id = u.id \
37                 WHERE c.post_id = $1 AND c.status = 'approved' AND c.deleted_at IS NULL \
38                   AND EXISTS (SELECT 1 FROM posts p WHERE p.id = $1 AND p.status = 'published' AND p.deleted_at IS NULL) \
39                 ORDER BY c.id ASC \
40                 LIMIT 200",
41                &[&post_id],
42            )
43            .await
44            .map_err(AppError::query)?;
45
46        let comments: Vec<_> = rows.iter().map(row_to_public_comment).collect();
47        let count = comments.len() as i64;
48
49        cache::set_comments_by_post(post_id, comments.clone()).await;
50
51        Ok(CommentTreeResponse { comments, count })
52    }
53    #[cfg(not(feature = "server"))]
54    unreachable!()
55}