這一篇,介紹菜單的管理功能。
上一篇中,我們完成了過渡,明白了本例是通過讀取xml文件的方式加載菜單到easyui的tree控件上的。也自己模擬了而一個菜單(手動創建),菜單最終肯定是要從數據庫中加載而得,由於數據庫目前是空的,暫時不做這一塊的東西。等到項目最後再回頭做。這裏使用這個模擬的菜單做 菜單的創建工作。
按照習慣,從後往前書寫,做菜單管理就是對Menu_list的正刪改查:
Service層:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Arise.Model;
using Arise.Common;
namespace Arise.Service
{
public class Menu_List_Service
{
public IList<Menu_List> GetAllMenuList()
{
using(AriseEntities ariseEntities = new AriseEntities())
{
return ariseEntities.Menu_List.ToList();
}
}
public Menu_List GetMenuListById(Guid MenuListId)
{
using(AriseEntities ariseEntities = new AriseEntities())
{
return ariseEntities.Menu_List.Where(ml => ml.Menu_List_Id == MenuListId).FirstOrDefault();
}
}
public void SaveMenuList(Menu_List menuList,string saveType)
{
using(AriseEntities ariseEntities = new AriseEntities())
{
try
{
if(saveType.ToUpper() == "ADD")
{
ariseEntities.Menu_List.Add(menuList);
}
else
{
ariseEntities.Entry(menuList).State = System.Data.Entity.EntityState.Modified;
}
ariseEntities.SaveChanges();
}
catch(Exception ex)
{
throw ex;
}
}
}
public void DeleteMenuList(Guid menuListId)
{
using(AriseEntities ariseEntities = new AriseEntities())
{
//這裏最好加上當前刪除的鏈接是否有用戶在使用的業務
//....
Menu_List menuList = ariseEntities.Menu_List.Where(ml => ml.Menu_List_Id == menuListId).FirstOrDefault();
ariseEntities.Entry(menuList).State = System.Data.Entity.EntityState.Deleted;
ariseEntities.SaveChanges();
}
}
}
}
上面的方法很明顯了,
GetAllMenuList():獲取所有菜單,裝載到list集合中。
GetMenuListById():通過Id獲取Menu對象。
SaveMenuList():新增和修改Menu,這裏通過字段saveType來判斷是新增還是修改Menu。
DeleteMenuList():刪除Menu,這裏做的不是很完善,當期按鈕若存在用戶使用時,不應該刪除成功的,但是這裏沒做這個業務,有興趣的可以自己判斷一下,就是去關聯查詢Menu_List_Access,若存在則不允許刪除即可。
Manager層:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Arise.Model;
using Arise.Service;
namespace Arise.Manager
{
public class Menu_List_Manager
{
private Menu_List_Service menuListService = new Menu_List_Service();
public IList<Menu_List> GetAllMenuList()
{
return menuListService.GetAllMenuList();
}
public Menu_List GetMenuListById(string MenuListId)
{
if (MenuListId == "")
{
return null;
}
return menuListService.GetMenuListById(Guid.Parse(MenuListId));
}
public void SaveMenuList(Menu_List menuList, string saveType)
{
try
{
menuListService.SaveMenuList(menuList,saveType);
}
catch(Exception ex)
{
throw ex;
}
}
public void DeleteMenuList(string menuListId)
{
if (menuListId != "")
{
menuListService.DeleteMenuList(Guid.Parse(menuListId));
}
}
}
}
這裏什麼贅述的,就是簡單的調用,值得一提的是,因爲數據庫Id字段爲uniqueidentifier,這裏需要使用Guid。
重點來了,一大波代碼正在前進:
我先將Controller的代碼和View的發出來,兩相結合,講解:
Controller層:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Arise.Common;
using Arise.Model;
using Arise.Manager;
namespace Arise.Web.Controllers
{
public class AdminController : BaseController
{
//
// GET: /Admin/
public ActionResult Home()
{
User_Master userMaster = (User_Master)Session["UserMaster"];
ViewBag.User = userMaster.User_Name;
ViewBag.Date = DateTime.Now;
string userMasterId = userMaster.User_Master_Id.ToString();
string userMenuPath = System.Configuration.ConfigurationManager.AppSettings["UserMenuPath"].ToString().Trim();
string xmlPath = userMenuPath + userMasterId + ".xml";
ViewBag.MenuTreeList = MenuXMLHelper.LoadMenuXML(xmlPath);
return View();
}
public ActionResult Index()
{
return View();
}
#region Menu List Page
public ActionResult MenuList()
{
return View();
}
/*
*獲取菜單信息,並將菜單信息拼接成tree能夠識別的字符串
* */
public string GeneratePermission()
{
string type = Request.Params["Type"].ToString().Trim();
Menu_List_Manager menuListManager = new Menu_List_Manager();
List<Menu_List> listMenu = menuListManager.GetAllMenuList().ToList();
string permissionList = "[";
//若menu_Level爲空則表示爲菜單父分類
var parentlist = listMenu.Where(p => p.Menu_Level.ToString() == "").OrderBy(p => p.Serial).ToList();
for (int i = 0; i < parentlist.Count; i++)
{
if (type != "")//表示爲菜單管理頁面
{
permissionList += "{\"id\":\"" + parentlist[i].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + parentlist[i].Menu_Name.ToString().Trim() + " /Serial:" + parentlist[i].Serial.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"1\"}";
}
else//表示爲菜單權限分配頁面
{
permissionList += "{\"id\":\"" + parentlist[i].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + parentlist[i].Menu_Name.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"1\"}";
}
//若menu_list不爲空,則爲父分類的ID,
var childlist = listMenu.Where(p => p.Menu_Level == parentlist[i].Menu_List_Id.ToString()).OrderBy(p => p.Serial).ToList();
if (childlist.Count != 0)
{
permissionList += ",\"children\":[";
}
for (int j = 0; j < childlist.Count; j++)
{
if (type != "")
{
permissionList += "{\"id\":\"" + childlist[j].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + childlist[j].Menu_Name.ToString().Trim() + " /Serial:" + childlist[j].Serial.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"2\"}},";
}
else
{
permissionList += "{\"id\":\"" + childlist[j].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + childlist[j].Menu_Name.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"2\"}},";
}
if (childlist.Count != 0 && j == childlist.Count - 1)
{
permissionList = permissionList.Substring(0, permissionList.Length - 1);
permissionList += "]";
}
}
permissionList += "},";
}
permissionList = permissionList.Substring(0, permissionList.Length - 1);
permissionList += "]";
return permissionList;
}
public JsonResult SaveMenuList()
{
try
{
string saveType = Request.Params["SaveType"].ToString().Trim();
string menuListId = Request.Params["MenuListId"].ToString().Trim();
string requestURL = Request.Params["RequestURL"].ToString().Trim();
string menuName = Request.Params["MenuName"].ToString().Trim();
int serial = Utility.ConvertToInt32(Request.Params["Serial"].ToString().Trim());
string menuLevel = Request.Params["MenuLevel"].ToString().Trim();
string iconName = "icon-system";
Menu_List_Manager menuListManager = new Menu_List_Manager();
Menu_List menuList = null;
if (menuListId != null)
{
menuList = menuListManager.GetMenuListById(menuListId);
}
if (saveType.ToUpper() == "ADD")
{
if (menuList != null)
{
Utility.ReturnJsonResult("0", UserMessageShow.Invaild);
}
menuList = new Menu_List();
menuList.Menu_List_Id = Guid.NewGuid();
menuList.Request_URL = requestURL;
menuList.Menu_Name = menuName;
menuList.Menu_Level = menuLevel;
menuList.Serial = serial;
menuList.Icon_Name = iconName;
}
else
{
if (menuList == null)
{
Utility.ReturnJsonResult("0", UserMessageShow.Invaild);
}
menuList.Request_URL = requestURL;
menuList.Menu_Name = menuName;
menuList.Menu_Level = menuLevel;
menuList.Serial = serial;
menuList.Icon_Name = iconName;
}
menuListManager.SaveMenuList(menuList, saveType);
return Utility.ReturnJsonResult("1", UserMessageShow.SaveSuccess);
}
catch(Exception ex)
{
return Utility.ReturnJsonResult("0",ex.Message);
}
}
public JsonResult GetMenuByMenuId()
{
try
{
string menuListId = Request.Params["MenuListId"].ToString().Trim();
Menu_List_Manager menuListManager = new Menu_List_Manager();
Menu_List menuList = menuListManager.GetMenuListById(menuListId);
return Utility.ReturnJsonResult<Menu_List>(menuList);
}
catch(Exception ex)
{
return Utility.ReturnJsonResult("0",ex.Message);
}
}
public JsonResult DeleteMenuByMenuId()
{
string menuListId = Request.Params["MenuListId"].ToString().Trim();
Menu_List_Manager menuListManager = new Menu_List_Manager();
menuListManager.DeleteMenuList(menuListId);
return Utility.ReturnJsonResult("0", UserMessageShow.DeleteSuccess);
}
#endregion
}
}
在代碼段#region Menu List Page下爲MenuList頁面對應的action。
View層:
@{
ViewBag.Title = "Menu List";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript">
function AddParentMenu()
{
$("#AddMenuInformation").dialog({
title: 'Add Menu Information',
width: 500,
height: 250
});
$('#trParentName').css("display", "none");
$('#trRequestURL').css("display", "none");
$('#hfSaveType').val("ADD");
$('#hfParentId').val("");
$("#txtMenuName").focus();
$('#txtParentMenuName').val("");
$('#hfMenuId').val("");
$('#txtMenuName').val('');
$('#txtMenuRequestURL').val('');
$('#txtSerialNumber').val('');
$("#AddMenuInformation").dialog('open');
}
function AddMenu() {
var node = $('#tt').tree('getSelected');
if (node == null) {
alert("Please select a menu Item!");
}
if (node.attributes.level == "2") {
alert("This menu can not be added child menu!");
return;
}
$('#hfParentId').val(node.id);
$("#AddMenuInformation").dialog({
title: 'Add Menu Information',
width: 500,
height: 250
});
$('#trParentName').css("display", "");
$('#trRequestURL').css("display", "");
$('#hfSaveType').val("ADD");
$("#txtMenuName").focus();
$('#txtParentMenuName').val(node.text.substring(0, node.text.indexOf("/")));
$('#hfMenuId').val("");
$('#txtMenuName').val('');
$('#txtMenuRequestURL').val('');
$('#txtSerialNumber').val('');
$("#AddMenuInformation").dialog('open');
}
function SaveMenuInfo() {
var type = $('#hfSaveType').val();
var menuId = $('#hfMenuId').val();
var parentMenuId = $('#hfParentId').val();
var menuName = $('#txtMenuName').val();
var menuRequestURL = $('#txtMenuRequestURL').val();
var serialNumber = $('#txtSerialNumber').val();
$.ajax({
url: '/Admin/SaveMenuList',
data: {
SaveType: type, MenuListId: menuId, MenuLevel: parentMenuId, MenuName: menuName, RequestURL: menuRequestURL, Serial: serialNumber
},
type: 'post',
dataType: 'json',
success: function (data) {
if (data.result == "0") {
alert(data.message);
} else {
$("#AddMenuInformation").dialog('close');
alert(data.message);
$('#tt').tree('reload');
}
}
});
}
function DeleteMenu() {
var node = $('#tt').tree('getSelected');
if (node.attributes.level == "1") {
alert("This menu can not be deleted!");
return;
}
if (confirm("Are you sure delete this menu?")) {
$.ajax({
url: '/Admin/DeleteMenuByMenuId',
data: {
MenuListId: node.id
},
type: 'post',
dataType: 'json',
success: function (data) {
if (data.result == "0") {
alert(data.message);
$('#tt').tree('reload');
} else {
alert(data.message);
}
}
});
}
}
function EditMenu() {
var node = $('#tt').tree('getSelected');
if (node == null) {
alert("Please select a menu Item!");
}
if (node.attributes.level == "1") {
return;
}
var nodeParent = $('tt').tree('getParent', node.target)
$('#hfMenuId').val(node.id);
$('#hfParentId').val(nodeParent.id);
$.ajax({
url: '/Admin/GetMenuByMenuId',
data: {
MenuListId: node.id
},
type: 'post',
dataType: 'json',
success: function (data) {
if (data.result == "1") {
alert(data.message);
} else {
$("#AddMenuInformation").dialog({
title: 'Edit Menu Information',
width: 500,
height: 250
});
$('#trParentName').css("display", "");
$('#trRequestURL').css("display", "");
$('#hfSaveType').val("Update");
$('#txtParentMenuName').val(nodeParent.text.substring(0, nodeParent.text.indexOf("/")));
$('#txtMenuName').val(data.Menu_Name);
$('#txtMenuRequestURL').val(data.Request_URL);
$('#txtSerialNumber').val(data.Serial);
$("#AddMenuInformation").dialog('open');
}
}
});
}
</script>
<div style="padding-top: 2px; padding-left: 2px;font-size:8px;">
<div id="dQueryPermissionList" class="easyui-panel" style="float: left; width: 360px; height: 'auto';
padding: 10px; background-color: #FFFFFF;" title="Menu List">
<div style="width: 330px; height: 450px; overflow: auto;">
<ul id="tt" class="easyui-tree" data-options="url:'/Admin/GeneratePermission?Type=S',method:'get',animate:true"></ul>
</div>
</div>
<div style="margin-top:15px;">
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-add'" onclick="AddMenu();" style="margin-right: 18px;">Add</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-edit'" onclick="EditMenu();" style="margin-right: 18px;">Edit</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" onclick="DeleteMenu();" style="margin-right: 18px;">Delete</a>
<a href="#" class="easyui-linkbutton" data-options="iconCls:'icon-cancel'" onclick="AddParentMenu();" style="margin-right: 18px;">AddParentMenu</a>
</div>
<div id="AddMenuInformation" class="easyui-dialog" closed="true" buttons="#AddMenuInformation-Buttons"
style="padding: 10px 20px">
<table>
<tr id="trParentName">
<td>
Parent Menu Name:
</td>
<td>
<input type="text" id="txtParentMenuName" name="txtParentMenuName" class="easyui-textbox" style="width: 238px" readonly="readonly" />
<input type="hidden" id="hfParentId" name="hfParentId" />
<input type="hidden" id="hfMenuId" name="hfMenuId" />
<input type="hidden" id="hfSaveType" name="hfSaveType" />
</td>
</tr>
<tr>
<td>
Menu Name:
</td>
<td>
<input type="text" id="txtMenuName" name="txtMenuName" class="easyui-textbox" style="width: 238px" />
</td>
</tr>
<tr id="trRequestURL">
<td>
Menu Request URL:
</td>
<td>
<input type="text" id="txtMenuRequestURL" name="txtMenuRequestURL" class="easyui-textbox" style="width: 238px" />
</td>
</tr>
<tr>
<td>
Serial Number:
</td>
<td>
<input type="text" id="txtSerialNumber" name="txtSerialNumber" class="easyui-textbox" style="width: 238px" onkeyup="onlyNumber(this)" onafterpaste="onlyNumber(this)" />
</td>
</tr>
</table>
</div>
<div id="AddMenuInformation-Buttons">
<a href="#" class="easyui-linkbutton" iconcls="icon-ok" onclick="SaveMenuInfo();">
Save
</a> <a href="#" class="easyui-linkbutton" iconcls="icon-cancel" onclick="javascript: $('#AddMenuInformation').dialog('close');">
Close
</a>
</div>
</div>
頁面顯示:
好了,代碼貼完了,講解開始,
在頁面我們看到tree是通過下面這個代碼加載的:
<div style="width: 330px; height: 400px; overflow: auto;">
<ul id="tt" class="easyui-tree" data-options="url:'/Admin/GeneratePermission?Type=S',method:'get',animate:true"></ul>
</div>
在頁面easyui通過tree控價訪問url獲取菜單信息,最終展示,這個返回的數據easyui是有規範的,他給提供一些可選參數,大致類似這種:
[{
"id":"5686e272-cc26-4039-8519-705baa2ab88d",
"text":"Setting /Serial:1",
"iconCls":"icon-system",
"children":[{
"id":"9c40bb25-92cb-40c8-a7cf-59f2e11c89ba",
"text":"Test /Serial:1",
"iconCls":"icon-system",
"attributes":{"level":"2"}},
{"id":"dc686259-11dc-4dbf-997f-c823c55387fd",
"text":"Test2 /Serial:2",
"iconCls":"icon-system",
"attributes":{"level":"2"}}]
}]
一串json,這個參數標準是easyui提供的,不是我們隨意定義的,這個具體還有那些參數可選呢?
每個節點可以包括下列屬性:(這個是easyui官網提供的可選參數)
id:節點的 id,它對於加載遠程數據很重要。
text:要顯示的節點文本。
state:節點狀態,’open’ 或 ‘closed’,默認是 ‘open’。當設置爲 ‘closed’ 時,該節點有子節點,並且將從遠程站點加載它們。
checked:指示節點是否被選中。
attributes:給一個節點添加的自定義屬性。
children:定義了一些子節點的節點數組
官網提供的一個Demo:
[{
"id":1,
"text":"Folder1",
"iconCls":"icon-save",
"children":[{
"text":"File1",
"checked":true
},{
"text":"Books",
"state":"open",
"attributes":{
"url":"/demo/book/abc",
"price":100
},
"children":[{
"text":"PhotoShop",
"checked":true
},{
"id": 8,
"text":"Sub Bookds",
"state":"closed"
}]
}]
},{
"text":"Languages",
"state":"closed",
"children":[{
"text":"Java"
},{
"text":"C#"
}]
}]
根據你項目的需要你可以選擇性的添加或是刪除某些不重要的屬性。所以這裏你應該知道了,服務器端有兩種實現方式,一種是你建立對應的Model,然後使用Utility裏面的Object直接轉成json;一種是自己拼接字符串。
第二種看似很傻,但是對於這種複用不是很強的業務,是沒必要建立Model的,所以這裏直接拼接字符串。
獲取所有列表,並將列表信息,轉換成easyui的tree等夠識別的json字符:
public string GeneratePermission()
{
string type = Request.Params["Type"].ToString().Trim();
Menu_List_Manager menuListManager = new Menu_List_Manager();
List<Menu_List> listMenu = menuListManager.GetAllMenuList().ToList();
string permissionList = "[";
//若menu_Level爲空則表示爲菜單父分類
var parentlist = listMenu.Where(p => p.Menu_Level.ToString() == "").OrderBy(p => p.Serial).ToList();
for (int i = 0; i < parentlist.Count; i++)
{
if (type != "")//表示爲菜單管理頁面
{
permissionList += "{\"id\":\"" + parentlist[i].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + parentlist[i].Menu_Name.ToString().Trim() + " /Serial:" + parentlist[i].Serial.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"1\"}";
}
else//表示爲菜單權限分配頁面
{
permissionList += "{\"id\":\"" + parentlist[i].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + parentlist[i].Menu_Name.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"1\"}";
}
//若menu_list不爲空,則爲父分類的ID,
var childlist = listMenu.Where(p => p.Menu_Level == parentlist[i].Menu_List_Id.ToString()).OrderBy(p => p.Serial).ToList();
if (childlist.Count != 0)
{
permissionList += ",\"children\":[";
}
for (int j = 0; j < childlist.Count; j++)
{
if (type != "")
{
permissionList += "{\"id\":\"" + childlist[j].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + childlist[j].Menu_Name.ToString().Trim() + " /Serial:" + childlist[j].Serial.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"2\"}},";
}
else
{
permissionList += "{\"id\":\"" + childlist[j].Menu_List_Id.ToString().Trim() + "\",\"text\":\"" + childlist[j].Menu_Name.ToString().Trim() + "\",\"iconCls\":\"" + parentlist[i].Icon_Name.ToString().Trim() + "\",\"attributes\":{\"level\":\"2\"}},";
}
if (childlist.Count != 0 && j == childlist.Count - 1)
{
permissionList = permissionList.Substring(0, permissionList.Length - 1);
permissionList += "]";
}
}
permissionList += "},";
}
permissionList = permissionList.Substring(0, permissionList.Length - 1);
permissionList += "]";
return permissionList;
}
這裏有兩個關鍵的點,需要略作解釋:
var parentlist = listMenu.Where(p => p.Menu_Level.ToString() == "").OrderBy(p => p.Serial).ToList();
取出所有父節點,並根據Serial排序。
這裏是使用linq將集合中符合條件的對象篩選出來,所以以後不要別人問你linq,你就只知道linq to ef。這是不全面的。linq不止有跟EF連用哦,功能強大着呢。
var childlist = listMenu.Where(p => p.Menu_Level == parentlist[i].Menu_List_Id.ToString()).OrderBy(p => p.Serial).ToList();
這裏是將當前父節點的所有子節點取出來。
這列的type參數你可能會有點迷惑,這個是添加用來區分做權限分配時候顯示的那個tree的。因爲做權限分配的時候也需要顯示一個tree結構,重寫一個方法又太麻煩了,所以都在這個方法裏寫了,這樣可能會對你現在造成一些麻煩,這樣,你看着太亂,就現將判斷type的那部分刪了,這樣就清晰了。
顯示講完之後,好像就沒什麼好講的了,添加和修改公用的同一個方法,添加父節點,跟添加子節點不太一下,所以就專門開了一個按鈕,這裏你可能遇到的問題就是easyui的dialg控件了。這個是easyui固定的寫法格式,自己多看兩遍熟悉一下就好了,基本用法都在代碼中了,這裏不過多解釋,希望可以自己鑽研一番。謝謝大家