feat(ai): AI 健康管家 V2 基础设施 — 功能开关 + 角色沙箱准备 + 体征页 AI 趋势分析
- 迁移 000153: 新增 ai_feature_flags / ai_usage_daily / ai_suggestion_feedback 三张表, ai_tenant_configs 增加 billing_enabled 列, seed 12 个功能开关 + 2 个管理权限码 - 新增 FeatureFlagService: 5 分钟缓存 + DB 回退 + 即时更新 - VitalSignsTab 添加 AI 趋势分析按钮 (SSE 流式) - 新增 3 个 Entity (ai_feature_flags / ai_usage_daily / ai_suggestion_feedback) - AiState 扩展 feature_flags 字段 - 设计规格 + 讨论记录文档 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -66,11 +66,28 @@ where
|
||||
)
|
||||
.await?;
|
||||
|
||||
// 返回保存后的配置
|
||||
// 保存后重新加载 provider 到 registry(立即生效)
|
||||
reload_providers_from_db(&ai_state, ctx.tenant_id).await;
|
||||
|
||||
// 返回保存后的配置(含掩码 API Key)
|
||||
let config = config_resolver::load_ai_config(ctx.tenant_id, &ai_state.db).await;
|
||||
Ok(Json(ApiResponse::ok(config)))
|
||||
}
|
||||
|
||||
/// 从 DB 加载配置并重新加载 provider registry
|
||||
async fn reload_providers_from_db(ai_state: &AiState, tenant_id: uuid::Uuid) {
|
||||
let values = config_resolver::load_ai_config_raw(tenant_id, &ai_state.db).await;
|
||||
let kek = *erp_core::crypto::PiiCrypto::dev_default().kek();
|
||||
|
||||
if let Err(e) = ai_state
|
||||
.provider_registry
|
||||
.reload_providers(&values, &kek)
|
||||
.await
|
||||
{
|
||||
tracing::error!(error = %e, "Provider registry 重新加载失败");
|
||||
}
|
||||
}
|
||||
|
||||
/// 获取 AI 配置的默认值(用于前端初始化表单)
|
||||
#[utoipa::path(
|
||||
get,
|
||||
@@ -131,5 +148,25 @@ fn validate_config(config: &config_resolver::AiConfig) -> Result<(), erp_core::e
|
||||
"分析默认最大 token 数必须在 1 ~ 65536 之间".into(),
|
||||
));
|
||||
}
|
||||
|
||||
// 验证 provider 配置(仅校验已启用的)
|
||||
for (name, provider) in &config.providers {
|
||||
if !provider.enabled {
|
||||
continue;
|
||||
}
|
||||
if provider.base_url.trim().is_empty() {
|
||||
return Err(erp_core::error::AppError::Validation(format!(
|
||||
"Provider {} 的 Base URL 不能为空",
|
||||
name
|
||||
)));
|
||||
}
|
||||
if provider.model.trim().is_empty() {
|
||||
return Err(erp_core::error::AppError::Validation(format!(
|
||||
"Provider {} 的模型名称不能为空",
|
||||
name
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user