Files
hms/crates/erp-config/src/handler/language_handler.rs
iven 8a253a4910
Some checks failed
CI / rust-check (push) Has been cancelled
CI / rust-test (push) Has been cancelled
CI / frontend-build (push) Has been cancelled
CI / security-audit (push) Has been cancelled
fix: 低优先级收尾 — 图片上传/语言编辑/插件恢复/URL 编码
- P3-2: ArticleEditor 图片上传接入 /upload 端点 + 封面图上传按钮
- P4-3: recover_plugins 添加 tenant 日志 + 同 ID 去重保护
- P4-4: LanguageManager 编辑弹窗改为真实表单 (name 字段) + 后端 name 持久化
- P4-6: Settings API getSetting/updateSetting 添加 encodeURIComponent
2026-04-26 19:52:42 +08:00

143 lines
4.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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, SetSettingParams, UpdateLanguageReq};
use crate::service::setting_service::SettingService;
#[utoipa::path(
get,
path = "/api/v1/languages",
responses(
(status = 200, description = "成功", body = ApiResponse<Vec<LanguageResp>>),
(status = 401, description = "未授权"),
(status = 403, description = "权限不足"),
),
security(("bearer_auth" = [])),
tag = "语言管理"
)]
/// GET /api/v1/languages
///
/// 获取当前租户的语言配置列表。
/// 查询 scope 为 "platform" 的设置,过滤 key 以 "language." 开头的记录。
/// 需要 `language.list` 权限。
pub async fn list_languages<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
) -> Result<JsonResponse<ApiResponse<Vec<LanguageResp>>>, AppError>
where
ConfigState: FromRef<S>,
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<LanguageResp> = 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 = s
.setting_value
.get("name")
.and_then(|v| v.as_str())
.unwrap_or(&code)
.to_string();
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)))
}
#[utoipa::path(
put,
path = "/api/v1/languages/{code}",
params(("code" = String, Path, description = "语言编码")),
request_body = UpdateLanguageReq,
responses(
(status = 200, description = "成功", body = ApiResponse<LanguageResp>),
(status = 401, description = "未授权"),
(status = 403, description = "权限不足"),
),
security(("bearer_auth" = [])),
tag = "语言管理"
)]
/// PUT /api/v1/languages/:code
///
/// 更新指定语言配置的激活状态。
/// 语言配置存储在 settings 表中key 为 "language.{code}"scope 为 "platform"。
/// 需要 `language.update` 权限。
pub async fn update_language<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
Path(code): Path<String>,
Json(req): Json<UpdateLanguageReq>,
) -> Result<JsonResponse<ApiResponse<LanguageResp>>, AppError>
where
ConfigState: FromRef<S>,
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "language.update")?;
let key = format!("language.{}", code);
let mut value = serde_json::json!({"is_active": req.is_active});
if let Some(ref name) = req.name {
value["name"] = serde_json::Value::String(name.clone());
}
SettingService::set(
SetSettingParams {
key: key.clone(),
scope: "platform".to_string(),
scope_id: None,
value,
version: None,
},
ctx.tenant_id,
ctx.user_id,
&state.db,
&state.event_bus,
)
.await?;
// 从返回的 SettingResp 中读取实际值
let updated = SettingService::get(&key, "platform", &None, ctx.tenant_id, &state.db).await?;
// 尝试从 value 中提取 name否则用 code 作为默认名称
let name = updated
.setting_value
.get("name")
.and_then(|v| v.as_str())
.unwrap_or(&code)
.to_string();
Ok(JsonResponse(ApiResponse::ok(LanguageResp {
code,
name,
is_active: req.is_active,
})))
}