ASP.NET MVC4 +EF+ EasyUI实现 动态菜单

这段时间没事,做了一个动态菜单的实现。有很多的地方想的不是很全,做的不够完善。欢迎大神们拍砖和指点!

话不多说,进入正题:

设计了一个数据库表:

在设计的时候每一个菜单的子菜单最多能添加 99 个,子菜单编号根据父菜单编号拼接上同级子菜单的个数。

    

这里因为要用到Easyui,一些子段是按照easyui属性设计的。

EF使用的是数据库优先方式创建。

贴上代码:

1.HTML代码:

 1     <style type="text/css">
 2         header {
 3             height:60px;
 4         }
 5         aside{
 6             float:left;
 7             width:200px;
 8         }
 9         article{
10             margin-left:204px
11         }
12     </style>
13 <body>
14     <header>
15         EasyUI treegrid 实现动态菜单
16     </header>
17 
18     <aside>
19     @*树形菜单*@
20         <ul id="tt"></ul>
21     </aside>
22     <article>
23         
24     @*treegrid数据表格*@
25 
26     <table id="treegrid" style="width: 600px; height: 400px"></table>
27         
28     @*treegrid的右键菜单*@
29     <div id="tree_menu" class="easyui-menu" style="width: 120px;">
30         <div>
31             <span>数据操作</span>
32             <div style="width: 120px;">
33                 <div id="add" data-options="iconCls:'icon-add0'">添加节点</div>
34                 <div id="edit" data-options="iconCls:'icon-edit0'">修改节点</div>
35                 <div id="delete" data-options="iconCls:'icon-delete0'">删除节点</div>
36             </div>
37         </div>
38         <div id="ref" data-options="iconCls:'icon-new0'">刷 新</div>
39         <div class="menu-sep"></div>
40         <div>Exit</div>
41     </div>
42     @*添加,修改表单(弹窗模式)*@
43     <div class ="treegrid_dialog" style="display: none;">
44         <form id="treegrid_form">
45             @*菜单主键*@
46             <input type="hidden" name ="MId"  />
47             @*父菜单编号*@
48             <input type="hidden" name ="pid" id="menuPid" />
49             @*菜单编号*@
50             <input type="hidden" name ="id" />
51             <table>
52                 <tr>
53                     <td>菜单名称</td><td><input  class="easyui-validatebox" name="text" data-options="required:true" /></td>
54                 </tr>
55                 <tr>
56                     <td>菜单图标</td><td><input  id="icon" name="iconCls" editable="false"/></td>
57                 </tr>
58                 <tr>
59                     <td>菜单路径</td><td><input  class="easyui-validatebox" name="url" data-options="required:true" /></td>
60                 </tr>
61                 <tr>
62                     <td>菜单是否选中</td>
63                     <td>
64                         <input id="yes" type="radio" name="checked" value="1" /><label for="yes"></label>
65                         <input id="no" type="radio" name="checked" value="0" /><label for="no"></label>
66                     </td>
67                 </tr>
68             </table>
69         </form>
70     </div>
71     </article>
72 </body>
View Code

