在使用 CAS 进行单点登录时,获取到用户的相关数据(例如菜单或权限),一般是通过后端从 CAS 服务器中获取用户信息,并在后端进行解析后,传递给前端去加载。在 JeecgBoot 这种场景下,如果你已经从 CAS 获取到了菜单数据,那么如何将这些菜单正确加载到前端主要涉及以下几个步骤。
目录
1. 后端获取菜单数据
2. 前端接收并渲染菜单
前端的主要步骤
例子(React)
例子(Vue)
3. 菜单数据格式匹配
4. 权限控制(可选)
总结
1. 后端获取菜单数据
通常,后端会通过 CAS 返回的用户身份信息(比如用户 ID、角色)去调用后端的 API(如用户菜单服务)获取用户的菜单和权限数据。如果菜单数据已经从 CAS 服务器成功返回给后端,确保以下两件事:
后端数据格式一致性:确保从 CAS 服务器返回的菜单数据结构与 Jeecg 前端期待的数据格式一致。后端 API 正确返回:如果前端是通过后端 API 来获取菜单,请确保 API 路由正确并返回给前端正确的菜单数据。例如,假设后端 API 返回如下格式的数据:
{ "menu": [ { "id": 1, "title": "Dashboard", "icon": "dashboard", "path": "/dashboard", "children": [] }, { "id": 2, "title": "User Management", "icon": "user", "path": "/user-management", "children": [ { "id": 3, "title": "Create User", "path": "/user-management/create" } ] } ]}
2. 前端接收并渲染菜单
在 JeecgBoot 中,前端菜单通常是基于 React
或 Vue
的组件来动态渲染的。如果从后端返回了菜单数据,可以通过以下步骤加载到前端页面中。
前端的主要步骤
请求菜单数据:通过 API 请求从后端获取菜单数据。
处理和存储菜单数据:将菜单数据存储在前端状态管理系统中,例如 Redux
或 Vuex
,以便后续动态渲染菜单。
动态渲染菜单:使用前端框架的组件,将获取到的菜单数据渲染出来。
例子(React)
import React, { useEffect, useState } from "react";import axios from "axios";import { Menu } from "antd";const DynamicMenu = () => { const [menuItems, setMenuItems] = useState([]); // 模拟 API 请求 useEffect(() => { axios.get("/api/getMenu") // 替换为实际的后端 API .then((response) => { setMenuItems(response.data.menu); // 假设后端返回的数据格式符合这个格式 }) .catch((error) => { console.error("Error fetching menu data", error); }); }, []); // 动态生成菜单 const renderMenuItems = (items) => { return items.map((item) => { if (item.children && item.children.length > 0) { return ( <Menu.SubMenu key={item.id} title={item.title} icon={item.icon}> {renderMenuItems(item.children)} </Menu.SubMenu> ); } return ( <Menu.Item key={item.id}> <a href={item.path}>{item.title}</a> </Menu.Item> ); }); }; return ( <Menu mode="vertical"> {renderMenuItems(menuItems)} </Menu> );};export default DynamicMenu;
在上述代码中:
使用axios
向后端请求菜单数据,并将其存储在 menuItems
状态中。使用递归的方式 renderMenuItems
动态渲染多层级的菜单结构。 例子(Vue)
如果使用 Vue
,你可以通过 axios
请求数据,并使用 v-for
进行动态渲染:
<template> <el-menu> <template v-for="item in menuItems"> <el-submenu v-if="item.children && item.children.length" :key="item.id" :index="item.id"> <template slot="title">{{ item.title }}</template> <el-menu-item v-for="child in item.children" :key="child.id" :index="child.id"> <router-link :to="child.path">{{ child.title }}</router-link> </el-menu-item> </el-submenu> <el-menu-item v-else :key="item.id" :index="item.id"> <router-link :to="item.path">{{ item.title }}</router-link> </el-menu-item> </template> </el-menu></template><script>import axios from 'axios';export default { data() { return { menuItems: [] }; }, created() { axios.get("/api/getMenu") .then(response => { this.menuItems = response.data.menu; }) .catch(error => { console.error("Error fetching menu data", error); }); }};</script>
3. 菜单数据格式匹配
确保从 CAS 或后端返回的菜单数据格式与前端渲染期望的菜单结构一致。通常,菜单数据会包含以下字段:
id: 菜单项的唯一标识符。title: 菜单项显示的名称。icon: 菜单项的图标(如果有)。path: 路由路径。children: 子菜单项(如果是嵌套菜单)。如果后端返回的数据结构不符合前端的要求,你可能需要在前端做一些数据预处理。
例如,假设后端返回的数据结构如下:
{ "menuList": [ { "menuId": 1, "menuName": "Dashboard", "menuUrl": "/dashboard", "subMenuList": [] }, { "menuId": 2, "menuName": "User Management", "menuUrl": "/user-management", "subMenuList": [ { "menuId": 3, "menuName": "Create User", "menuUrl": "/user-management/create" } ] } ]}
你可以在前端转换为适合渲染的数据格式:
const transformMenuData = (data) => { return data.menuList.map(item => ({ id: item.menuId, title: item.menuName, path: item.menuUrl, children: item.subMenuList ? transformMenuData(item.subMenuList) : [] }));};
然后将其传递到渲染函数:
useEffect(() => { axios.get("/api/getMenu") .then((response) => { const transformedMenu = transformMenuData(response.data); setMenuItems(transformedMenu); }) .catch((error) => { console.error("Error fetching menu data", error); });}, []);
4. 权限控制(可选)
在某些情况下,CAS 还可能返回用户的权限数据,你可以根据用户的权限来动态加载或隐藏某些菜单项。确保前端在处理菜单时,有一层权限判断逻辑,根据用户的角色或权限来渲染不同的菜单。
总结
确保后端正确获取到菜单数据。使用前端请求后端 API 获取菜单。动态渲染菜单,确保数据格式与前端渲染格式一致。(可选)实现权限控制,隐藏或显示特定菜单项。通过这些步骤,应该可以成功加载从 CAS 返回的菜单并在前端正确显示。