Files
erp/crates/erp-config/src/handler/theme_handler.rs
iven 841766b168
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(用户管理): 修复用户列表页面加载失败问题
修复用户列表页面加载失败导致测试超时的问题,确保页面元素正确渲染
2026-04-19 08:46:28 +08:00

109 lines
3.2 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, State};
use axum::response::Json as JsonResponse;
use erp_core::error::AppError;
use erp_core::rbac::require_permission;
use erp_core::types::{ApiResponse, TenantContext};
use crate::config_state::ConfigState;
use crate::dto::{SetSettingParams, ThemeResp};
use crate::error::ConfigError;
use crate::service::setting_service::SettingService;
/// 默认主题配置。
fn default_theme() -> ThemeResp {
ThemeResp {
primary_color: None,
logo_url: None,
sidebar_style: None,
}
}
#[utoipa::path(
get,
path = "/api/v1/themes",
responses(
(status = 200, description = "成功", body = ApiResponse<ThemeResp>),
(status = 401, description = "未授权"),
(status = 403, description = "权限不足"),
),
security(("bearer_auth" = [])),
tag = "主题设置"
)]
/// GET /api/v1/theme
///
/// 获取当前租户的主题配置。
/// 主题配置存储在 settings 表中key 为 "theme"scope 为 "tenant"。
/// 当没有任何主题配置时,返回默认主题(所有字段为 null
/// 需要 `theme.read` 权限。
pub async fn get_theme<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
) -> Result<JsonResponse<ApiResponse<ThemeResp>>, AppError>
where
ConfigState: FromRef<S>,
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "theme.read")?;
let theme = match SettingService::get("theme", "tenant", &None, ctx.tenant_id, &state.db).await
{
Ok(setting) => serde_json::from_value(setting.setting_value)
.map_err(|e| AppError::Validation(format!("主题配置解析失败: {e}")))?,
Err(ConfigError::NotFound(_)) => default_theme(),
Err(e) => return Err(e.into()),
};
Ok(JsonResponse(ApiResponse::ok(theme)))
}
#[utoipa::path(
put,
path = "/api/v1/themes",
request_body = ThemeResp,
responses(
(status = 200, description = "成功", body = ApiResponse<ThemeResp>),
(status = 401, description = "未授权"),
(status = 403, description = "权限不足"),
),
security(("bearer_auth" = [])),
tag = "主题设置"
)]
/// PUT /api/v1/theme
///
/// 更新当前租户的主题配置。
/// 将主题配置序列化为 JSON 存储到 settings 表。
/// 需要 `theme.update` 权限。
pub async fn update_theme<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
Json(req): Json<ThemeResp>,
) -> Result<JsonResponse<ApiResponse<ThemeResp>>, AppError>
where
ConfigState: FromRef<S>,
S: Clone + Send + Sync + 'static,
{
require_permission(&ctx, "theme.update")?;
let value = serde_json::to_value(&req)
.map_err(|e| AppError::Validation(format!("主题配置序列化失败: {e}")))?;
SettingService::set(
SetSettingParams {
key: "theme".to_string(),
scope: "tenant".to_string(),
scope_id: None,
value,
version: None,
},
ctx.tenant_id,
ctx.user_id,
&state.db,
&state.event_bus,
)
.await?;
Ok(JsonResponse(ApiResponse::ok(req)))
}