feat: initialize Nuanji (Warm Notes) project

- Base platform from base.git (ERP base: auth, core, config, message, workflow, plugin)
- Created erp-diary module skeleton (lib.rs, dto.rs, error.rs, event.rs, state.rs)
- Integrated erp-diary into workspace and erp-server
- Added DiaryModule registration in main.rs
- Added DiaryState FromRef in state.rs
- Diary routes mounted (empty routes, ready for implementation)
- Product design spec v1.2 preserved in docs/
- Implementation plan preserved in plans/

Cargo check: OK
Cargo test: OK (78+ base tests passing)
This commit is contained in:
iven
2026-05-31 20:52:19 +08:00
commit c539e6fd83
285 changed files with 59156 additions and 0 deletions

125
crates/erp-diary/src/dto.rs Normal file
View File

@@ -0,0 +1,125 @@
// erp-diary 数据传输对象 (DTO)
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
/// 日记心情枚举
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum Mood {
Happy,
Calm,
Sad,
Angry,
Thinking,
}
/// 天气枚举
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum Weather {
Sunny,
Cloudy,
Rainy,
Snowy,
Windy,
}
/// 创建日记请求
#[derive(Debug, Deserialize, ToSchema)]
pub struct CreateJournalReq {
pub title: String,
pub date: chrono::NaiveDate,
pub mood: Mood,
pub weather: Weather,
pub tags: Vec<String>,
pub is_private: bool,
pub class_id: Option<uuid::Uuid>,
pub assigned_topic_id: Option<uuid::Uuid>,
}
/// 更新日记请求
#[derive(Debug, Deserialize, ToSchema)]
pub struct UpdateJournalReq {
pub title: Option<String>,
pub mood: Option<Mood>,
pub weather: Option<Weather>,
pub tags: Option<Vec<String>>,
pub is_private: Option<bool>,
pub shared_to_class: Option<bool>,
pub version: i32,
}
/// 日记响应
#[derive(Debug, Serialize, ToSchema)]
pub struct JournalResp {
pub id: uuid::Uuid,
pub author_id: uuid::Uuid,
pub class_id: Option<uuid::Uuid>,
pub title: String,
pub date: chrono::NaiveDate,
pub mood: Mood,
pub weather: Weather,
pub tags: Vec<String>,
pub is_private: bool,
pub shared_to_class: bool,
pub version: i32,
pub created_at: chrono::DateTime<chrono::Utc>,
pub updated_at: chrono::DateTime<chrono::Utc>,
}
/// 创建班级请求
#[derive(Debug, Deserialize, ToSchema)]
pub struct CreateClassReq {
pub name: String,
pub school_name: Option<String>,
}
/// 加入班级请求
#[derive(Debug, Deserialize, ToSchema)]
pub struct JoinClassReq {
pub class_code: String,
}
/// 班级响应
#[derive(Debug, Serialize, ToSchema)]
pub struct ClassResp {
pub id: uuid::Uuid,
pub name: String,
pub school_name: Option<String>,
pub teacher_id: uuid::Uuid,
pub class_code: String,
pub member_count: i32,
pub is_active: bool,
}
/// 同步请求
#[derive(Debug, Deserialize, ToSchema)]
pub struct SyncReq {
pub last_sync_time: Option<chrono::DateTime<chrono::Utc>>,
pub changes: Vec<SyncChange>,
}
/// 同步变更条目
#[derive(Debug, Deserialize, ToSchema)]
pub enum SyncChange {
CreateJournal { data: serde_json::Value },
UpdateJournal { id: uuid::Uuid, version: i32, data: serde_json::Value },
DeleteJournal { id: uuid::Uuid, version: i32 },
}
/// 同步响应
#[derive(Debug, Serialize, ToSchema)]
pub struct SyncResp {
pub server_changes: Vec<serde_json::Value>,
pub conflicts: Vec<ConflictInfo>,
pub sync_time: chrono::DateTime<chrono::Utc>,
}
/// 冲突信息
#[derive(Debug, Serialize, ToSchema)]
pub struct ConflictInfo {
pub journal_id: uuid::Uuid,
pub local_version: i32,
pub server_version: i32,
}