//! 提示词模板 HTTP 处理器 use axum::{ extract::{Extension, Path, Query, State}, Json, }; use crate::state::AppState; use crate::error::SaasResult; use crate::auth::types::AuthContext; use crate::auth::handlers::{log_operation, check_permission}; use super::types::*; use super::service; /// GET /api/v1/prompts/check — OTA 批量检查更新 pub async fn check_updates( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> SaasResult> { let result = service::check_updates(&state.db, &req.device_id, &req.versions).await?; log_operation(&state.db, &ctx.account_id, "prompt.check", "prompt", &req.device_id, Some(serde_json::json!({"updates_count": result.updates.len()})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// GET /api/v1/prompts — 列表全部模板 pub async fn list_prompts( State(state): State, Extension(ctx): Extension, Query(query): Query, ) -> SaasResult>> { check_permission(&ctx, "prompt:read")?; Ok(Json(service::list_templates(&state.db, &query).await?)) } /// POST /api/v1/prompts — 创建提示词模板 pub async fn create_prompt( State(state): State, Extension(ctx): Extension, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "prompt:write")?; let source = req.source.as_deref().unwrap_or("custom"); let result = service::create_template( &state.db, &req.name, &req.category, req.description.as_deref(), source, &req.system_prompt, req.user_prompt_template.as_deref(), req.variables.clone(), req.min_app_version.as_deref(), ).await?; log_operation(&state.db, &ctx.account_id, "prompt.create", "prompt", &result.id, Some(serde_json::json!({"name": req.name})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// GET /api/v1/prompts/{name} — 获取模板(按名称) pub async fn get_prompt( State(state): State, Extension(ctx): Extension, Path(name): Path, ) -> SaasResult> { check_permission(&ctx, "prompt:read")?; Ok(Json(service::get_template_by_name(&state.db, &name).await?)) } /// PUT /api/v1/prompts/{name} — 更新模板元数据 + 可选自动创建新版本 pub async fn update_prompt( State(state): State, Extension(ctx): Extension, Path(name): Path, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "prompt:write")?; let tmpl = service::get_template_by_name(&state.db, &name).await?; let result = service::update_template( &state.db, &tmpl.id, req.description.as_deref(), req.status.as_deref(), req.system_prompt.as_deref(), req.user_prompt_template.as_deref(), req.variables.clone(), req.changelog.as_deref(), req.min_app_version.as_deref(), ).await?; log_operation(&state.db, &ctx.account_id, "prompt.update", "prompt", &tmpl.id, Some(serde_json::json!({"name": name})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// DELETE /api/v1/prompts/{name} — 归档模板 pub async fn archive_prompt( State(state): State, Extension(ctx): Extension, Path(name): Path, ) -> SaasResult> { check_permission(&ctx, "prompt:admin")?; let tmpl = service::get_template_by_name(&state.db, &name).await?; let result = service::update_template(&state.db, &tmpl.id, None, Some("archived"), None, None, None, None, None).await?; log_operation(&state.db, &ctx.account_id, "prompt.archive", "prompt", &tmpl.id, None, ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// GET /api/v1/prompts/{name}/versions — 查看版本历史 pub async fn list_versions( State(state): State, Extension(ctx): Extension, Path(name): Path, ) -> SaasResult>> { check_permission(&ctx, "prompt:read")?; let tmpl = service::get_template_by_name(&state.db, &name).await?; Ok(Json(service::list_versions(&state.db, &tmpl.id).await?)) } /// GET /api/v1/prompts/{name}/versions/{version} — 获取特定版本 pub async fn get_version( State(state): State, Extension(ctx): Extension, Path((name, version)): Path<(String, i32)>, ) -> SaasResult> { check_permission(&ctx, "prompt:read")?; Ok(Json(service::get_version_by_number(&state.db, &name, version).await?)) } /// POST /api/v1/prompts/{name}/versions — 发布新版本 pub async fn create_version( State(state): State, Extension(ctx): Extension, Path(name): Path, Json(req): Json, ) -> SaasResult> { check_permission(&ctx, "prompt:write")?; let tmpl = service::get_template_by_name(&state.db, &name).await?; let result = service::create_version( &state.db, &tmpl.id, &req.system_prompt, req.user_prompt_template.as_deref(), req.variables.clone(), req.changelog.as_deref(), req.min_app_version.as_deref(), ).await?; log_operation(&state.db, &ctx.account_id, "prompt.publish_version", "prompt", &tmpl.id, Some(serde_json::json!({"name": name, "version": result.version})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) } /// POST /api/v1/prompts/{name}/rollback/{version} — 回退到指定版本 pub async fn rollback_version( State(state): State, Extension(ctx): Extension, Path((name, version)): Path<(String, i32)>, ) -> SaasResult> { check_permission(&ctx, "prompt:admin")?; let tmpl = service::get_template_by_name(&state.db, &name).await?; let result = service::rollback_version(&state.db, &tmpl.id, version).await?; log_operation(&state.db, &ctx.account_id, "prompt.rollback", "prompt", &tmpl.id, Some(serde_json::json!({"name": name, "target_version": version})), ctx.client_ip.as_deref()).await?; Ok(Json(result)) }