1#[cfg(feature = "server")]
4use crate::api::error::ApiError;
5use crate::models::post::{Post, PostListItem, PostStats, PostStatus, Tag};
6
7#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
9pub struct CreatePostResponse {
10 pub success: bool,
12 pub message: String,
14 pub post_id: Option<i32>,
16 pub slug: Option<String>,
18}
19
20#[derive(Debug, Clone, Default, PartialEq, serde::Serialize, serde::Deserialize)]
22pub struct AdminPostQuery {
23 pub search: Option<String>,
25 pub status: Option<PostStatus>,
27 pub tag: Option<String>,
29}
30
31impl AdminPostQuery {
32 pub fn search(text: impl Into<String>) -> Self {
34 Self {
35 search: Some(text.into()),
36 ..Self::default()
37 }
38 }
39}
40
41#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
43pub enum BatchPostAction {
44 Publish,
46 Unpublish,
47 Trash,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
52pub struct BatchPostResult {
53 pub done: usize,
54 pub failed: usize,
55}
56
57#[cfg_attr(not(feature = "server"), allow(dead_code))]
60impl CreatePostResponse {
61 pub fn err(message: impl Into<String>) -> Self {
63 Self {
64 success: false,
65 message: message.into(),
66 post_id: None,
67 slug: None,
68 }
69 }
70
71 pub fn ok(message: impl Into<String>, post_id: i32, slug: impl Into<String>) -> Self {
73 Self {
74 success: true,
75 message: message.into(),
76 post_id: Some(post_id),
77 slug: Some(slug.into()),
78 }
79 }
80
81 pub fn ok_msg(message: impl Into<String>) -> Self {
83 Self {
84 success: true,
85 message: message.into(),
86 post_id: None,
87 slug: None,
88 }
89 }
90}
91
92#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
94pub struct PostListResponse {
95 pub posts: Vec<PostListItem>,
97 pub total: i64,
99}
100
101#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
103pub struct TagListResponse {
104 pub tags: Vec<Tag>,
106}
107
108#[cfg_attr(not(feature = "server"), allow(dead_code))]
111#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
112pub struct PostSuggestion {
113 pub slug: String,
115 pub title: String,
117 pub summary: Option<String>,
119 #[cfg_attr(
121 target_arch = "wasm32",
122 serde(
123 default,
124 deserialize_with = "crate::models::rfc3339::deserialize_option"
125 )
126 )]
127 pub published_at: Option<chrono::DateTime<chrono::Utc>>,
128 pub tags: Vec<String>,
130}
131
132#[cfg_attr(not(feature = "server"), allow(dead_code))]
134#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
135pub struct PostSuggestionResponse {
136 pub posts: Vec<PostSuggestion>,
138}
139
140#[cfg(feature = "server")]
142pub const SUGGESTION_LIMIT: i64 = 8;
143
144#[cfg_attr(not(feature = "server"), allow(dead_code))]
146#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
147pub struct PostOutline {
148 pub slug: String,
150 pub total: u32,
152 pub headings: Vec<String>,
154}
155
156#[cfg(feature = "server")]
158pub const OUTLINE_PREVIEW_LIMIT: usize = 6;
159
160#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
162pub struct PostStatsResponse {
163 pub stats: PostStats,
165}
166
167#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
169pub struct SinglePostResponse {
170 pub post: Option<Post>,
172}
173
174#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
176pub struct PublicPostResponse {
177 pub post: Option<crate::models::public_post::PublicPost>,
178}
179
180#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
182pub struct RebuildResult {
183 pub rebuilt: u64,
185 pub failed: u64,
187 pub errors: Vec<String>,
189 pub next_after_id: Option<i32>,
191}
192
193#[cfg(feature = "server")]
195pub(super) fn write_response(
196 result: Result<super::service::WriteOutcome, super::service::WriteError>,
197 message: &str,
198) -> Result<CreatePostResponse, ApiError> {
199 use super::service::WriteError;
200 match result {
201 Ok(value) => Ok(CreatePostResponse::ok(message, value.post_id, value.slug)),
202 Err(WriteError::Invalid(message)) => Ok(CreatePostResponse::err(message)),
203 Err(WriteError::Conflict(_)) => Ok(CreatePostResponse::err(
204 "文章已被修改,请重新读取后合并更改",
205 )),
206 Err(WriteError::Failed(error)) => Err(error.into()),
207 }
208}