您好,登錄后才能下訂單哦!
近花了不少時間在重構(gòu)和進一步提煉我的Web開發(fā)框架上,力求在用戶體驗和界面設(shè)計方面,和Winform開發(fā)框架保持一致,而在Web上,我主要采用EasyUI的前端界面處理技術(shù),走MVC的技術(shù)路線,在重構(gòu)完善過程中,很多細節(jié)花費不少時間進行研究和提煉,一步步走過來,也積累了不少經(jīng)驗,本系列將主要介紹我在進一步完善我的Web框架基礎(chǔ)上積累的經(jīng)驗進行分享,本隨筆主要介紹使用如何使用Json實體類構(gòu)建菜單數(shù)據(jù),然后在主界面中進行使用。
菜單的界面效果如下所示,菜單分為一級菜單、二級菜單、三級菜單,他們各自在位置上是不同的定義,這個界面布局規(guī)定三級菜單就是最小的菜單節(jié)點了,也就是葉子節(jié)點。
要實現(xiàn)以上的菜單,需要把菜單定義成相關(guān)的Json數(shù)據(jù),然后通過腳本把它們添加到界面里面去,如下數(shù)據(jù)和腳本就是定義相關(guān)的菜單數(shù)據(jù)的。
<script type="text/javascript"> var _menus = { "default": [ { "menuid": "1", "icon": "icon-computer", "menuname": "權(quán)限管理", "menus": [ { "menuid": "13", "menuname": "用戶管理", "icon": "icon-user", "url": "/User/Index" }, { "menuid": "14", "menuname": "組織機構(gòu)管理", "icon": "icon-organ", "url": "/OU/Index" }, { "menuid": "15", "menuname": "角色管理", "icon": "icon-group-key", "url": "/Role/Index" }, { "menuid": "16", "menuname": "功能管理", "icon": "icon-key", "url": "/Function/Index" }, { "menuid": "17", "menuname": "登陸日志", "icon": "icon-view", "url": "/LoginLog/Index" } ] }, { "menuid": "2", "icon": "icon-user", "menuname": "其他管理", "menus": [{ "menuid": "21", "menuname": "修改密碼", "icon": "icon-lock", "url": "javascript:ShowPasswordDialog()" } ] } ], "point": [ { "menuid": "3", "icon": "icon-computer", "menuname": "事務(wù)中心", "menus": [ { "menuid": "33", "menuname": "測試菜單1", "icon": "icon-user", "url": "../Commonpage/building.htm" }, { "menuid": "34", "menuname": "測試菜單2", "icon": "icon-organ", "url": "../Commonpage/building.htm" }, { "menuid": "35", "menuname": "測試菜單3", "icon": "icon-group-key", "url": "../Commonpage/building.htm" }, { "menuid": "36", "menuname": "測試菜單4", "icon": "icon-key", "url": "../Commonpage/building.htm" } ] }, { "menuid": "4", "icon": "icon-user", "menuname": "其他菜單", "menus": [{ "menuid": "41", "menuname": "測試菜單5", "icon": "icon-lock", "url": "../Commonpage/building.htm" }] } ] }; function showSubMenu(url, title, menuCategory, defaultIcon) { if (defaultIcon == null || defaultIcon == "") { defaultIcon = "icon-table"; } addTab(title, url, "icon " + defaultIcon); Clearnav(); if (menuCategory != "") { addNav(_menus[menuCategory]); } } </script>
從上面的菜單Json數(shù)據(jù)來看,它是一個字典的Json數(shù)據(jù)列表,在Web界面上,通過下面的代碼可以展開上面Json定義的二級菜單。
<li><a href="#" onclick="showSubMenu('/User/Index', '用戶管理', 'default')">權(quán)限管理</a></li>
雖然上面的定義的數(shù)據(jù)能夠解決菜單的顯示問題,但是對于我們需要動態(tài)控制的菜單,顯然做不到,因此需要把上面的json數(shù)據(jù),通過菜單控制器進行動態(tài)生成才可以,然后在腳本里面通過Jquery的方式獲取Json數(shù)據(jù),如下所示。
var _menus = {}; //同步獲取 $.ajax({ type: 'GET', url: '/Menu/GetMenuData?r=' + Math.random(), async: false,//同步 dataType: 'json', success: function (json) { _menus = json; }, error: function (xhr, status, error) { alert("操作失敗"); //xhr.responseText } });
上面的GetMenuData方法,通過后臺的控制器進行動態(tài)生成的,它的代碼如下所示
/// <summary> /// 獲取樹形展示數(shù)據(jù) /// </summary> /// <returns></returns> public ActionResult GetMenuData() { string json = GetTreeJson("-1", "", ""); json = json.Trim(','); return Content(string.Format("[{0}]", json)); } /// <summary> /// 遞歸獲取樹形信息 /// </summary> /// <returns></returns> private string GetTreeJson(string PID, string folderIcon, string leafIcon) { string condition = string.Format("PID='{0}' ", PID); List<MenuInfo> nodeList = BLLFactory<Menu>.Instance.Find(condition); StringBuilder content = new StringBuilder(); foreach (MenuInfo model in nodeList) { string ParentID = (model.PID == "-1" ? "0" : model.PID); string subMenu = this.GetTreeJson(model.ID, folderIcon, leafIcon); string parentMenu = string.Format("{{ \"id\":\"{0}\", \"pId\":\"{1}\", \"name\":\"{2}\" ", model.ID, ParentID, model.Name); if (string.IsNullOrEmpty(subMenu)) { if (!string.IsNullOrEmpty(leafIcon)) { parentMenu += string.Format(",\"icon\":\"{0}\" }},", leafIcon); } else { parentMenu += "},"; } } else { if (!string.IsNullOrEmpty(folderIcon)) { parentMenu += string.Format(",\"icon\":\"{0}\" }},", folderIcon); } else { parentMenu += "},"; } } content.AppendLine(parentMenu.Trim()); content.AppendLine(subMenu.Trim()); } return content.ToString().Trim(); }
不過對于上面的代碼,我覺得雖然能解決問題,能夠正確生成相關(guān)的Json代碼,但是感覺不夠優(yōu)雅,我不喜歡使用拼湊方法構(gòu)建數(shù)據(jù)。
前面看了Menu的Json腳本,我說過他是一個字典類型的Json數(shù)據(jù)格式,那么我們是否可以通過字典和實體信息來承載,然后直接通過ToJson方法出來呢?答案是可以的。
/// <summary> /// 獲取菜單的樹形展示數(shù)據(jù) /// </summary> /// <returns></returns> public ActionResult GetMenuData() { Dictionary<string, List<MenuData>> dict = new Dictionary<string, List<MenuData>>(); List<MenuInfo> list = BLLFactory<Menu>.Instance.GetTopMenu(MyConstants.SystemType); int i = 0; foreach (MenuInfo info in list) { if (!HasFunction(info.FunctionId)) { continue; } List<MenuData> treeList = new List<MenuData>(); List<MenuNodeInfo> nodeList = BLLFactory<Menu>.Instance.GetTreeByID(info.ID); foreach (MenuNodeInfo nodeInfo in nodeList) { if (!HasFunction(nodeInfo.FunctionId)) { continue; } MenuData menuData = new MenuData(nodeInfo.ID, nodeInfo.Name, string.IsNullOrEmpty(nodeInfo.WebIcon) ? "icon-computer" : nodeInfo.WebIcon); foreach (MenuNodeInfo subNodeInfo in nodeInfo.Children) { if (!HasFunction(subNodeInfo.FunctionId)) { continue; } string icon = string.IsNullOrEmpty(subNodeInfo.WebIcon) ? "icon-organ" : subNodeInfo.WebIcon; menuData.menus.Add(new MenuData(subNodeInfo.ID, subNodeInfo.Name, icon, subNodeInfo.Url)); } treeList.Add(menuData); } //添加到字典里面,如果是第一個,默認用default名稱 string dictName = (i++ == 0) ? "default" : info.ID; dict.Add(dictName, treeList); } string content = ToJson(dict); return Content(content.Trim(',')); }
上面的代碼,通過MenuData的對象數(shù)據(jù),來承載相關(guān)的菜單信息,然后把它添加到字典Dictionary<string, List<MenuData>> dict 里面就可以了,這樣的代碼,沒有那么多拼湊出來的感覺,是不是很好看呢?把對象轉(zhuǎn)換為Json數(shù)據(jù),直接通過ToJson就可以解決了,很簡單吧。
而菜單的權(quán)限控制,就是通過集合權(quán)限管理進行判斷,父菜單如果沒有權(quán)限,就直接跳過,不在繼續(xù)生成下面的子菜單,權(quán)限判斷的如下所示。
if (!HasFunction(info.FunctionId)) { continue; }
當(dāng)然,在界面上展開二級菜單的操作界面,也應(yīng)該通過腳本動態(tài)進行生成的,這樣才能做到所有的內(nèi)容動態(tài)構(gòu)建。
<ul class="navigation" > @Html.Raw(@ViewBag.HeaderScript)</ul>
上面使用ViewBag對象進行傳遞腳本內(nèi)容到界面上,其實后臺生成的操作,是一行HTML代碼就是了,代碼類似下面的內(nèi)容。
<li><a href="#" onclick="showSubMenu('/User/Index', '用戶管理', 'default')">權(quán)限管理</a></li>
最后出來的效果,就是博客開始介紹的界面截圖,沒有任何變化,但是代碼我們已經(jīng)經(jīng)過了幾步的優(yōu)化整理,看起來很清爽,更能實現(xiàn)動態(tài)變化了。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。