use axum::Extension; use axum::extract::{FromRef, Json, Path, State}; use axum::response::Json as JsonResponse; use erp_core::error::AppError; use erp_core::rbac::require_permission; use erp_core::types::{ApiResponse, Pagination, TenantContext}; use crate::config_state::ConfigState; use crate::dto::{LanguageResp, UpdateLanguageReq}; use crate::service::setting_service::SettingService; /// GET /api/v1/languages /// /// 获取当前租户的语言配置列表。 /// 查询 scope 为 "platform" 的设置,过滤 key 以 "language." 开头的记录。 /// 需要 `language.list` 权限。 pub async fn list_languages( State(state): State, Extension(ctx): Extension, ) -> Result>>, AppError> where ConfigState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "language.list")?; let pagination = Pagination { page: Some(1), page_size: Some(100), }; let (settings, _total) = SettingService::list_by_scope( "platform", &None, ctx.tenant_id, &pagination, &state.db, ) .await?; let languages: Vec = settings .into_iter() .filter(|s| s.setting_key.starts_with("language.")) .filter_map(|s| { let code = s.setting_key.strip_prefix("language.")?.to_string(); let name = code.clone(); // 默认使用 code 作为名称 let is_active = s .setting_value .get("is_active") .and_then(|v| v.as_bool()) .unwrap_or(true); Some(LanguageResp { code, name, is_active, }) }) .collect(); Ok(JsonResponse(ApiResponse::ok(languages))) } /// PUT /api/v1/languages/:code /// /// 更新指定语言配置的激活状态。 /// 语言配置存储在 settings 表中,key 为 "language.{code}",scope 为 "platform"。 /// 需要 `language.update` 权限。 pub async fn update_language( State(state): State, Extension(ctx): Extension, Path(code): Path, Json(req): Json, ) -> Result>, AppError> where ConfigState: FromRef, S: Clone + Send + Sync + 'static, { require_permission(&ctx, "language.update")?; let key = format!("language.{}", code); let value = serde_json::json!({"is_active": req.is_active}); SettingService::set( &key, "platform", &None, value, ctx.tenant_id, ctx.user_id, &state.db, &state.event_bus, ) .await?; Ok(JsonResponse(ApiResponse::ok(LanguageResp { code, name: String::new(), is_active: req.is_active, }))) }