- 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)
76 lines
2.3 KiB
Rust
76 lines
2.3 KiB
Rust
// 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())
|
|
}
|
|
}
|