feat(ai): 新增预算状态 + 成本估算 API 端点
Phase 3 Task 25: - GET /ai/budget/status — 租户月度预算状态和告警等级 - GET /ai/cost/estimate — 按分析类型+模型估算单次成本
This commit is contained in:
@@ -558,6 +558,42 @@ where
|
|||||||
Ok(Json(ApiResponse::ok(result)))
|
Ok(Json(ApiResponse::ok(result)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// === 成本与预算 ===
|
||||||
|
|
||||||
|
pub async fn budget_status<S>(
|
||||||
|
State(state): State<AiState>,
|
||||||
|
Extension(ctx): Extension<TenantContext>,
|
||||||
|
) -> Result<Json<ApiResponse<crate::service::cost::BudgetStatus>>, erp_core::error::AppError>
|
||||||
|
where
|
||||||
|
AiState: FromRef<S>,
|
||||||
|
S: Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
require_permission(&ctx, "ai.usage.list")?;
|
||||||
|
let cost_svc = crate::service::cost::CostService::new(state.db.clone());
|
||||||
|
let status = cost_svc.get_budget_status(ctx.tenant_id).await?;
|
||||||
|
Ok(Json(ApiResponse::ok(status)))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct CostEstimateQuery {
|
||||||
|
pub analysis_type: String,
|
||||||
|
pub model: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn cost_estimate<S>(
|
||||||
|
Extension(ctx): Extension<TenantContext>,
|
||||||
|
Query(params): Query<CostEstimateQuery>,
|
||||||
|
) -> Result<Json<ApiResponse<crate::service::cost::CostEstimate>>, erp_core::error::AppError>
|
||||||
|
where
|
||||||
|
AiState: FromRef<S>,
|
||||||
|
S: Clone + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
require_permission(&ctx, "ai.usage.list")?;
|
||||||
|
let model = params.model.unwrap_or_else(|| "claude-sonnet-4-6".to_string());
|
||||||
|
let estimate = crate::service::cost::CostService::estimate_cost(¶ms.analysis_type, &model);
|
||||||
|
Ok(Json(ApiResponse::ok(estimate)))
|
||||||
|
}
|
||||||
|
|
||||||
// === SSE 流构建辅助 ===
|
// === SSE 流构建辅助 ===
|
||||||
|
|
||||||
fn build_sse_stream(
|
fn build_sse_stream(
|
||||||
|
|||||||
@@ -359,5 +359,13 @@ impl AiModule {
|
|||||||
"/ai/quota/summary",
|
"/ai/quota/summary",
|
||||||
axum::routing::get(crate::handler::quota_summary),
|
axum::routing::get(crate::handler::quota_summary),
|
||||||
)
|
)
|
||||||
|
.route(
|
||||||
|
"/ai/budget/status",
|
||||||
|
axum::routing::get(crate::handler::budget_status),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/ai/cost/estimate",
|
||||||
|
axum::routing::get(crate::handler::cost_estimate),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user