use axum::extract::{Path, Query}; use axum::http::StatusCode; use axum::routing::get; use axum::{Extension, Json, Router}; use serde_json::{Value, json}; use sqlx::PgPool; use crate::model::MailListQuery; use crate::repository::MailRepository; type ApiError = (StatusCode, Json); #[derive(Clone)] pub struct MailRouteState { pub db: PgPool, } impl MailRouteState { pub fn new(db: PgPool) -> Self { Self { db } } } pub fn routes(db: PgPool) -> Router where S: Clone + Send + Sync + 'static, { Router::new() .route("/mail-api/messages", get(list_messages)) .route("/mail-api/messages/{id}", get(get_message)) .layer(Extension(MailRouteState::new(db))) } async fn list_messages( Extension(state): Extension, Query(query): Query, ) -> Result, ApiError> { let messages = MailRepository::list_recent(&state.db, query.limit.unwrap_or(20)) .await .map_err(api_internal_error)?; Ok(Json(json!({ "success": true, "messages": messages, }))) } async fn get_message( Extension(state): Extension, Path(id): Path, ) -> Result, ApiError> { let message = MailRepository::find(&state.db, id) .await .map_err(api_internal_error)? .ok_or_else(|| api_not_found("邮件记录不存在"))?; Ok(Json(json!({ "success": true, "message": message, }))) } fn api_not_found(message: impl Into) -> ApiError { ( StatusCode::NOT_FOUND, Json(json!({ "success": false, "message": message.into(), })), ) } fn api_internal_error(error: anyhow::Error) -> ApiError { eprintln!("mail 接口失败: {error}"); ( StatusCode::INTERNAL_SERVER_ERROR, Json(json!({ "success": false, "message": "mail 接口失败", })), ) }