From 9c3f2242bab2f33915ca3ca727f4d1071a327232 Mon Sep 17 00:00:00 2001 From: xfy Date: Wed, 8 Jul 2026 16:40:32 +0800 Subject: [PATCH] feat(stats): add trash count to PostStats for posts page badge MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为合并回收站到 /admin/posts 的 tab 设计铺路:PostStats 新增 trash 字段, 统计 deleted_at IS NOT NULL 的文章数,供文章列表页「回收站」tab 角标使用。 - stats.rs: 条件聚合查询增加 trash 列,server/非 server 构造同步补字段 - models/post.rs: PostStats 加 pub trash: i64 - cache.rs: post_stats_cache_roundtrip 测试 fixture 补 trash 字段 --- src/api/posts/stats.rs | 13 ++++++++----- src/cache.rs | 1 + src/models/post.rs | 2 ++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/api/posts/stats.rs b/src/api/posts/stats.rs index dbf90ed..a2b612b 100644 --- a/src/api/posts/stats.rs +++ b/src/api/posts/stats.rs @@ -1,7 +1,7 @@ //! 文章统计接口。 //! -//! 返回文章总数、草稿数与已发布数,供管理后台仪表盘使用,结果缓存。 -//! Dioxus server function,注册在 `/api` 路径下。 +//! 返回文章总数、草稿数、已发布数与回收站(软删除)数量,供管理后台仪表盘与 +//! 文章列表页使用,结果缓存。Dioxus server function,注册在 `/api` 路径下。 //! 仅在 `feature = "server"` 启用的服务端构建中查询数据库。 use dioxus::prelude::*; @@ -19,7 +19,7 @@ use crate::models::post::PostStats; /// 获取文章统计信息。 /// /// 需要 admin 权限;优先命中缓存,未命中时通过单次条件聚合查询同时统计 -/// 未删除文章总数、草稿数与已发布数。 +/// 未删除文章总数、草稿数、已发布数与回收站(软删除)数量。 #[server(GetPostStats, "/api")] pub async fn get_post_stats() -> Result { let _user = get_current_admin_user().await?; @@ -32,13 +32,14 @@ pub async fn get_post_stats() -> Result { let client = get_conn().await.map_err(AppError::db_conn)?; - // 通过单次条件聚合查询同时统计总数、草稿数与已发布数。 + // 通过单次条件聚合查询同时统计总数、草稿数、已发布数与回收站数量。 let row = client .query_one( "SELECT COUNT(*) FILTER (WHERE deleted_at IS NULL) AS total, COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'draft') AS drafts, - COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'published') AS published + COUNT(*) FILTER (WHERE deleted_at IS NULL AND status = 'published') AS published, + COUNT(*) FILTER (WHERE deleted_at IS NOT NULL) AS trash FROM posts", &[], ) @@ -49,6 +50,7 @@ pub async fn get_post_stats() -> Result { total: row.get("total"), drafts: row.get("drafts"), published: row.get("published"), + trash: row.get("trash"), }; crate::cache::set_post_stats(stats.clone()).await; Ok(PostStatsResponse { stats }) @@ -61,6 +63,7 @@ pub async fn get_post_stats() -> Result { total: 0, drafts: 0, published: 0, + trash: 0, }, }) } diff --git a/src/cache.rs b/src/cache.rs index 93e2b9a..3f141c8 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -736,6 +736,7 @@ mod tests { total: 10, drafts: 3, published: 7, + trash: 2, }; set_post_stats(stats.clone()).await; diff --git a/src/models/post.rs b/src/models/post.rs index a7d9eb3..33e1ed2 100644 --- a/src/models/post.rs +++ b/src/models/post.rs @@ -187,6 +187,8 @@ pub struct PostStats { pub drafts: i64, /// 已发布数量。 pub published: i64, + /// 回收站(软删除)数量。 + pub trash: i64, } #[cfg(test)]