1use chrono::{DateTime, Utc};
3#[cfg(feature = "server")]
4use rmcp::schemars;
5use serde::{Deserialize, Serialize};
6
7#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
8#[cfg_attr(feature = "server", derive(rmcp::schemars::JsonSchema))]
9#[serde(rename_all = "snake_case")]
10pub enum NoteKind {
11 #[default]
12 Moment,
13 Topic,
14}
15
16impl NoteKind {
17 pub fn as_str(self) -> &'static str {
18 match self {
19 Self::Moment => "moment",
20 Self::Topic => "topic",
21 }
22 }
23 pub fn label(self) -> &'static str {
24 match self {
25 Self::Moment => "随记",
26 Self::Topic => "主题笔记",
27 }
28 }
29}
30
31#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
32#[cfg_attr(feature = "server", derive(rmcp::schemars::JsonSchema))]
33pub struct NoteDraft {
34 pub id: Option<i32>,
35 pub expected_version: Option<i32>,
37 #[serde(default)]
38 pub kind: NoteKind,
39 #[serde(default)]
40 pub title: String,
41 pub content_md: String,
42 #[serde(default)]
43 pub tags: Vec<String>,
44 #[serde(default)]
45 pub notebook_ids: Vec<i32>,
46}
47
48#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
49pub struct Note {
50 pub id: i32,
51 pub slug: String,
52 pub version: i32,
53 pub kind: NoteKind,
54 pub title: String,
55 pub content_md: String,
56 pub content_html: String,
57 pub toc_html: String,
58 pub summary: String,
59 pub tags: Vec<String>,
60 pub created_at: DateTime<Utc>,
61 pub updated_at: DateTime<Utc>,
62 pub published_at: Option<DateTime<Utc>>,
63 pub published_version: Option<i32>,
65 pub knowledge_version: Option<i32>,
66 pub deleted_at: Option<DateTime<Utc>>,
67 pub notebook_ids: Vec<i32>,
68}
69
70impl Note {
71 pub fn display_title(&self) -> String {
72 if self.title.trim().is_empty() {
73 if self.summary.trim().is_empty() {
74 self.kind.label().to_string()
75 } else {
76 self.summary.chars().take(48).collect()
77 }
78 } else {
79 self.title.clone()
80 }
81 }
82 pub fn draft(&self) -> NoteDraft {
83 NoteDraft {
84 id: Some(self.id),
85 expected_version: Some(self.version),
86 kind: self.kind,
87 title: self.title.clone(),
88 content_md: self.content_md.clone(),
89 tags: self.tags.clone(),
90 notebook_ids: self.notebook_ids.clone(),
91 }
92 }
93}
94
95#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
96pub struct NotePage {
97 pub notes: Vec<Note>,
98 pub total: i64,
99}
100
101#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
102#[cfg_attr(feature = "server", derive(rmcp::schemars::JsonSchema))]
103pub struct NoteFilter {
104 #[serde(default)]
105 pub query: String,
106 pub kind: Option<NoteKind>,
107 pub notebook_id: Option<i32>,
108 #[serde(default)]
109 pub tag: String,
110 #[serde(default)]
111 pub trash: bool,
112 pub published: Option<bool>,
114 pub knowledge: Option<bool>,
115 #[serde(default)]
116 pub page: i32,
117}
118
119#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
120pub struct Notebook {
121 pub id: i32,
122 pub title: String,
123 pub description: String,
124 pub is_public: bool,
125 pub archived_at: Option<DateTime<Utc>>,
126 pub note_count: i64,
127 pub updated_at: DateTime<Utc>,
128}
129
130#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
131pub struct NotebookInput {
132 pub id: Option<i32>,
133 pub title: String,
134 pub description: String,
135 pub is_public: bool,
136}
137
138#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
139pub struct NoteRevision {
140 pub version: i32,
141 pub title: String,
142 pub created_at: DateTime<Utc>,
143}
144
145#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
146#[serde(rename_all = "snake_case")]
147pub enum NoteAction {
148 Publish,
149 Unpublish,
150 IncludeKnowledge,
151 ExcludeKnowledge,
152 Trash,
153 Restore,
154}