2.JavaScript代码:

  1        var treegrid;
  2         var treegrid_dialog;
  3         var iconData;
  4         $(function () {
  5             //绑定菜单tree数据
  6             $('#tt').tree({
  7                 url: '/System/GetTree'
  8             });
  9 
 10             iconData = [{
 11                 value: '',
 12                 text: '默认'
 13             }, {
 14                 value: 'icon-add',
 15                 text: 'icon-add'
 16             }, {
 17                 value: 'icon-edit',
 18                 text: 'icon-edit'
 19             }, {
 20                 value: 'icon-remove',
 21                 text: 'icon-remove'
 22             }, {
 23                 value: 'icon-save',
 24                 text: 'icon-save'
 25             }, {
 26                 value: 'icon-cut',
 27                 text: 'icon-cut'
 28             }, {
 29                 value: 'icon-ok',
 30                 text: 'icon-ok'
 31             }, {
 32                 value: 'icon-no',
 33                 text: 'icon-no'
 34             }, {
 35                 value: 'icon-cancel',
 36                 text: 'icon-cancel'
 37             }, {
 38                 value: 'icon-reload',
 39                 text: 'icon-reload'
 40             }, {
 41                 value: 'icon-search',
 42                 text: 'icon-search'
 43             }, {
 44                 value: 'icon-print',
 45                 text: 'icon-print'
 46             }, {
 47                 value: 'icon-help',
 48                 text: 'icon-help'
 49             }, {
 50                 value: 'icon-undo',
 51                 text: 'icon-undo'
 52             }, {
 53                 value: 'icon-redo',
 54                 text: 'icon-redo'
 55             }, {
 56                 value: 'icon-back',
 57                 text: 'icon-back'
 58             }, {
 59                 value: 'icon-sum',
 60                 text: 'icon-sum'
 61             }, {
 62                 value: 'icon-tip',
 63                 text: 'icon-tip'
 64             }];
 65 
 66            treegrid= $('#treegrid').treegrid({
 67                         url: '/System/GetTree',
 68                         idField: 'id',
 69                         treeField: 'text',
 70                         columns: [[
 71                             { title: '菜单名称', field: 'text', width: 180 },
 72                             {
 73                                 title: '菜单图标', field: 'iconCls', width: 100,
 74                                 formatter: function (value) {
 75                                     if (value!=null) {
 76                                         return '<span class="' + value+ '"></span>';
 77                                     }
 78                                 }
 79                             },
 80                             { title: '菜单路径', field: 'url', width: 100 },
 81                             { title: '是否选中', field: 'checked', width: 100 }
 82                         ]],
 83                         onContextMenu: function (e, row) {
 84                             e.preventDefault();
 85                             $(this).treegrid('unselectAll');
 86                             $(this).treegrid('select', row.id);
 87                             $('#tree_menu').menu('show', {
 88                                 left: e.pageX,
 89                                 top: e.pageY
 90                             });
 91                         }
 92            });
 93             //刷新treegrid数据
 94             $("#ref").click(function () {
 95                    treegrid.treegrid('reload');
 96                });
 97             //添加节点
 98             $("#add").click(function () {
 99                 //取得选中节点
100                 var node = treegrid.treegrid('getSelected');
101                 //清空表单数据
102                 $("#treegrid_form").form('clear');
103                 $("#no").attr("checked", "true");//添加节点--设置表单(菜单是否选中)--默认选择‘否’
104                 $("#menuPid").val(node.id); //设置将要添加节点 的 父节点编号
105                 $("#icon").combobox({
106                     //url: '../../Content/data/icondata.json',
107                     //valueField: 'id',
108                     //textField: 'text'
109                     data: iconData
110                 });
111                 treegrid_dialog = $(".treegrid_dialog").show().dialog({
112                     modal: true,
113                     title: '添加 ' + node.text + ' 节点的子节点',
114                     closed: false,
115                     width: 400,
116                     height: 250,
117                     cache: false,
118                     collapsible: true,
119                     maximizable: true,
120                     resizable: true,
121                     buttons: [{
122                         text: '保    存',
123                         plain:true,
124                         iconCls: 'icon-save',
125                         handler: function () {
126                             //数据验证 通过与否
127                             var validate = $("#treegrid_form").form('validate');
128                             if (validate == false) {
129                                 return false;
130                             }
131 
132                             $.ajax({
133                                 url: '/System/AddMenu',
134                                 data: $("#treegrid_form").serialize(),
135                                 type: 'POST',
136                                 cache: false,
137                                 dataType: 'json',
138                                 success: function (data) {
139                                     if (data && data.Success) {
140                                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
141                                         treegrid_dialog.dialog('close');
142                                         treegrid.treegrid('reload');
143                                     }
144                                     else {
145                                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
146                                         treegrid_dialog.dialog('close');
147                                         treegrid.treegrid('reload');
148                                     }
149                                 }
150                             });
151                         }
152                     }, {
153                         text: '取   消',
154                         iconCls: 'icon-redo',
155                         plain: true,
156                         handler: function () {
157                             treegrid_dialog.dialog('close');
158                         }
159                     }]
160                 });
161             });
162             //编辑节点
163             $("#edit").click(function () {
164                 //取得选中节点
165                 var node = treegrid.treegrid('getSelected');
166                 //清空表单数据
167                 $("#treegrid_form").form('clear');
168                 treegrid_dialog = $(".treegrid_dialog").show().dialog({
169                     modal: true,
170                     title: '编辑 ' + node.text + ' 节点',
171                     closed: false,
172                     width: 400,
173                     height: 250,
174                     cache: false,
175                     collapsible: true,
176                     maximizable: true,
177                     resizable: true,
178                     buttons: [{
179                         text: '保    存',
180                         plain:true,
181                         iconCls: 'icon-save',
182                         handler: function () {
183                             //数据验证 通过与否
184                             var validate = $("#treegrid_form").form('validate');
185                             if (validate == false) {
186                                 return false;
187                             }
188                             $.ajax({
189                                 url: '/System/EditMenu',
190                                 data: $("#treegrid_form").serialize(),
191                                 type: 'POST',
192                                 cache: false,
193                                 dataType: 'json',
194                                 success: function (data) {
195                                     if (data && data.Success) {
196                                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
197                                         treegrid_dialog.dialog('close');
198                                         treegrid.treegrid('reload');
199                                     }
200                                     else {
201                                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
202                                         treegrid_dialog.dialog('close');
203                                         treegrid.treegrid('reload');
204                                     }
205                                 }
206                             });
207                         }
208                     }, {
209                         text: '取   消',
210                         iconCls: 'icon-redo',
211                         plain: true,
212                         handler: function () {
213                             treegrid_dialog.dialog('close');
214                         }
215                     }]
216                 });
217                 //绑定编辑窗口表单数据
218                 $("#treegrid_form").form('load', node);
219             });
220             //删除节点
221             $("#delete").click(function () {
222                 //取得选中节点
223                 var node = treegrid.treegrid('getSelected');
224                 $.post('/System/DeleteMenu', { MId: node.MId }, function (data) {
225                     if (data && data.Success) {
226                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
227                         treegrid.treegrid('reload');
228                     }
229                     else {
230                         $.messager.show({ title: '提示', msg: '' + data.Msg + '', timeout: 5000, showType: 'slide' });
231                         treegrid.treegrid('reload');
232                     }
233                 });
234             });
235         });
View Code

