角色配置菜单完成,处理了几个ToDo

This commit is contained in:
summer853300975 2016-11-07 21:41:17 +08:00
parent 3dffd04718
commit 6e1a306ac6
13 changed files with 314 additions and 95 deletions

View File

@ -264,6 +264,7 @@
<Content Include="Views\Admin\Profiles.cshtml" /> <Content Include="Views\Admin\Profiles.cshtml" />
<Content Include="Views\Shared\Footer.cshtml" /> <Content Include="Views\Shared\Footer.cshtml" />
<Content Include="Views\Shared\MenuTree.cshtml" /> <Content Include="Views\Shared\MenuTree.cshtml" />
<Content Include="Views\Shared\NavigatorConfig.cshtml" />
<Content Include="Views\Shared\SubNavigation.cshtml" /> <Content Include="Views\Shared\SubNavigation.cshtml" />
<Content Include="Views\Shared\SubMenu.cshtml" /> <Content Include="Views\Shared\SubMenu.cshtml" />
<Content Include="Views\Shared\SubMenuTree.cshtml" /> <Content Include="Views\Shared\SubMenuTree.cshtml" />

View File

@ -310,4 +310,19 @@
Group.saveGroupsByRoleId = function (roleId, groupIds, callback) { Group.saveGroupsByRoleId = function (roleId, groupIds, callback) {
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", groupIds: groupIds } }); processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", groupIds: groupIds } });
}; };
htmlTemplateForMenu='<li class="dd-item dd3-item" data-id="{0}"><div class="dd-handle dd3-handle"></div><div class="dd3-content"><label><input name="menuParent" type="checkbox" value="{0}" {2} /><input type="radio" name="menu" value="{0}" {2} /><span>{1}</span></label></div></li>';
//Menus
Menu = {
url: '../api/Menus/', title: "授权菜单", html: function (result) {
return $.map(result, function (element, index) {
return $.format(htmlTemplateForMenu, element.ID, element.Name, element.Active);
}).join('');
}
}
Menu.getMenusByRoleId = function (roleId, callback) {
processData.call(this, { Id: roleId, callback: callback, data: { type: "role" } });
};
Menu.saveMenusByRoleId = function (roleId, menuIds, callback) {
processData.call(this, { Id: roleId, callback: callback, method: "PUT", data: { type: "role", menuIds:menuIds } });
};
})(jQuery); })(jQuery);

View File

