动态生成用户菜单

网站导航是用户访问网站的主要方式,它帮助用户轻松地找到他们想要的内容。如果导航菜单能够根据用户权限数据库动态生成,那么这将是网站的一个加分项。本文将解释如何根据网站管理员赋予的权限,为用户从数据库生成菜单。

前端展示

前端生成菜单的方式与从数据库生成菜单相似。这里将修改后端部分,仅从那里生成菜单项。在转向后端之前,让先了解一些基本的数据库生成菜单的方法。在创建这个菜单时,使用了一些基本功能,例如:

数据库获取菜单数据。这个函数用于获取特定用户的菜单项(这里硬编码了UserID为K010,可以在这里设置会话值)。

private DataTable GetMenuData() { try { using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["MenuWithCustomPrivs"].ConnectionString)) { SqlCommand cmd = new SqlCommand("spMenuItem", con); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.AddWithValue("@UserID", "K010"); DataTable dtMenuItems = new DataTable(); SqlDataAdapter sda = new SqlDataAdapter(cmd); sda.Fill(dtMenuItems); cmd.Dispose(); sda.Dispose(); return dtMenuItems; } } catch (Exception ex) { // 显示错误信息 } return null; }

添加顶级/父菜单项。这里将添加Parent ID为NULL的菜单项。同时,还将调用一个函数来绑定子菜单。在这个函数中,调用了另一个函数AddChildMenuItems,它将为该菜单项绑定子项。

private void AddTopMenuItems(DataTable menuData) { DataView view = null; try { view = new DataView(menuData); view.RowFilter = "ParentID IS NULL"; foreach (DataRowView row in view) { MenuItem newMenuItem = new MenuItem(row["Text"].ToString(), row["MenuID"].ToString()); menuBar.Items.Add(newMenuItem); AddChildMenuItems(menuData, newMenuItem); } } catch (Exception ex) { // 显示错误信息 } finally { view = null; } }

添加子菜单项。这里使用这段代码来绑定子项。在这里根据从上面函数传递的Parent ID过滤菜单项。

private void AddChildMenuItems(DataTable menuData, MenuItem parentMenuItem) { DataView view = null; try { view = new DataView(menuData); view.RowFilter = "ParentID=" + parentMenuItem.Value; foreach (DataRowView row in view) { MenuItem newMenuItem = new MenuItem(row["Text"].ToString(), row["MenuID"].ToString()); newMenuItem.NavigateUrl = row["NavigateUrl"].ToString(); parentMenuItem.ChildItems.Add(newMenuItem); AddChildMenuItems(menuData, newMenuItem); } } catch (Exception ex) { // 显示错误信息 } finally { view = null; } }

以上就是绑定菜单控件的基本函数。

后端展示

现在,来到主要部分,数据库结构。这里有五个不同的表,它们包含了用户、组(角色)、其权限和菜单项的详细信息。

tblGroupPrivMst:这个表包含了组/角色和适用的权限位的信息。

tblMenuMst:这个表包含了菜单描述、菜单ID和导航URL字段。

tblUserGrpMap:这是一个映射表,它将负责用户与相应组的关系。

tblDesgMst:这个表包含了用户在网站上的职位。

tblUserMst:这个表包含了用户详细信息。

角色/组的权限位将存储在tblGroupPrivMst表中,权限位的长度将等于菜单项的总长度。这些权限位不过是0和1的组合。假设总共有10个菜单项,那么权限位将是0101011100,并且将按照这样的方式排列,以便菜单项将连续对应到位位置。第一位的0表示该角色不适用第一个位置的项。

生成菜单。可能会喜欢编写简单的SQL存储过程来生成菜单。使用的SP,根据用户权限生成菜单项如下:

CREATE PROCEDURE [dbo].[spMenuItem] @UserID [varchar](50) WITH EXECUTE AS CALLER AS BEGIN -- 声明变量 DECLARE @GroupCode VARCHAR(5) SET @GroupCode=(SELECT DISTINCT GroupCode FROM tblUserGrpMap WHERE UserID=@UserID) CREATE TABLE #TMP(MenuID INT, Text VARCHAR(50), Description VARCHAR(50), ParentID INT, NavigateUrl VARCHAR(100)) DECLARE @VAL VARCHAR(MAX), @Pos INT, @len INT SET @VAL=(SELECT REPLACE(REPLACE(CONVERT(VARCHAR(30), SUM(CAST(PrivilegeID AS NUMERIC(30,0)))), '2', '1'), '3', '1') FROM tblGroupPrivMst WHERE GroupCode in (SELECT GroupCode FROM tblUserGrpMap WHERE UserID=@UserID)) SET @Pos=1 SET @len=LEN(@VAL) WHILE (@len!=0) BEGIN DECLARE @Value CHAR(1) SET @Value=SUBSTRING(@VAL, @Pos, 1) IF @Value=1 BEGIN INSERT INTO #TMP SELECT * FROM tblMenuMst WHERE MenuID=@Pos END SET @Pos=@Pos+1 SET @len=@len-1 END -- 插入顶级节点 INSERT INTO #TMP SELECT * FROM tblMenuMst WHERE MenuID IN (SELECT DISTINCT ParentID FROM #TMP WHERE ParentID NOT IN (SELECT MenuID FROM #TMP)) -- 插入第二级节点 INSERT INTO #TMP SELECT * FROM tblMenuMst WHERE MenuID IN (SELECT DISTINCT ParentID FROM #TMP WHERE ParentID NOT IN (SELECT MenuID FROM #TMP)) -- 插入第三级节点 INSERT INTO #TMP SELECT * FROM tblMenuMst WHERE MenuID IN (SELECT DISTINCT ParentID FROM #TMP WHERE ParentID NOT IN (SELECT MenuID FROM #TMP)) SELECT * FROM #TMP ORDER BY MenuID ASC DROP TABLE #TMP END

这个SP将生成最多三级的菜单项。如果有更多的级别,需要重复这个插入命令:

INSERT INTO #TMP SELECT * FROM tblMenuMst WHERE MenuID IN(SELECT DISTINCT ParentID FROM #TMP WHERE ParentID NOT IN(SELECT MenuID FROM #TMP))

执行程序后,将得到类似于这样的菜单:

知道,在设计上可能有点无聊。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485