3.后台Controller方法

  1        private SYS_UserLimitEntities db = new SYS_UserLimitEntities();
  2 
  3         public ActionResult Index()
  4         {
  5             return View();
  6         }
  7 
  8         #region 取得树形菜单 + ActionResult GetTree(string id)
  9         /// <summary>
 10         /// 取得树形菜单
 11         /// </summary>
 12         /// <param name="id">用户点击tree时,向后台访问父菜单编号</param>
 13         /// <returns></returns>
 14         [HttpPost]
 15         public ActionResult GetTree(string id)
 16         {
 17             try
 18             {
 19                 List<Menu> list = null;
 20                 //判断是否执行点击tree时,按需加载要扩展的菜单
 21                 if (id != null)
 22                 {
 23                     list = db.Menu.Where(a => a.pid == id).ToList();
 24                 }
 25                 else
 26                 {
 27                     list = db.Menu.Where(a => a.pid == "000").ToList();//取得根菜单
 28                 }
 29                 return Json(list);//返回easyui展示数据的json数据
 30             }
 31             catch (Exception)
 32             {
 33                 throw;
 34             }
 35         } 
 36         #endregion
 37 
 38         #region 添加菜单操作 + ActionResult AddMenu(Menu menu)
 39         /// <summary>
 40         /// 添加菜单操作
 41         /// </summary>
 42         /// <param name="menu">收集到的Menu菜单各个属性的值</param>
 43         /// <returns></returns>
 44         [HttpPost]
 45         public ActionResult AddMenu(Menu menu)
 46         {
 47             Messages m = new Messages();
 48             try
 49             {
 50                 string newid = null;//将要添加菜单的编号
 51                 //判断将要添加子菜单的父菜单状态是否为父菜单状态/否则修改
 52                 Menu me = db.Menu.Single(a => a.id == menu.pid);
 53                 if (me.state == "open")
 54                 {
 55                     me.state = "closed";
 56                 }
 57                 //取得将要添加子菜单同级菜单-----并倒序排列
 58                 var mlist = db.Menu.Where(a => a.pid == menu.pid).OrderByDescending(a => a.MId).ToList();
 59                 //判断与将要添加的子菜单的同级菜单数目是否为0
 60                 if (mlist.Count > 0)
 61                 {
 62                     //取得同级菜单编号最大的的最后 两位 以便计算出将要添加菜单编号
 63                     string id = mlist[0].id;
 64                     int i = Convert.ToInt32(id.Substring(id.Length - 2, 2)) + 1;
 65                     //限定每一个子菜单的数目不得超过99个
 66                     if (i == 100)
 67                     {
 68                         m.Msg = "该菜单的子菜单已经达到最大数目了,你可以选择创建其他菜单选项";
 69                         return Json(m);
 70                     }
 71                     //判断子菜单编号后两位是否为‘01’两位形式不是则补填为两位
 72                     newid = i > 9 ? mlist[0].pid + i.ToString() : mlist[0].pid + "0" + i.ToString();
 73                 }
 74                 else
 75                 {
 76                     newid = menu.pid + "01";//没有同级菜单时候就默认添加菜单的编号为 父菜单编号+‘01’
 77                 }
 78                 //修改将要添加菜单的菜单编号
 79                 menu.id = newid;
 80                 menu.state = "open";
 81                 //写入数据库
 82                 db.Menu.Add(menu);
 83 
 84                 db.SaveChanges();
 85                 m.Msg = "成功的添加["+menu.text+"]的菜单节点信息!";
 86                 m.Success = true;
 87                 return Json(m);
 88             }
 89             catch (Exception ex)
 90             {
 91                 m.Msg = "添加失败!" + ex.Message;
 92                 return Json(m);
 93             }
 94         } 
 95         #endregion
 96 
 97         #region 编辑菜单操作 + ActionResult EditMenu(Menu menu)
 98         /// <summary>
 99         /// 编辑菜单操作
