@@ -13,7 +13,7 @@ public partial class RoleMenuDialog
1313
1414 private List < Data . Entities . Rbac . Menu > MenuList = new ( ) ;
1515
16- private List < TreeItemData < MenuTreeItem > > MenuTreeItemSet = new ( ) ;
16+ private List < MenuTableRow > MenuTableRows = new ( ) ;
1717
1818 private List < int > CheckedMenuIdList = new ( ) ;
1919
@@ -24,23 +24,52 @@ protected override async Task OnInitializedAsync()
2424 using var context = await _dbFactory . CreateDbContextAsync ( ) ;
2525 CheckedMenuIdList = context . RoleMenus . Where ( rm => rm . RoleId == RoleId ) . Select ( rm => rm . MenuId ) . ToList ( ) ;
2626 MenuList = context . Menus . ToList ( ) ;
27- MenuTreeItemSet = AppendMenuItems ( null , MenuList ) ;
27+
28+ // 处理菜单层级结构
29+ BuildMenuTableRows ( ) ;
2830 }
2931
30- private List < TreeItemData < MenuTreeItem > > AppendMenuItems ( int ? parentId , List < Data . Entities . Rbac . Menu > menus )
32+ private void BuildMenuTableRows ( )
3133 {
32- return menus . Where ( m => m . ParentId == parentId ) . OrderBy ( m => m . Order )
33- . Select ( m => new TreeItemData < MenuTreeItem >
34+ // 构建顶级菜单
35+ BuildMenuLevelRows ( null , 0 ) ;
36+ }
37+
38+ private void BuildMenuLevelRows ( int ? parentId , int level )
39+ {
40+ // 获取当前层级的菜单项
41+ var menuItems = MenuList . Where ( m => m . Type == 1 && m . ParentId == parentId )
42+ . OrderBy ( m => m . Order )
43+ . ToList ( ) ;
44+
45+ foreach ( var menu in menuItems )
46+ {
47+ // 创建当前菜单行
48+ var menuRow = new MenuTableRow
3449 {
35- Value = new MenuTreeItem
50+ Menu = new MenuItemViewModel
3651 {
37- Id = m . Id ,
38- IsChecked = CheckedMenuIdList . Contains ( m . Id ) ,
39- MenuIcon = m . Icon ,
40- MenuName = m . Name ,
52+ Id = menu . Id ,
53+ IsChecked = CheckedMenuIdList . Contains ( menu . Id ) ,
54+ MenuIcon = menu . Icon ,
55+ MenuName = menu . Name ,
56+ Level = level
4157 } ,
42- Children = AppendMenuItems ( m . Id , menus )
43- } ) . ToList ( ) ;
58+ Buttons = MenuList . Where ( m => m . Type == 2 && m . ParentId == menu . Id )
59+ . OrderBy ( m => m . Order )
60+ . Select ( button => new MenuItemViewModel
61+ {
62+ Id = button . Id ,
63+ IsChecked = CheckedMenuIdList . Contains ( button . Id ) ,
64+ MenuName = button . Name
65+ } ) . ToList ( )
66+ } ;
67+
68+ MenuTableRows . Add ( menuRow ) ;
69+
70+ // 递归处理子菜单
71+ BuildMenuLevelRows ( menu . Id , level + 1 ) ;
72+ }
4473 }
4574
4675 #endregion
@@ -51,7 +80,8 @@ private async Task SubmitRoleMenu()
5180 {
5281 using var context = await _dbFactory . CreateDbContextAsync ( ) ;
5382
54- var idList = GetSelectedValues ( MenuTreeItemSet ) ;
83+ // 获取所有选中的菜单和按钮ID
84+ var idList = GetSelectedValues ( ) ;
5585
5686 var roleMenuList = context . RoleMenus . Where ( rm => rm . RoleId == RoleId ) . ToList ( ) ;
5787
@@ -71,66 +101,114 @@ private async Task SubmitRoleMenu()
71101 MudDialog ? . Close ( DialogResult . Ok ( true ) ) ;
72102 }
73103
74- private List < int > GetSelectedValues ( List < TreeItemData < MenuTreeItem > > set )
104+ private List < int > GetSelectedValues ( )
75105 {
76- return set . Where ( i => i . Value . IsChecked ) . Select ( i => i . Value . Id )
77- . Concat ( set . SelectMany ( i => GetSelectedValues ( i . Children ) ) )
78- . ToList ( ) ;
106+ var result = new List < int > ( ) ;
107+
108+ // 添加选中的菜单ID
109+ result . AddRange ( MenuTableRows . Where ( row => row . Menu . IsChecked ) . Select ( row => row . Menu . Id ) ) ;
110+
111+ // 添加选中的按钮ID
112+ foreach ( var row in MenuTableRows )
113+ {
114+ result . AddRange ( row . Buttons . Where ( btn => btn . IsChecked ) . Select ( btn => btn . Id ) ) ;
115+ }
116+
117+ return result ;
79118 }
80119
81120 #endregion
82121
83-
84122 #region checkbox checked change event
85123
86- private void CheckedChanged ( bool value , TreeItemData < MenuTreeItem > item )
124+ private void MenuCheckedChanged ( bool value , MenuItemViewModel item )
87125 {
88- LoopCheckedChange ( value , item ) ;
89- if ( value )
126+ item . IsChecked = value ;
127+
128+ // 如果取消选中菜单,同时取消选中其所有按钮和子菜单
129+ if ( ! value )
130+ {
131+ // 取消所有按钮
132+ var row = MenuTableRows . FirstOrDefault ( r => r . Menu . Id == item . Id ) ;
133+ if ( row != null )
134+ {
135+ foreach ( var button in row . Buttons )
136+ {
137+ button . IsChecked = false ;
138+ }
139+ }
140+
141+ // 递归取消所有子菜单
142+ UncheckChildMenus ( item . Id ) ;
143+ }
144+ else
90145 {
91- LoopParentChecked ( item ) ;
146+ // 如果选中菜单,确保其所有父菜单也被选中
147+ CheckParentMenus ( item . Id ) ;
92148 }
93149 }
94150
95- private void LoopCheckedChange ( bool value , TreeItemData < MenuTreeItem > item )
151+ private void UncheckChildMenus ( int parentId )
96152 {
97- item . Value . IsChecked = value ;
98- foreach ( var i in item . Children )
153+ // 查找所有子菜单行
154+ var childRows = MenuTableRows . Where ( r => MenuList . Any ( m => m . Id == r . Menu . Id && m . ParentId == parentId ) ) . ToList ( ) ;
155+
156+ foreach ( var childRow in childRows )
99157 {
100- LoopCheckedChange ( value , i ) ;
158+ childRow . Menu . IsChecked = false ;
159+
160+ // 取消所有按钮
161+ foreach ( var button in childRow . Buttons )
162+ {
163+ button . IsChecked = false ;
164+ }
165+
166+ // 递归处理子菜单的子菜单
167+ UncheckChildMenus ( childRow . Menu . Id ) ;
101168 }
102169 }
103170
104- private void LoopParentChecked ( TreeItemData < MenuTreeItem > item )
171+ private void CheckParentMenus ( int menuId )
105172 {
106- item . Value . IsChecked = true ;
107- var parent = FindParentItem ( item . Value , MenuTreeItemSet ) ;
108- if ( parent != null )
173+ // 找到当前菜单
174+ var menu = MenuList . FirstOrDefault ( m => m . Id == menuId ) ;
175+ if ( menu ? . ParentId != null )
109176 {
110- LoopParentChecked ( parent ) ;
177+ // 找到父菜单行
178+ var parentRow = MenuTableRows . FirstOrDefault ( r => r . Menu . Id == menu . ParentId ) ;
179+ if ( parentRow != null && ! parentRow . Menu . IsChecked )
180+ {
181+ parentRow . Menu . IsChecked = true ;
182+
183+ // 递归处理父菜单的父菜单
184+ CheckParentMenus ( parentRow . Menu . Id ) ;
185+ }
111186 }
112187 }
113188
114- private TreeItemData < MenuTreeItem > ? FindParentItem ( MenuTreeItem item , List < TreeItemData < MenuTreeItem > > itemList )
189+ private void ButtonCheckedChanged ( bool value , MenuItemViewModel item )
115190 {
116- var parent = itemList . FirstOrDefault ( i => i . Children . Any ( c => c . Value . Id == item . Id ) ) ;
117- if ( parent == null )
191+ item . IsChecked = value ;
192+
193+ // 如果选中按钮,确保其所属菜单也被选中
194+ if ( value )
118195 {
119- foreach ( var i in itemList )
196+ var row = MenuTableRows . FirstOrDefault ( r => r . Buttons . Any ( b => b . Id == item . Id ) ) ;
197+ if ( row != null )
120198 {
121- parent = FindParentItem ( item , i . Children ) ;
122- if ( parent != null )
123- {
124- return parent ;
125- }
199+ row . Menu . IsChecked = true ;
200+
201+ // 确保所有父菜单也被选中
202+ CheckParentMenus ( row . Menu . Id ) ;
126203 }
127204 }
128- return parent ;
129205 }
130206
131207 #endregion
132208
133- private class MenuTreeItem
209+ #region Models
210+
211+ private class MenuItemViewModel
134212 {
135213 public int Id { get ; set ; }
136214
@@ -139,7 +217,17 @@ private class MenuTreeItem
139217 public string ? MenuName { get ; set ; }
140218
141219 public bool IsChecked { get ; set ; }
220+
221+ public int Level { get ; set ; } = 0 ;
222+ }
142223
224+ private class MenuTableRow
225+ {
226+ public MenuItemViewModel Menu { get ; set ; } = new ( ) ;
227+
228+ public List < MenuItemViewModel > Buttons { get ; set ; } = new ( ) ;
143229 }
230+
231+ #endregion
144232 }
145233}
0 commit comments