Skip to main content

yggdrasil/models/
note.rs

1//! 笔记、不可变版本和有序笔记本的共享模型。
2use 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    /// 更新必须携带读到的版本;过期写入被拒绝。
36    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    /// 仅管理接口填充。公开接口不暴露工作稿或知识库版本。
64    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    /// 仅管理接口应用;公开查询不能借此探测私密状态。
113    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}