feat(config): 菜单动态化改造 — 侧边栏从后端 API 加载
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

- 新增 seed 迁移插入完整菜单树(4 directory + 23 menu = 27 条)
- 新增 GET /api/v1/menus/user 端点(仅需登录,无需 menu.list 权限)
- MainLayout 从 API 动态获取菜单树替换硬编码数组
- 扩展图标映射表覆盖 22 个 Ant Design 图标
- Header 标题从动态菜单数据查找,保留 fallback
This commit is contained in:
iven
2026-04-26 01:55:01 +08:00
parent 2539e5fc44
commit e3177f262c
6 changed files with 323 additions and 138 deletions

View File

@@ -236,6 +236,39 @@ where
}))
}
#[utoipa::path(
get,
path = "/api/v1/menus/user",
responses(
(status = 200, description = "成功", body = ApiResponse<Vec<MenuResp>>),
(status = 401, description = "未授权"),
),
security(("bearer_auth" = [])),
tag = "菜单管理"
)]
/// GET /api/v1/menus/user
///
/// 获取当前用户可见的菜单树(无需 menu.list 权限,仅需登录)。
pub async fn get_user_menus<S>(
State(state): State<ConfigState>,
Extension(ctx): Extension<TenantContext>,
) -> Result<JsonResponse<ApiResponse<Vec<MenuResp>>>, AppError>
where
ConfigState: FromRef<S>,
S: Clone + Send + Sync + 'static,
{
let role_ids: Vec<Uuid> = ctx
.roles
.iter()
.filter_map(|r| Uuid::parse_str(r).ok())
.collect();
// 如果用户有角色关联菜单按角色过滤否则返回全部admin 兜底)
let menus = MenuService::get_menu_tree(ctx.tenant_id, &role_ids, &state.db).await?;
Ok(JsonResponse(ApiResponse::ok(menus)))
}
/// 删除菜单的乐观锁版本号请求体。
#[derive(Debug, serde::Deserialize, utoipa::ToSchema)]
pub struct DeleteMenuVersionReq {