Skip to main content

pickcat_api_collection/dto/
topic.rs

1//! 主题与内容 DTO。
2
3use serde::{Deserialize, Serialize};
4
5use super::user::{PageInfoDTO, TopicAuthorDTO, UserSubjectInfoDTO, UserSubjectTagDTO};
6
7/// 主题列表项;与用户主页的主题列表项是同一结构。
8pub type TopicListItemDTO = UserSubjectInfoDTO;
9
10/// `GET /api/v1/topic-recommendations`:主题列表项额外带 `reason`。
11#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct RecommendedTopicDTO {
13    #[serde(flatten)]
14    pub topic: UserSubjectInfoDTO,
15    /// 推荐原因,如 `PINNED` / `TRENDING`。
16    pub reason: String,
17}
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(rename_all = "camelCase")]
21pub struct TopicRecommendationsDTO {
22    pub strategy: String,
23    pub items: Vec<RecommendedTopicDTO>,
24    pub page_info: PageInfoDTO,
25}
26
27// ---------------------------------------------------------------------------
28// 楼层
29// ---------------------------------------------------------------------------
30
31#[derive(Debug, Clone, Serialize, Deserialize)]
32#[serde(rename_all = "camelCase")]
33pub struct PostViewerCapabilitiesDTO {
34    #[serde(default)]
35    pub can_pin: bool,
36    pub can_edit: bool,
37    pub can_like: bool,
38    pub can_bookmark: bool,
39    pub can_report: bool,
40    pub can_select_answer: bool,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
44#[serde(rename_all = "camelCase")]
45pub struct PostViewerStateDTO {
46    pub liked: bool,
47    pub bookmark_id: Option<String>,
48    pub selected_answer: bool,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
52#[serde(rename_all = "camelCase")]
53pub struct TopicPostDTO {
54    pub id: String,
55    pub topic_id: String,
56    pub post_number: u64,
57    pub reply_to_post_number: Option<u64>,
58    pub deleted: bool,
59    pub children: Vec<TopicPostDTO>,
60    pub current_revision: u64,
61    pub like_count: u64,
62    pub pinned: bool,
63    pub cooked_html: String,
64    pub author: TopicAuthorDTO,
65    pub created_at: String,
66    pub edited_at: Option<String>,
67    pub viewer_capabilities: PostViewerCapabilitiesDTO,
68    pub viewer_state: PostViewerStateDTO,
69}
70
71// ---------------------------------------------------------------------------
72// 主题详情
73// ---------------------------------------------------------------------------
74
75#[derive(Debug, Clone, Serialize, Deserialize)]
76#[serde(rename_all = "camelCase")]
77pub struct TopicViewerCapabilitiesDTO {
78    pub can_edit: bool,
79    pub can_reply: bool,
80    pub can_delete: bool,
81    pub can_bookmark: bool,
82    pub can_close: bool,
83    pub can_reopen: bool,
84    #[serde(default)]
85    pub can_unselect_answer: bool,
86    #[serde(default)]
87    pub can_clear_duplicate: bool,
88    #[serde(default)]
89    pub can_mark_duplicate: bool,
90    pub can_pin_globally: bool,
91    #[serde(default)]
92    pub can_unpin: bool,
93    pub pinnable_tag_ids: Vec<String>,
94}
95
96#[derive(Debug, Clone, Serialize, Deserialize)]
97#[serde(rename_all = "camelCase")]
98pub struct TopicViewerStateDTO {
99    pub bookmark_id: Option<String>,
100}
101
102/// 主题所属合集(`collection` 字段)。
103#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct TopicCollectionDTO {
105    pub id: String,
106    pub name: String,
107}
108
109#[derive(Debug, Clone, Serialize, Deserialize)]
110#[serde(rename_all = "camelCase")]
111pub struct TopicDetailDTO {
112    pub id: String,
113    pub title: String,
114    pub kind: String,
115    pub author: TopicAuthorDTO,
116    pub tags: Vec<UserSubjectTagDTO>,
117    pub reply_count: u64,
118    pub view_count: u64,
119    /// 详情响应可能省略计数(未登录或无权限时)。
120    pub like_count: Option<u64>,
121    pub bookmark_count: Option<u64>,
122    pub collection: Option<TopicCollectionDTO>,
123    pub closed_at: Option<String>,
124    /// 关闭操作人;文档标注为 DateTime/String,实际类型未验证。
125    pub closed_by: Option<serde_json::Value>,
126    pub pinned: bool,
127    pub pinned_globally: bool,
128    pub pinned_tag_id: Option<String>,
129    pub pinned_at: Option<String>,
130    pub pinned_until: Option<String>,
131    pub last_activity_at: String,
132    pub created_at: String,
133    pub edited_at: Option<String>,
134    pub updated_at: String,
135    pub first_post: TopicPostDTO,
136    pub replies_truncated: bool,
137    /// 主题事件流,结构未文档化。
138    pub events: Vec<serde_json::Value>,
139    pub events_truncated: bool,
140    pub viewer_capabilities: TopicViewerCapabilitiesDTO,
141    pub viewer_state: TopicViewerStateDTO,
142}
143
144// ---------------------------------------------------------------------------
145// 发布主题 / 回帖
146// ---------------------------------------------------------------------------
147
148/// 发布主题首楼(`POST /api/v1/posts`)。
149#[derive(Debug, Clone, Serialize, Deserialize)]
150#[serde(rename_all = "camelCase")]
151pub struct CreateTopicDTO {
152    pub title: String,
153    pub markdown: String,
154    pub kind: String,
155    pub tag_ids: Vec<String>,
156}
157
158/// 发布回帖(`POST /api/v1/posts`)。`reply_to_post_number` 用于楼中楼。
159#[derive(Debug, Clone, Serialize, Deserialize)]
160#[serde(rename_all = "camelCase")]
161pub struct CreateReplyDTO {
162    pub topic_id: String,
163    pub markdown: String,
164    #[serde(skip_serializing_if = "Option::is_none")]
165    pub reply_to_post_number: Option<u64>,
166}
167
168/// `POST /api/v1/posts` 的 202 响应(异步审核受理)。
169#[derive(Debug, Clone, Serialize, Deserialize)]
170#[serde(rename_all = "camelCase")]
171pub struct CreatePostResponseDTO {
172    pub submission_id: String,
173    pub topic_id: String,
174    pub post_id: String,
175    pub status: String,
176}
177
178// ---------------------------------------------------------------------------
179// 投稿审核
180// ---------------------------------------------------------------------------
181
182#[derive(Debug, Clone, Serialize, Deserialize)]
183#[serde(rename_all = "camelCase")]
184pub struct PostSubmissionDTO {
185    pub id: String,
186    pub status: String,
187    pub content_role: String,
188    /// 提交内容原样回显,随 `content_role` 变化,结构未固定。
189    pub request: serde_json::Value,
190    pub risk_level: Option<String>,
191    pub topic_id: String,
192    pub post_id: String,
193    pub post_number: u64,
194    pub base_revision: Option<String>,
195    pub created_at: String,
196    pub updated_at: String,
197}