feat(health): 添加文章修订历史查询 API — GET /health/articles/{id}/revisions
补全 ArticleRevision 实体的读取查询(之前仅有写入 save_revision), 新增 list_revisions service + handler + 路由,支持分页。
This commit is contained in:
@@ -144,6 +144,21 @@ impl ReviewArticleReq {
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 修订历史 DTOs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
|
||||
pub struct ArticleRevisionResp {
|
||||
pub id: Uuid,
|
||||
pub article_id: Uuid,
|
||||
pub revision_number: i32,
|
||||
pub title: String,
|
||||
pub summary: Option<String>,
|
||||
pub created_by: Option<Uuid>,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// 分类 DTOs
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
@@ -203,3 +203,29 @@ where
|
||||
article_service::increment_view_count(&state, ctx.tenant_id, id).await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct ListRevisionsQuery {
|
||||
pub page: Option<u64>,
|
||||
pub page_size: Option<u64>,
|
||||
}
|
||||
|
||||
/// 查询文章修订历史
|
||||
pub async fn list_revisions<S>(
|
||||
State(state): State<HealthState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(id): Path<uuid::Uuid>,
|
||||
Query(params): Query<ListRevisionsQuery>,
|
||||
) -> Result<Json<ApiResponse<PaginatedResponse<crate::dto::article_dto::ArticleRevisionResp>>>, AppError>
|
||||
where
|
||||
HealthState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "health.articles.list")?;
|
||||
let page = params.page.unwrap_or(1);
|
||||
let page_size = params.page_size.unwrap_or(20);
|
||||
let result = article_service::list_revisions(
|
||||
&state, ctx.tenant_id, id, page, page_size,
|
||||
).await?;
|
||||
Ok(Json(ApiResponse::ok(result)))
|
||||
}
|
||||
|
||||
@@ -433,6 +433,10 @@ impl HealthModule {
|
||||
"/health/articles/{id}/view",
|
||||
axum::routing::post(article_handler::view_article),
|
||||
)
|
||||
.route(
|
||||
"/health/articles/{id}/revisions",
|
||||
axum::routing::get(article_handler::list_revisions),
|
||||
)
|
||||
// 资讯分类
|
||||
.route(
|
||||
"/health/article-categories",
|
||||
|
||||
@@ -588,3 +588,54 @@ async fn save_revision(
|
||||
active.insert(&state.db).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn list_revisions(
|
||||
state: &HealthState,
|
||||
tenant_id: Uuid,
|
||||
article_id: Uuid,
|
||||
page: u64,
|
||||
page_size: u64,
|
||||
) -> HealthResult<PaginatedResponse<crate::dto::article_dto::ArticleRevisionResp>> {
|
||||
use crate::entity::article_revision;
|
||||
|
||||
let page = page.max(1);
|
||||
let page_size = page_size.clamp(1, 100);
|
||||
|
||||
let condition = article_revision::Column::ArticleId
|
||||
.eq(article_id)
|
||||
.and(article_revision::Column::TenantId.eq(tenant_id));
|
||||
|
||||
let total = article_revision::Entity::find()
|
||||
.filter(condition.clone())
|
||||
.count(&state.db)
|
||||
.await?;
|
||||
|
||||
let items = article_revision::Entity::find()
|
||||
.filter(condition)
|
||||
.order_by_desc(article_revision::Column::RevisionNumber)
|
||||
.offset(((page - 1) * page_size) as u64)
|
||||
.limit(page_size)
|
||||
.all(&state.db)
|
||||
.await?;
|
||||
|
||||
let data = items
|
||||
.into_iter()
|
||||
.map(|m| crate::dto::article_dto::ArticleRevisionResp {
|
||||
id: m.id,
|
||||
article_id: m.article_id,
|
||||
revision_number: m.revision_number,
|
||||
title: m.title,
|
||||
summary: m.summary,
|
||||
created_by: m.created_by,
|
||||
created_at: m.created_at,
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(PaginatedResponse {
|
||||
data,
|
||||
total,
|
||||
page,
|
||||
page_size,
|
||||
total_pages: ((total as f64) / (page_size as f64)).ceil() as u64,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user