@ -7,94 +7,94 @@ using System.Web.Http;
namespace Bootstrap.Admin.Controllers namespace Bootstrap.Admin.Controllers
{ {
public class GroupsController : ApiController public class GroupsController : ApiController
{ {
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public QueryData<Group> Get([FromUri]QueryGroupOption value) public QueryData<Group> Get([FromUri]QueryGroupOption value)
{ {
return value.RetrieveData(); return value.RetrieveData();
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <returns></returns> /// <returns></returns>
[HttpGet] [HttpGet]
public Group Get(int id) public Group Get(int id)
{ {
return GroupHelper.RetrieveGroups().FirstOrDefault(t => t.ID == id); return GroupHelper.RetrieveGroups().FirstOrDefault(t => t.ID == id);
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="value"></param> /// <param name="value"></param>
[HttpPost] [HttpPost]
public bool Post([FromBody]Group value) public bool Post([FromBody]Group value)
{ {
return GroupHelper.SaveGroup(value); return GroupHelper.SaveGroup(value);
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
[HttpDelete] [HttpDelete]
public bool Delete([FromBody]string value) public bool Delete([FromBody]string value)
{ {
return GroupHelper.DeleteGroup(value); return GroupHelper.DeleteGroup(value);
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
[HttpPost] [HttpPost]
public IEnumerable<Group> Post(int id, [FromBody]JObject value) public IEnumerable<Group> Post(int id, [FromBody]JObject value)
{ {
var ret = new List<Group>(); var ret = new List<Group>();
dynamic json = value; dynamic json = value;
switch ((string)json.type) switch ((string)json.type)
{ {
case "user": case "user":
ret = GroupHelper.RetrieveGroupsByUserId(id).ToList(); ret = GroupHelper.RetrieveGroupsByUserId(id).ToList();
break; break;
case "role": case "role":
ret = GroupHelper.RetrieveGroupsByRoleId(id).ToList(); ret = GroupHelper.RetrieveGroupsByRoleId(id).ToList();
break; break;
default: default:
break; break;
} }
return ret; return ret;
} }
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
/// <param name="id"></param> /// <param name="id"></param>
/// <param name="value"></param> /// <param name="value"></param>
/// <returns></returns> /// <returns></returns>
[HttpPut] [HttpPut]
public bool Put(int id, [FromBody]JObject value) public bool Put(int id, [FromBody]JObject value)
{ {
var ret = false; var ret = false;
dynamic json = value; dynamic json = value;
string groupIds = json.groupIds; string groupIds = json.groupIds;
switch ((string)json.type) switch ((string)json.type)
{ {
case "user": case "user":
ret = GroupHelper.SaveGroupsByUserId(id, groupIds); ret = GroupHelper.SaveGroupsByUserId(id, groupIds);
break; break;
case "role": case "role":
ret = GroupHelper.SaveGroupsByRoleId(id, groupIds); ret = GroupHelper.SaveGroupsByRoleId(id, groupIds);
break; break;
default: default:
break; break;
} }
return ret; return ret;
} }
} }
} }

View File

@ -1,5 +1,8 @@
using Bootstrap.Admin.Models; using Bootstrap.Admin.Models;
using Bootstrap.DataAccess; using Bootstrap.DataAccess;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Web.Http; using System.Web.Http;
namespace Bootstrap.Admin.Controllers namespace Bootstrap.Admin.Controllers
@ -34,5 +37,36 @@ namespace Bootstrap.Admin.Controllers
{ {
return MenuHelper.DeleteMenu(value); return MenuHelper.DeleteMenu(value);
} }
[HttpPost]
public IEnumerable<Menu> Post(int id, [FromBody]JObject value)
{
var ret = new List<Menu>();
dynamic json = value;
switch ((string)json.type)
{
case "role":
ret = MenuHelper.RetrieveMenusByRoleId(id).ToList();
break;
default:
break;
}
return ret;
}
[HttpPut]
public bool Put(int id, [FromBody]JObject value)
{
var ret = false;
dynamic json = value;
string menuIds = json.menuIds.ToString();
switch ((string)json.type)
{
case "role":
ret = MenuHelper.SaveMenusByRoleId(id, menuIds);
break;
default:
break;
}
return ret;
}
} }
} }

View File

@ -32,7 +32,6 @@ namespace Bootstrap.Admin.Models
} }
var ret = new QueryData<Group>(); var ret = new QueryData<Group>();
ret.total = data.Count(); ret.total = data.Count();
// TODO: 通过option.Sort属性判断对那列进行排序现在统一对名称列排序
data = Order == "asc" ? data.OrderBy(t => t.GroupName) : data.OrderByDescending(t => t.GroupName); data = Order == "asc" ? data.OrderBy(t => t.GroupName) : data.OrderByDescending(t => t.GroupName);
ret.rows = data.Skip(Offset).Take(Limit); ret.rows = data.Skip(Offset).Take(Limit);
return ret; return ret;

View File

@ -32,7 +32,6 @@ namespace Bootstrap.Admin.Models
} }
var ret = new QueryData<Role>(); var ret = new QueryData<Role>();
ret.total = data.Count(); ret.total = data.Count();
// TODO: 通过option.Sort属性判断对那列进行排序现在统一对名称列排序
data = Order == "asc" ? data.OrderBy(t => t.RoleName) : data.OrderByDescending(t => t.RoleName); data = Order == "asc" ? data.OrderBy(t => t.RoleName) : data.OrderByDescending(t => t.RoleName);
ret.rows = data.Skip(Offset).Take(Limit); ret.rows = data.Skip(Offset).Take(Limit);
return ret; return ret;

View File

