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:
75
crates/erp-diary/src/error.rs
Normal file
75
crates/erp-diary/src/error.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
// erp-diary 错误类型
|
||||
|
||||
use axum::http::StatusCode;
|
||||
use axum::response::{IntoResponse, Response};
|
||||
use serde::Serialize;
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum DiaryError {
|
||||
#[error("日记未找到: {0}")]
|
||||
NotFound(String),
|
||||
|
||||
#[error("版本冲突: 本地版本 {local}, 服务端版本 {server}")]
|
||||
VersionConflict { local: i32, server: i32 },
|
||||
|
||||
#[error("班级码无效")]
|
||||
InvalidClassCode,
|
||||
|
||||
#[error("班级码已过期")]
|
||||
ClassCodeExpired,
|
||||
|
||||
#[error("班级码尝试次数过多,请 {lockout_minutes} 分钟后重试")]
|
||||
ClassCodeLocked { lockout_minutes: u32 },
|
||||
|
||||
#[error("无权限执行此操作")]
|
||||
Forbidden,
|
||||
|
||||
#[error("内容安全检查未通过")]
|
||||
ContentSafetyViolation,
|
||||
|
||||
#[error("同步失败: {0}")]
|
||||
SyncFailed(String),
|
||||
|
||||
#[error("{0}")]
|
||||
BadRequest(String),
|
||||
|
||||
#[error("内部错误: {0}")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ErrorBody {
|
||||
error: String,
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl IntoResponse for DiaryError {
|
||||
fn into_response(self) -> Response {
|
||||
let (status, message) = match &self {
|
||||
DiaryError::NotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
|
||||
DiaryError::VersionConflict { .. } => (StatusCode::CONFLICT, self.to_string()),
|
||||
DiaryError::InvalidClassCode | DiaryError::ClassCodeExpired => {
|
||||
(StatusCode::BAD_REQUEST, self.to_string())
|
||||
}
|
||||
DiaryError::ClassCodeLocked { .. } => (StatusCode::TOO_MANY_REQUESTS, self.to_string()),
|
||||
DiaryError::Forbidden => (StatusCode::FORBIDDEN, self.to_string()),
|
||||
DiaryError::ContentSafetyViolation => (StatusCode::BAD_REQUEST, self.to_string()),
|
||||
DiaryError::SyncFailed(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
|
||||
DiaryError::BadRequest(_) => (StatusCode::BAD_REQUEST, self.to_string()),
|
||||
DiaryError::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
|
||||
};
|
||||
|
||||
let body = ErrorBody {
|
||||
error: format!("diary.{}", status.as_u16()),
|
||||
message,
|
||||
};
|
||||
|
||||
(status, axum::Json(body)).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<sea_orm::DbErr> for DiaryError {
|
||||
fn from(err: sea_orm::DbErr) -> Self {
|
||||
DiaryError::Internal(err.to_string())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user