fix(health): 添加 GET 单条轮播图端点 — 修复 Switch 切换 405

后端 /health/banners/{id} 路由只注册了 PUT/DELETE,缺少 GET handler。
前端 bannerApi.get(id) 调用时返回 405 Method Not Allowed,导致轮播图
状态切换失败。新增 banner_service::get_banner + banner_handler::get_banner
+ BannerNotFound 错误类型 + 路由注册。
This commit is contained in:
iven
2026-05-15 21:40:59 +08:00
parent 33febd2fbd
commit 50e3b16381
4 changed files with 40 additions and 2 deletions

View File

@@ -107,6 +107,9 @@ pub enum HealthError {
#[error("媒体文件夹不存在")]
MediaFolderNotFound,
#[error("轮播图不存在")]
BannerNotFound,
#[error("状态转换无效: {0}")]
InvalidStatusTransition(String),
@@ -157,7 +160,8 @@ impl From<HealthError> for AppError {
| HealthError::PatientAssignmentNotFound
| HealthError::HandoffLogNotFound
| HealthError::MediaNotFound
| HealthError::MediaFolderNotFound => AppError::NotFound(err.to_string()),
| HealthError::MediaFolderNotFound
| HealthError::BannerNotFound => AppError::NotFound(err.to_string()),
HealthError::ScheduleFull => AppError::Validation(err.to_string()),
HealthError::InvalidStatusTransition(s) => AppError::Validation(s),
HealthError::VersionMismatch => AppError::VersionMismatch,

View File

@@ -49,6 +49,21 @@ where
Ok(Json(ApiResponse::ok(result)))
}
/// GET /health/banners/{id} — 获取单个轮播图
pub async fn get_banner<S>(
State(state): State<HealthState>,
Extension(ctx): Extension<TenantContext>,
Path(id): Path<uuid::Uuid>,
) -> Result<Json<ApiResponse<BannerResp>>, AppError>
where
HealthState: FromRef<S>,
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "health.banners.list")?;
let result = banner_service::get_banner(&state, ctx.tenant_id, id).await?;
Ok(Json(ApiResponse::ok(result)))
}
/// POST /health/banners — 创建轮播图
pub async fn create_banner<S>(
State(state): State<HealthState>,

View File

@@ -55,6 +55,8 @@ where
)
.route(
"/health/banners/{id}",
axum::routing::put(banner_handler::update_banner).delete(banner_handler::delete_banner),
axum::routing::get(banner_handler::get_banner)
.put(banner_handler::update_banner)
.delete(banner_handler::delete_banner),
)
}

View File

@@ -62,6 +62,23 @@ pub async fn list_banners(
Ok(result)
}
/// 获取单个轮播图
pub async fn get_banner(
state: &HealthState,
tenant_id: Uuid,
banner_id: Uuid,
) -> HealthResult<BannerResp> {
let b = banner::Entity::find_by_id(banner_id)
.filter(banner::Column::TenantId.eq(tenant_id))
.filter(banner::Column::DeletedAt.is_null())
.one(&state.db)
.await?
.ok_or(HealthError::BannerNotFound)?;
let media_map = load_media_map(state, &[b.media_item_id]).await?;
Ok(banner_to_resp(&b, &media_map))
}
/// 创建轮播图
pub async fn create_banner(
state: &HealthState,