@ -32,8 +32,17 @@ namespace Bootstrap.Admin.Models
} }
var ret = new QueryData<User>(); var ret = new QueryData<User>();
ret.total = data.Count(); ret.total = data.Count();
// TODO: 通过option.Sort属性判断对那列进行排序现在统一对名称列排序 switch (Sort)
data = Order == "asc" ? data.OrderBy(t => t.UserName) : data.OrderByDescending(t => t.UserName); {
case "UserName":
data = Order == "asc" ? data.OrderBy(t => t.UserName) : data.OrderByDescending(t => t.UserName);
break;
case "RegisterTime":
data = Order == "asc" ? data.OrderBy(t => t.RegisterTime) : data.OrderByDescending(t => t.RegisterTime);
break;
default:
break;
}
ret.rows = data.Skip(Offset).Take(Limit); ret.rows = data.Skip(Offset).Take(Limit);
return ret; return ret;
} }

View File

@ -44,14 +44,45 @@
var groupIds = $('#dialogGroup :checked').map(function (index, element) { var groupIds = $('#dialogGroup :checked').map(function (index, element) {
return $(element).val(); return $(element).val();
}).toArray().join(','); }).toArray().join(',');
Group.saveGroupsByRoleId(roleId, groupIds, { modal: 'dialogGroup' }); Group.saveGroupsByRoleId(roleId, groupIds, { modal: 'dialogGroup' });
}
},
{
id: 'btn_assignMenu',
click: function (row) {
Menu.getMenusByRoleId(row.ID, function (data) {
$(".menu-content .modal-header .modal-title").text($.format('{0}-菜单授权窗口', row.RoleName));
$('.menu-content button:last').data('type', 'menu');
$('ol.dd-list').html(data);
$('#dialogMenu').modal('show');
$('.menu-content').show();
$('div.dd3-content :checkbox').show();
$('div.dd3-content :radio').hide();
})
}
},
{
id: 'btnSubmitMenu',
click: function (row) {
var roleId = row.ID;
var type = $('.menu-content button:last').data('type');
switch (type) {
case "menu":
var menuIds = $('.dd3-content :checkbox:checked').map(function (index, element) {
return $(element).val();
}).toArray().join(',');
break;
default:
break;
}
Menu.saveMenusByRoleId(roleId, menuIds, { modal: 'dialogMenu' });
} }
}] }]
} }
}); });
$('#nestable_menu').nestable();
$('table').smartTable({ $('table').smartTable({
url: '../api/Roles', //请求后台的URL* url: '../api/Roles', //请求后台的URL*
sortName: 'RoleName', sortName: 'RoleName',

View File

@ -3,8 +3,14 @@
ViewBag.Title = "角色管理"; ViewBag.Title = "角色管理";
Layout = "~/Views/Shared/_Default.cshtml"; Layout = "~/Views/Shared/_Default.cshtml";
} }
@section css {
<link href="~/Content/css/fa.css" rel="stylesheet" />
<link href="~/Content/css/jquery.nestable.css" rel="stylesheet" />
}
@section Javascript { @section Javascript {
<script src="~/Content/js/jquery.nestable.js"></script>
<script src="~/scripts/Roles.js"></script> <script src="~/scripts/Roles.js"></script>
} }
@section header { @section header {
@Html.Partial("Header", Model) @Html.Partial("Header", Model)
@ -34,6 +40,9 @@
<button id="btn_assignGroup" type="button" class="btn btn-info"> <button id="btn_assignGroup" type="button" class="btn btn-info">
<span class="fa fa-home" aria-hidden="true"></span>指派部门 <span class="fa fa-home" aria-hidden="true"></span>指派部门
</button> </button>
<button id="btn_assignMenu" type="button" class="btn btn-info">
<span class="fa fa-home" aria-hidden="true"></span>指派菜单
</button>
} }
@section modal { @section modal {
<div class="modal-header"> <div class="modal-header">
@ -57,4 +66,5 @@
@section customModal{ @section customModal{
@Html.Partial("UserConfig") @Html.Partial("UserConfig")
@Html.Partial("GroupConfig") @Html.Partial("GroupConfig")
@Html.Partial("NavigatorConfig", Model.Navigations)
} }

View File

@ -0,0 +1,7 @@
@model IEnumerable<Menu>
<div class="modal fade" id="dialogMenu" tabindex="-1" role="dialog" data-backdrop="static" aria-labelledby="myMenuModalLabel" aria-hidden="true">
<div class="modal-dialog">
@Html.Partial("MenuTree", Model)
</div>
</div>

View File

@ -25,6 +25,7 @@
<cacheManager> <cacheManager>
<add key="MenuHelper-RetrieveMenus" interval="600" desc="所有菜单数据缓存" /> <add key="MenuHelper-RetrieveMenus" interval="600" desc="所有菜单数据缓存" />
<add key="MenuHelper-RetrieveMenusByUserId" interval="600" desc="指定用户菜单数据缓存"/> <add key="MenuHelper-RetrieveMenusByUserId" interval="600" desc="指定用户菜单数据缓存"/>
<add key="MenuHelper-RetrieveMenusByRoleId" interval="600" desc="角色菜单信息缓存" />
<add key="UserHelper-RetrieveUsers" interval="600" desc="所有用户数据缓存"/> <add key="UserHelper-RetrieveUsers" interval="600" desc="所有用户数据缓存"/>
<add key="UserHelper-RetrieveUsersByName" interval="600" desc="指定用户名的用户数据缓存"/> <add key="UserHelper-RetrieveUsersByName" interval="600" desc="指定用户名的用户数据缓存"/>
<add key="UserHelper-RetrieveUsersByRoleId" interval="600" desc="指定角色的用户数据缓存"/> <add key="UserHelper-RetrieveUsersByRoleId" interval="600" desc="指定角色的用户数据缓存"/>

View File

@ -7,6 +7,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Data; using System.Data;
using System.Data.Common; using System.Data.Common;
using System.Data.SqlClient;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
@ -16,6 +17,7 @@ namespace Bootstrap.DataAccess
{ {
internal const string RetrieveMenusDataKey = "MenuHelper-RetrieveMenus"; internal const string RetrieveMenusDataKey = "MenuHelper-RetrieveMenus";
internal const string RetrieveMenusByUserIDDataKey = "MenuHelper-RetrieveMenusByUserId"; internal const string RetrieveMenusByUserIDDataKey = "MenuHelper-RetrieveMenusByUserId";
internal const string RetrieveMenusByRoleIDDataKey = "MenuHelper-RetrieveMenusByRoleId";
/// <summary> /// <summary>
/// 查询所有菜单信息 /// 查询所有菜单信息
/// </summary> /// </summary>
@ -184,5 +186,88 @@ namespace Bootstrap.DataAccess
} }
return ret; return ret;
} }
/// <summary>
/// 查询某个角色所配置的菜单
/// </summary>
/// <param name="roleId"></param>
/// <returns></returns>
public static IEnumerable<Menu> RetrieveMenusByRoleId(int roleId)
{
string key = string.Format("{0}-{1}", RetrieveMenusByRoleIDDataKey, roleId);
return CacheManager.GetOrAdd(key, CacheSection.RetrieveIntervalByKey(RetrieveMenusByRoleIDDataKey), k =>
{
List<Menu> Menus = new List<Menu>();
string sql = "select n.ID,n.ParentId, n.Name,n.[Order],n.Icon,n.Url,n.Category, case nr.NavigationID when n.ID then 'active' else '' end [status] from Navigations n left join NavigationRole nr on n.ID = nr.NavigationID and RoleID = @RoleID";
DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, sql);
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@RoleID", roleId, ParameterDirection.Input));
try
{
using (DbDataReader reader = DBAccessManager.SqlDBAccess.ExecuteReader(cmd))
{
while (reader.Read())
{
Menus.Add(new Menu()
{
ID = (int)reader[0],
ParentId = (int)reader[1],
Name = (string)reader[2],
Order = (int)reader[3],
Icon = LgbConvert.ReadValue(reader[4], string.Empty),
Url = LgbConvert.ReadValue(reader[5], string.Empty),
Category = (string)reader[6],
Active = (string)reader[7] == "" ? "" : "checked"
});
}
}
}
catch (Exception ex) { ExceptionManager.Publish(ex); }
return Menus;
}, CacheSection.RetrieveDescByKey(RetrieveMenusByRoleIDDataKey));
}
/// <summary>
/// 通过角色ID保存当前授权菜单
/// </summary>
/// <param name="id"></param>
/// <param name="menuIds"></param>
/// <returns></returns>
public static bool SaveMenusByRoleId(int id, string menuIds)
{
bool ret = false;
DataTable dt = new DataTable();
dt.Columns.Add("RoleID", typeof(int));
dt.Columns.Add("NavigationID", typeof(int));
if (!string.IsNullOrEmpty(menuIds)) menuIds.Split(',').ToList().ForEach(menuId => dt.Rows.Add(id, Convert.ToInt32(menuId)));
using (TransactionPackage transaction = DBAccessManager.SqlDBAccess.BeginTransaction())
{
try
{
//删除菜单角色表该角色所有的菜单
string sql = "delete from NavigationRole where RoleID=@RoleID";
using (DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, sql))
{
cmd.Parameters.Add(DBAccessManager.SqlDBAccess.CreateParameter("@RoleID", id, ParameterDirection.Input));
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd, transaction);
//批插入菜单角色表
using (SqlBulkCopy bulk = new SqlBulkCopy((SqlConnection)transaction.Transaction.Connection, SqlBulkCopyOptions.Default, (SqlTransaction)transaction.Transaction))
{
bulk.DestinationTableName = "NavigationRole";
bulk.ColumnMappings.Add("RoleID", "RoleID");
bulk.ColumnMappings.Add("NavigationID", "NavigationID");
bulk.WriteToServer(dt);
transaction.CommitTransaction();
}
}
CacheCleanUtility.ClearCache(menuIds: menuIds, roleIds: id.ToString());
ret = true;
}
catch (Exception ex)
{
ExceptionManager.Publish(ex);
transaction.RollbackTransaction();
}
}
return ret;
}
} }
} }