100         /// </summary>
101         /// <param name="menu">收集表单Menu数据</param>
102         /// <returns></returns>
103         [HttpPost]
104         public ActionResult EditMenu(Menu menu)
105         {
106             Messages m = new Messages();
107             try
108             {
109                 //将要修改的菜单添加到EF容器
110                 DbEntityEntry<Menu> entry = db.Entry<Menu>(menu);
111                 //设置包装类对象状态为unchanged
112                 entry.State = System.Data.EntityState.Unchanged;
113                 //设置改变的属性
114                 entry.Property(a => a.text).IsModified = true;
115                 entry.Property(a => a.url).IsModified = true;
116                 entry.Property(a => a.@checked).IsModified = true;
117                 entry.Property(a => a.iconCls).IsModified = true;
118                 //提交数据库
119                 db.SaveChanges();
120                 m.Msg = "节点["+menu.text+"]的信息修改成功!";
121                 m.Success = true;
122                 return Json(m);
123             }
124             catch (Exception ex)
125             {
126                 m.Msg = "修改失败!" + ex.Message;
127                 return Json(m);
128             }
129         }
130         #endregion
131 
132         #region 删除菜单操作 + ActionResult DeleteMenu(int MId)
133         /// <summary>
134         /// 删除菜单操作
135         /// </summary>
136         /// <param name="MId">将要删除的菜单编号</param>
137         /// <returns></returns>
138         [HttpPost]
139         public ActionResult DeleteMenu(int MId)
140         {
141             Messages m = new Messages();
142             try
143             {
144                 //取得将要删除的实体对象
145                 Menu menu = db.Menu.Single(a => a.MId == MId);
146                 // 删除项有--子菜单时
147                 /*
148                  * 从选中的节点开始,将其节点以及其一下节点都删除
149                  * --无论从那个节点开始删除都能自如的将其子菜单以及子子菜单删除,以此类推
150                 */
151                 List<Menu> mlist = db.Menu.Where(a => a.id.IndexOf(menu.id)>=0).ToList();
152                 if (mlist.Count>0)
153                 {
154                     foreach (var item in mlist)
155                     {
156                         db.Menu.Remove(item);
157                     }
158                 }
159                 db.Menu.Remove(menu);
160                 db.SaveChanges();
161                 m.Msg = "节点已经被成功删除!";
162                 m.Success = true;
163                 return Json(m);
164             }
165             catch (Exception ex)
166             {
167                 m.Msg = "删除失败!" + ex.Message;
168                 return Json(m);
169             }
170         }
171         #endregion
View Code

效果图如下:

 

 实例下载地址:

http://pan.baidu.com/share/link?shareid=512055&uk=2804979851

功能自己捣鼓,不足之处还望各位看客指出修正。

posted @ 2013-06-02 15:45  PAGE珑夫  阅读(2637)  评论(6编辑  收藏  举报