yggdrasil/api/posts/
delete.rs1use dioxus::prelude::*;
9
10#[cfg(feature = "server")]
11use super::helpers::get_current_admin_user;
12use super::types::CreatePostResponse;
13#[cfg(feature = "server")]
14use crate::api::error::AppError;
15#[cfg(feature = "server")]
16use crate::db::pool::get_conn;
17
18#[server(DeletePost, "/api")]
23pub async fn delete_post(post_id: i32) -> Result<CreatePostResponse, ServerFnError> {
24 let _user = get_current_admin_user().await?;
25
26 #[cfg(feature = "server")]
27 {
28 let mut client = get_conn().await.map_err(AppError::db_conn)?;
29 let tx = client.transaction().await.map_err(AppError::tx)?;
30
31 let slug_row = tx
33 .query_opt(
34 "SELECT slug FROM posts WHERE id = $1 AND deleted_at IS NULL FOR UPDATE",
35 &[&post_id],
36 )
37 .await
38 .map_err(AppError::query)?;
39
40 let Some(slug_row) = slug_row else {
41 return Ok(CreatePostResponse::err("文章不存在".to_string()));
42 };
43 let slug: String = slug_row.get(0);
44
45 let tags = super::helpers::fetch_post_tags(&tx, post_id).await?;
46
47 let result = tx
49 .execute(
50 "UPDATE posts SET deleted_at = NOW() WHERE id = $1 AND deleted_at IS NULL",
51 &[&post_id],
52 )
53 .await
54 .map_err(AppError::tx)?;
55
56 if result == 0 {
57 return Ok(CreatePostResponse::err("文章不存在".to_string()));
58 }
59
60 tx.commit().await.map_err(AppError::tx)?;
61
62 crate::cache::invalidate_for_post_write(std::slice::from_ref(&slug), &tags).await;
64
65 Ok(CreatePostResponse::ok(
66 "删除成功".to_string(),
67 post_id,
68 slug,
69 ))
70 }
71
72 #[cfg(not(feature = "server"))]
73 {
74 Ok(CreatePostResponse::err("server only".to_string()))
75 }
76}