- 添加基础crate结构(erp-core, erp-common) - 实现核心模块trait和事件总线 - 配置Docker开发环境(PostgreSQL+Redis) - 添加Tauri桌面端基础框架 - 设置CI/CD工作流 - 编写项目协作规范文档(CLAUDE.md)
79 lines
2.2 KiB
Rust
79 lines
2.2 KiB
Rust
use axum::http::StatusCode;
|
|
use axum::response::{IntoResponse, Response};
|
|
use axum::Json;
|
|
use serde::Serialize;
|
|
|
|
/// 统一错误响应格式
|
|
#[derive(Debug, Serialize)]
|
|
pub struct ErrorResponse {
|
|
pub error: String,
|
|
pub message: String,
|
|
#[serde(skip_serializing_if = "Option::is_none")]
|
|
pub details: Option<serde_json::Value>,
|
|
}
|
|
|
|
/// 平台级错误类型
|
|
#[derive(Debug, thiserror::Error)]
|
|
pub enum AppError {
|
|
#[error("资源未找到: {0}")]
|
|
NotFound(String),
|
|
|
|
#[error("验证失败: {0}")]
|
|
Validation(String),
|
|
|
|
#[error("未授权")]
|
|
Unauthorized,
|
|
|
|
#[error("禁止访问: {0}")]
|
|
Forbidden(String),
|
|
|
|
#[error("冲突: {0}")]
|
|
Conflict(String),
|
|
|
|
#[error("内部错误: {0}")]
|
|
Internal(String),
|
|
}
|
|
|
|
impl IntoResponse for AppError {
|
|
fn into_response(self) -> Response {
|
|
let (status, message) = match &self {
|
|
AppError::NotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
|
|
AppError::Validation(_) => (StatusCode::BAD_REQUEST, self.to_string()),
|
|
AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "未授权".to_string()),
|
|
AppError::Forbidden(_) => (StatusCode::FORBIDDEN, self.to_string()),
|
|
AppError::Conflict(_) => (StatusCode::CONFLICT, self.to_string()),
|
|
AppError::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, "内部错误".to_string()),
|
|
};
|
|
|
|
let body = ErrorResponse {
|
|
error: status.canonical_reason().unwrap_or("Error").to_string(),
|
|
message,
|
|
details: None,
|
|
};
|
|
|
|
(status, Json(body)).into_response()
|
|
}
|
|
}
|
|
|
|
impl From<anyhow::Error> for AppError {
|
|
fn from(err: anyhow::Error) -> Self {
|
|
AppError::Internal(err.to_string())
|
|
}
|
|
}
|
|
|
|
impl From<sea_orm::DbErr> for AppError {
|
|
fn from(err: sea_orm::DbErr) -> Self {
|
|
match err {
|
|
sea_orm::DbErr::RecordNotFound(msg) => AppError::NotFound(msg),
|
|
sea_orm::DbErr::Query(sea_orm::RuntimeErr::SqlxError(e))
|
|
if e.to_string().contains("duplicate key") =>
|
|
{
|
|
AppError::Conflict("记录已存在".to_string())
|
|
}
|
|
_ => AppError::Internal(err.to_string()),
|
|
}
|
|
}
|
|
}
|
|
|
|
pub type AppResult<T> = Result<T, AppError>;
|