feat(ai): Prompt 管理 Phase 2 — analysis_type 后端选择键 + 筛选修复
- 新增 ai_prompt.analysis_type 列作为后端按链路选择 Prompt 的唯一键 - name 回归显示标识符用途,不再承担选择键角色 - 迁移 000164: 新增 analysis_type 列 + 从 name 回填 + 索引 - 迁移 000165: 修复旧数据从 category 错误回填的问题 - AiPromptList 页面重构: 分析类型/调用链路列、详情抽屉、新建表单 - DrawerForm 组件新增 onValuesChange 回调支持跨字段联动 - 新建表单选择分析类型后自动填充标识符 - 筛选过滤器改为按 analysis_type 而非 category 过滤(后端+前端同步) - 停用/激活/回滚/删除操作完整可用
This commit is contained in:
@@ -95,7 +95,7 @@ where
|
||||
|
||||
let prompt = state
|
||||
.prompt
|
||||
.get_active_prompt(ctx.tenant_id, "lab_report_interpretation")
|
||||
.get_active_prompt(ctx.tenant_id, AnalysisType::LabReport.prompt_name())
|
||||
.await?;
|
||||
|
||||
let model_config = &prompt.model_config;
|
||||
@@ -190,7 +190,7 @@ where
|
||||
|
||||
let prompt = state
|
||||
.prompt
|
||||
.get_active_prompt(ctx.tenant_id, "health_trend_analysis")
|
||||
.get_active_prompt(ctx.tenant_id, AnalysisType::Trends.prompt_name())
|
||||
.await?;
|
||||
|
||||
let model_config = &prompt.model_config;
|
||||
@@ -262,7 +262,7 @@ where
|
||||
|
||||
let prompt = state
|
||||
.prompt
|
||||
.get_active_prompt(ctx.tenant_id, "personalized_checkup_plan")
|
||||
.get_active_prompt(ctx.tenant_id, AnalysisType::CheckupPlan.prompt_name())
|
||||
.await?;
|
||||
|
||||
let model_config = &prompt.model_config;
|
||||
@@ -341,7 +341,7 @@ where
|
||||
|
||||
let prompt = state
|
||||
.prompt
|
||||
.get_active_prompt(ctx.tenant_id, "report_summary_generation")
|
||||
.get_active_prompt(ctx.tenant_id, AnalysisType::ReportSummary.prompt_name())
|
||||
.await?;
|
||||
|
||||
let model_config = &prompt.model_config;
|
||||
@@ -417,7 +417,7 @@ where
|
||||
|
||||
let prompt = state
|
||||
.prompt
|
||||
.get_active_prompt(ctx.tenant_id, "follow_up_summary_generation")
|
||||
.get_active_prompt(ctx.tenant_id, AnalysisType::FollowUpSummary.prompt_name())
|
||||
.await?;
|
||||
|
||||
let model_config = &prompt.model_config;
|
||||
@@ -577,6 +577,7 @@ where
|
||||
#[derive(Debug, Deserialize, utoipa::IntoParams)]
|
||||
pub struct ListPromptsQuery {
|
||||
pub category: Option<String>,
|
||||
pub analysis_type: Option<String>,
|
||||
pub page: Option<u64>,
|
||||
pub page_size: Option<u64>,
|
||||
}
|
||||
@@ -605,7 +606,11 @@ where
|
||||
};
|
||||
let (items, total) = state
|
||||
.prompt
|
||||
.list_prompts(ctx.tenant_id, params.category, &pagination)
|
||||
.list_prompts(
|
||||
ctx.tenant_id,
|
||||
params.analysis_type.or(params.category),
|
||||
&pagination,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(serde_json::json!({
|
||||
"data": items,
|
||||
@@ -623,6 +628,7 @@ pub struct CreatePromptBody {
|
||||
pub user_prompt_template: String,
|
||||
pub model_config: serde_json::Value,
|
||||
pub category: String,
|
||||
pub analysis_type: String,
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -655,6 +661,7 @@ where
|
||||
body.user_prompt_template,
|
||||
body.model_config,
|
||||
body.category,
|
||||
body.analysis_type,
|
||||
)
|
||||
.await?;
|
||||
Ok(Json(ApiResponse::ok(prompt)))
|
||||
@@ -702,6 +709,48 @@ where
|
||||
Ok(Json(ApiResponse::ok(prompt)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = "/ai/prompts/{id}/deactivate",
|
||||
responses((status = 200, description = "停用 Prompt 模板")),
|
||||
tag = "AI Prompt",
|
||||
security(("bearer_auth" = [])),
|
||||
)]
|
||||
pub async fn deactivate_prompt<S>(
|
||||
State(state): State<AiState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(id): Path<uuid::Uuid>,
|
||||
) -> Result<Json<ApiResponse<crate::entity::ai_prompt::Model>>, erp_core::error::AppError>
|
||||
where
|
||||
AiState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "ai.prompt.manage")?;
|
||||
let prompt = state.prompt.deactivate_prompt(id, ctx.tenant_id).await?;
|
||||
Ok(Json(ApiResponse::ok(prompt)))
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
path = "/ai/prompts/{id}",
|
||||
responses((status = 200, description = "删除 Prompt 模板")),
|
||||
tag = "AI Prompt",
|
||||
security(("bearer_auth" = [])),
|
||||
)]
|
||||
pub async fn delete_prompt<S>(
|
||||
State(state): State<AiState>,
|
||||
Extension(ctx): Extension<TenantContext>,
|
||||
Path(id): Path<uuid::Uuid>,
|
||||
) -> Result<Json<ApiResponse<()>>, erp_core::error::AppError>
|
||||
where
|
||||
AiState: FromRef<S>,
|
||||
S: Clone + Send + Sync + 'static,
|
||||
{
|
||||
require_permission(&ctx, "ai.prompt.manage")?;
|
||||
state.prompt.delete_prompt(id, ctx.tenant_id).await?;
|
||||
Ok(Json(ApiResponse::ok(())))
|
||||
}
|
||||
|
||||
// === 用量统计 ===
|
||||
|
||||
#[utoipa::path(
|
||||
|
||||
Reference in New Issue
Block a user