View File

@ -37,6 +37,11 @@ namespace Bootstrap.DataAccess.Tests
{ {
Assert.IsTrue(MenuHelper.RetrieveMenusByUserId(1).Count() > 1, "根据用户ID查询菜单的MenuHelper.RetrieveMenusByUserId方法调用失败"); Assert.IsTrue(MenuHelper.RetrieveMenusByUserId(1).Count() > 1, "根据用户ID查询菜单的MenuHelper.RetrieveMenusByUserId方法调用失败");
} }
[TestMethod]
public void RetrieveMenuByRoleIDTest()
{
Assert.IsTrue(MenuHelper.RetrieveMenusByRoleId(1).Count() >= 0, "根据角色ID查询菜单的MenuHelper.RetrieveMenusByRoleId方法调用失败");
}
[TestMethod] [TestMethod]
public void SaveMenuTest() public void SaveMenuTest()
@ -85,5 +90,28 @@ namespace Bootstrap.DataAccess.Tests
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd); DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
} }
} }
[TestMethod]
public void SaveMenusByRoleIdTest()
{
var menu = MenuHelper.RetrieveMenus().FirstOrDefault(m => m.Name == Menu.Name);
if (menu == null) MenuHelper.SaveMenu(Menu);
menu = MenuHelper.RetrieveMenus().FirstOrDefault(m => m.Name == Menu.Name);
var role = RoleHelper.RetrieveRoles().FirstOrDefault(r => r.RoleName == Role.RoleName);
if (role == null) RoleHelper.SaveRole(Role);
role = RoleHelper.RetrieveRoles().FirstOrDefault(r => r.RoleName == Role.RoleName);
Assert.IsTrue(MenuHelper.SaveMenusByRoleId(role.ID, menu.ID.ToString()), "存储角色菜单信息失败");
int x = MenuHelper.RetrieveMenusByRoleId(role.ID).Count();
Assert.IsTrue(x >= 1, string.Format("获取角色ID={0}的菜单信息失败", role.ID));
//删除数据
string sql = "Delete from Navigations where Name = '__测试菜单__';";
sql += "Delete from Roles where RoleName='_测试角色_';";
sql += string.Format("Delete from NavigationRole where RoleID={0};", role.ID);
using (DbCommand cmd = DBAccessManager.SqlDBAccess.CreateCommand(CommandType.Text, sql))
{
DBAccessManager.SqlDBAccess.ExecuteNonQuery(cmd);
}
}
} }
} }