class=
" modal-body " >
class=
" form-group row required " >
class=" col-md-3 col-form-label " for =" tenancy-name " >@L(" MenuName " )
class=" col-md-9 " >
"tenancy-name " type=" text " class =" form-control " name=" MenuName " value=" @Model.MenuName " required maxlength=" 64 " minlength=" 2 " >
class=
" form-group row required " >
class=" col-md-3 col-form-label " for =" name " >@L(" LName " )
class=" col-md-9 " >
"name " type=" text " class =" form-control " name=" LName " value=" @Model.LName " required maxlength=" 128 " >
class=
" form-group row required " >
class=" col-md-3 col-form-label " for =" name " >@L(" Url " )
class=" col-md-9 " >
"name " type=" text " class =" form-control " name=" Url " value=" @Model.Url " required maxlength=" 128 " >
<div>class=<span>"</span><span>form-group row required</span><span>"</span>>
<label>class=<span>"</span><span>col-md-3 col-form-label</span><span>"</span> <span>for</span>=<span>"</span><span>name</span><span>"</span>>@L(<span>"</span><span>PageName</span><span>"</span>)</label>
<div>class=<span>"</span><span>col-md-9</span><span>"</span>>
<input>"<span>name</span><span>"</span> type=<span>"</span><span>text</span><span>"</span> <span>class</span>=<span>"</span><span>form-control</span><span>"</span> name=<span>"</span><span>PageName</span><span>"</span> value=<span>"</span><span>@Model.PageName</span><span>"</span> required maxlength=<span>"</span><span>128</span><span>"</span>>
</div>
</div>
<div>class=<span>"</span><span>form-group row required</span><span>"</span>>
<label>class=<span>"</span><span>col-md-3 col-form-label</span><span>"</span> <span>for</span>=<span>"</span><span>name</span><span>"</span>>@L(<span>"</span><span>ParentId</span><span>"</span>)</label>
<div>class=<span>"</span><span>col-md-9</span><span>"</span>>
<input>"<span>name</span><span>"</span> type=<span>"</span><span>text</span><span>"</span> <span>class</span>=<span>"</span><span>form-control</span><span>"</span> name=<span>"</span><span>ParentId</span><span>"</span> value=<span>"</span><span>@Model.ParentId</span><span>"</span> required maxlength=<span>"</span><span>128</span><span>"</span>>
</div>
</div>
<div>class=<span>"</span><span>form-group row required</span><span>"</span>>
<label>class=<span>"</span><span>col-md-3 col-form-label</span><span>"</span> <span>for</span>=<span>"</span><span>name</span><span>"</span>>@L(<span>"</span><span>Orders</span><span>"</span>)</label>
<div>class=<span>"</span><span>col-md-9</span><span>"</span>>
<input>"<span>name</span><span>"</span> type=<span>"</span><span>text</span><span>"</span> <span>class</span>=<span>"</span><span>form-control</span><span>"</span> name=<span>"</span><span>Orders</span><span>"</span> value=<span>"</span><span>@Model.Orders</span><span>"</span> required maxlength=<span>"</span><span>128</span><span>"</span>>
</div>
</div>
<div>class=<span>"</span><span>form-group row</span><span>"</span>>
<label>class=<span>"</span><span>col-md-3 col-form-label</span><span>"</span> <span>for</span>=<span>"</span><span>isactive</span><span>"</span>>@L(<span>"</span><span>IsActive</span><span>"</span>)</label>
<div>class=<span>"</span><span>col-md-9</span><span>"</span>>
<input>"<span>isactive</span><span>"</span> type=<span>"</span><span>checkbox</span><span>"</span> name=<span>"</span><span>IsActive</span><span>"</span> value=<span>"</span><span>true</span><span>"</span> @(Model.IsActive ? <span>"</span><span>checked</span><span>"</span> : <span>""</span>) />
</div>
</div>
</div><span>
@await Html.PartialAsync(</span><span>"</span><span>~/Views/Shared/Modals/_ModalFooterWithSaveAndCancel.cshtml</span><span>"</span><span>)
View Code
修改Index.AdvancedSearch.cshtml
@using AbpLearn.Web.Views.Shared.Components.TenantChange
@using Abp.Application.Services.Dto
@model ChangeModalViewModel
class="abp-advanced-search">
"MenusSearchForm" class="form-horizontal">
"hidden" name="TenantId" value="@Model.TenantId" />
class="form-horizontal">
class="form-group">
@Html.DropDownList(
"ChangeTenancyNames",
Model.TeneacyItems.Select(i => i.ToSelectListItem()),
new { @class = "form-control edited", id = "ChangeTenancyName" })
因为在abp里面加载当前列表调用的是abp.services.app.menus.getAll方法,我们还需要对MenusAppService中的GetAllAsync做一下修改
[Serializable]
public class MenusPagedResultRequestDto: PagedResultRequestDto, IPagedAndSortedResultRequest
{
public virtual int? TenantId { get; set; }
public virtual string Sorting { get; set; }
public virtual bool ShowAll { get; set; }
}
#region 查询全部菜单
///
/// 查询全部菜单
///
///
///
public override async Task> GetAllAsync(MenusPagedResultRequestDto input)
{
IQueryable query;
query = CreateFilteredQuery(input).Where(o => o.TenantId == (input.TenantId == 0 ? null : input.TenantId));
var totalCount = await AsyncQueryableExecuter.CountAsync(query);
query = ApplySorting(query, input);
if (!input.ShowAll) query = ApplyPaging(query, input);
var entities = await AsyncQueryableExecuter.ToListAsync(query);
return new PagedResultDto(
totalCount,
entities.Select(MapToEntityDto).ToList()
);
}
#endregion
这样,我们在选中下面中的任意一个Tenant时,将会跳到对应的菜单里面了
我们先把Host管理员菜单和默认菜单配置一下
二、实现添加租户时,初始化标准菜单和权限
首先我们找到添加租户的地方,去TenantAppService里面去找,可以看到有CreateAsync的重写
public override async Task CreateAsync(CreateTenantDto input)
{
CheckCreatePermission();
// Create tenant
var tenant = ObjectMapper.Map(input);
tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty()
? null
: SimpleStringCipher.Instance.Encrypt(input.ConnectionString);
var defaultEdition = await _editionManager.FindByNameAsync(EditionManager.DefaultEditionName);
if (defaultEdition != null)
{
tenant.EditionId = defaultEdition.Id;
}
await _tenantManager.CreateAsync(tenant);
await CurrentUnitOfWork.SaveChangesAsync(); // To get new tenant's id.
// Create tenant database
_abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);
// We are working entities of new tenant, so changing tenant filter
using (CurrentUnitOfWork.SetTenantId(tenant.Id))
{
// Create static roles for new tenant
CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
await CurrentUnitOfWork.SaveChangesAsync(); // To get static role ids
// Grant all permissions to admin role
var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
await _roleManager.GrantAllPermissionsAsync(adminRole);
// Create admin user for the tenant
var adminUser = User.CreateTenantAdminUser(tenant.Id, input.AdminEmailAddress);
await _userManager.InitializeOptionsAsync(tenant.Id);
CheckErrors(await _userManager.CreateAsync(adminUser, User.DefaultPassword));
await CurrentUnitOfWork.SaveChangesAsync(); // To get admin user's id
// Assign admin user to role!
CheckErrors(await _userManager.AddToRoleAsync(adminUser, adminRole.Name));
await CurrentUnitOfWork.SaveChangesAsync();
}
return MapToEntityDto(tenant);
}
我们需要做的是,在 using (CurrentUnitOfWork.SetTenantId(tenant.Id)) 的内部尾部添加赋予菜单和权限的方法即可
赋予菜单和权限的方法我们分开写,都放在MenusAppService中,
public interface IMenusAppService : IAsyncCrudAppServiceint, MenusPagedResultRequestDto, CreateMenuDto, MenuDto>
{
///
/// 赋予默认菜单
///
///
///
Task GiveMenusAsync(EntityDto<int > input);
///
/// 赋予当前租户Admin角色菜单权限
///
///
///
Task GivePermissionsAsync(EntityDto<int > input);
} ,>
#region 赋予默认菜单
public async Task GiveMenusAsync(EntityDto input)
{
if (input.Id > 0)
{
var tenant = await _tenantManager.GetByIdAsync(input.Id);
using (_unitOfWorkManager.Current.SetTenantId(tenant.Id))
{
var query = CreateFilteredQuery(new MenusPagedResultRequestDto()).Where(o => o.TenantId == tenant.Id);
var systemMenus = await AsyncQueryableExecuter.ToListAsync(query);
if (!systemMenus.Any())
{
query = CreateFilteredQuery(new MenusPagedResultRequestDto()).Where(o => o.TenantId == -1);
var defaultMenus = await AsyncQueryableExecuter.ToListAsync(query);
if (defaultMenus.Any())
{
List GetMenusInserts(List abpMenus,int parentId = 0)
{
List menusInserts = new List();
foreach (var entity in abpMenus.Where(o => o.ParentId == parentId))
{
var insert = new MenusInsert()
{
LName = entity.LName,
MenuName = entity.MenuName,
PageName = entity.PageName,
Icon = entity.Icon,
Url = entity.Url,
IsActive = entity.IsActive,
Orders = entity.Orders,
ParentId = entity.ParentId,
TenantId = tenant.Id
};
insert.menusInserts = GetMenusInserts(abpMenus, entity.Id);
menusInserts.Add(insert);
}
return menusInserts;
}
async Task InsertMenusAsync(List inserts,int parentId = 0)
{
foreach (var insert in inserts)
{
var entity = await CreateAsync(new AbpMenus()
{
LName = insert.LName,
MenuName = insert.MenuName,
PageName = insert.PageName,
Icon = insert.Icon,
Url = insert.Url,
IsActive = insert.IsActive,
Orders = insert.Orders,
ParentId = parentId,
TenantId = tenant.Id
});
if (insert.menusInserts.Any())
{
await InsertMenusAsync(insert.menusInserts, entity.Id);
}
}
}
await InsertMenusAsync(GetMenusInserts(defaultMenus));
}
}
}
}
}
#endregion
#region 赋予当前租户Admin角色菜单权限
///
/// 赋予当前租户Admin角色菜单权限
///
///
///
public async Task GivePermissionsAsync(EntityDto<int > input)
{
if (input.Id > 0 )
{
var tenant = await _tenantManager.GetByIdAsync(input.Id);
using (_unitOfWorkManager.Current.SetTenantId(tenant.Id))
{
var adminRoles = await _roleRepository.GetAllListAsync(o => o.Name == StaticRoleNames.Tenants.Admin && o.TenantId == tenant.Id);
if (adminRoles.FirstOrDefault() != null )
{
var adminRole = adminRoles.FirstOrDefault();
var query = CreateFilteredQuery(new MenusPagedResultRequestDto()).Where(o => o.TenantId == tenant.Id);
var systemMenus = await AsyncQueryableExecuter.ToListAsync(query);
var permissions = ConvertTenantPermissions(systemMenus);
// await _roleManager.ResetAllPermissionsAsync(adminRole.FirstOrDefault()); // 重置授权
var active_BatchCount = 10 ;
var active_permissions = ConvertTenantPermissions(systemMenus.Where(o => o.IsActive).ToList());
for (int i = 0 ; i < active_permissions.Count(); i += 10 )// 每次后移5位
{
// await _roleManager.SetGrantedPermissionsAsync(adminRole.FirstOrDefault().Id, active_permissions.Take(active_BatchCount).Skip(i));
foreach (var notActive_permission in active_permissions.Take(active_BatchCount).Skip(i))
{
await _roleManager.GrantPermissionAsync(adminRole, notActive_permission);
}
active_BatchCount += 10 ;// 每次从数组中选出N+10位,skip前N位
}
var notActive_BatchCount = 10 ;
var notActive_permissions = ConvertTenantPermissions(systemMenus.Where(o => !o.IsActive).ToList());
for (int i = 0 ; i < notActive_permissions.Count(); i += 10 )// 每次后移5位
{
foreach (var notActive_permission in notActive_permissions.Take(notActive_BatchCount).Skip(i))
{
await _roleManager.ProhibitPermissionAsync(adminRole, notActive_permission);
}
notActive_BatchCount += 10 ;// 每次从数组中选出N+10位,skip前N位
}
}
else
{
throw new AbpDbConcurrencyException(" 未获取到当前租户的Admin角色! " );
}
}
}
else
{
var adminRoles = await _roleRepository.GetAllListAsync(o => o.Name == StaticRoleNames.Tenants.Admin && o.TenantId == null );
if (adminRoles.FirstOrDefault() != null )
{
var adminRole = adminRoles.FirstOrDefault();
var query = CreateFilteredQuery(new MenusPagedResultRequestDto()).Where(o => o.TenantId == null || o.TenantId == 0 );
var systemMenus = await AsyncQueryableExecuter.ToListAsync(query);
// await _roleManager.ResetAllPermissionsAsync(adminRole.FirstOrDefault()); // 重置授权
var active_BatchCount = 10 ;
var active_permissions = ConvertHostPermissions(systemMenus.Where(o => o.IsActive).ToList());
for (int i = 0 ; i < active_permissions.Count(); i += 10 )// 每次后移5位
{
// await _roleManager.SetGrantedPermissionsAsync(adminRole.FirstOrDefault().Id, active_permissions.Take(active_BatchCount).Skip(i));
foreach (var notActive_permission in active_permissions.Take(active_BatchCount).Skip(i))
{
await _roleManager.GrantPermissionAsync(adminRole, notActive_permission);
}
active_BatchCount += 10 ;// 每次从数组中选出N+10位,skip前N位
}
var notActive_BatchCount = 10 ;
var notActive_permissions = ConvertHostPermissions(systemMenus.Where(o => !o.IsActive).ToList());
for (int i = 0 ; i < notActive_permissions.Count(); i += 10 )// 每次后移5位
{
foreach (var notActive_permission in notActive_permissions.Take(notActive_BatchCount).Skip(i))
{
await _roleManager.ProhibitPermissionAsync(adminRole, notActive_permission);
}
notActive_BatchCount += 10 ;// 每次从数组中选出N+10位,skip前N位
}
}
}
}
public IEnumerable ConvertTenantPermissions(IReadOnlyList systemMenus)
{
return systemMenus.Select(o => new Permission(o.PageName, L(o.MenuName), L(o.LName), MultiTenancySides.Tenant));
}
public IEnumerable ConvertHostPermissions(IReadOnlyList systemMenus)
{
return systemMenus.Select(o => new Permission(o.PageName, L(o.MenuName), L(o.LName), MultiTenancySides.Host));
}
#endregion
TenantAppService.cs中做一下修改
public override async Task CreateAsync(CreateTenantDto input)
{
CheckCreatePermission();
// Create tenant
var tenant = ObjectMapper.Map(input);
tenant.ConnectionString = input.ConnectionString.IsNullOrEmpty()
? null
: SimpleStringCipher.Instance.Encrypt(input.ConnectionString);
var defaultEdition = await _editionManager.FindByNameAsync(EditionManager.DefaultEditionName);
if (defaultEdition != null)
{
tenant.EditionId = defaultEdition.Id;
}
await _tenantManager.CreateAsync(tenant);
await CurrentUnitOfWork.SaveChangesAsync(); // To get new tenant's id.
// Create tenant database
_abpZeroDbMigrator.CreateOrMigrateForTenant(tenant);
// We are working entities of new tenant, so changing tenant filter
using (CurrentUnitOfWork.SetTenantId(tenant.Id))
{
// Create static roles for new tenant
CheckErrors(await _roleManager.CreateStaticRoles(tenant.Id));
await CurrentUnitOfWork.SaveChangesAsync(); // To get static role ids
// Grant all permissions to admin role
var adminRole = _roleManager.Roles.Single(r => r.Name == StaticRoleNames.Tenants.Admin);
await _roleManager.GrantAllPermissionsAsync(adminRole);
// Create admin user for the tenant
var adminUser = User.CreateTenantAdminUser(tenant.Id, input.AdminEmailAddress);
await _userManager.InitializeOptionsAsync(tenant.Id);
CheckErrors(await _userManager.CreateAsync(adminUser, User.DefaultPassword));
await CurrentUnitOfWork.SaveChangesAsync(); // To get admin user's id
// Assign admin user to role!
CheckErrors(await _userManager.AddToRoleAsync(adminUser, adminRole.Name));
await CurrentUnitOfWork.SaveChangesAsync();
await _menusAppService.GiveMenusAsync(new EntityDto() { Id = tenant.Id });
await CurrentUnitOfWork.SaveChangesAsync();
await _menusAppService.GivePermissionsAsync(new EntityDto() { Id = tenant.Id });
await CurrentUnitOfWork.SaveChangesAsync();
}
return MapToEntityDto(tenant);
}
现在我们添加租户企业1、企业2
现在菜单已经同步好了,我们去数据库看下权限的同步
TenantId:
null是Host
1是abp页面第一次加载时初始化的Default租户
2是我之前添加的旧的企业1,那个时候方法没写好,就把2的删掉了
3是企业2
4是企业1
由此可以看出,我们添加的菜单对应的PageName已经作为权限添加到权限表了
三、实现菜单修改后,权限赋予对应租户
这一个其实在二里面已经写好了,前台做一个按钮,赋予权限,调用一下就好了
例如:
Index.cshtml //为什么要加getCurrentLoginInformationsOutput.Tenant == null的判断?是因为租户在进入菜单管理的地方,我们不给他们添加、赋予权限的权限
在/wwwroot/view-resources/Views/Menus/Index.js中添加
$(document).on('click', '#GivePermissions', function (e) {
var tenantId = $(this).attr('data-tenant-id');
abp.message.confirm(
abp.utils.formatString(
"是否赋予当前租户管理员账号所有权限?",
"系统"
),
null,
(isConfirmed) => {
if (isConfirmed) {
_menuService
.givePermissions({
id: tenantId
})
.done(() => {
abp.notify.info("操作成功!");
_$menusTable.ajax.reload();
});
}
}
);
});
四、实现菜单的动态加载
在https://www.cnblogs.com/wangpengzong/p/13089690.html 中我们找到了菜单生成的地方,在最底部,通过NavigationManager来获取到Menus,这里其实有一个初始化方法(Initialize ),调用的是AbpLearnNavigationProvider的SetNavigation方法来进行本地化,然后在
NavigationManager的非静态构造函数中去获取已经本地化的Menus,但是本地化Menus因为是在初始化时,程序的初始化我们无法获取到当前的Tenant信息,所以只能将获取Menus的地方推迟,放在倒数第二个类UserNavigationManager里面的GetMenuAsync方法中,我们来看下GetMenuAsync
public async Task GetMenuAsync(string menuName, UserIdentifier user)
{
var menuDefinition = _navigationManager.Menus.GetOrDefault(menuName);
if (menuDefinition == null)
{
throw new AbpException("There is no menu with given name: " + menuName);
}
var userMenu = new UserMenu(menuDefinition, _localizationContext);
await FillUserMenuItems(user, menuDefinition.Items, userMenu.Items);
return userMenu;
}
第一句话获取menuDefinition是关键点,我们将menuDefinition修改为从数据库中获取,在AbpLearn.Application/Authorization/Menus下添加UserNavigationManager.cs
using Abp;
using Abp.Application.Features;
using Abp.Application.Navigation;
using Abp.Authorization;
using Abp.Dependency;
using Abp.Localization;
using Abp.MultiTenancy;
using Abp.Runtime.Session;
using AbpLearn.Authorization.Menus.Dto;
using AbpLearn.Sessions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AbpLearn.Authorization.Menus
{
public class UserNavigationManager : IUserNavigationManager, ITransientDependency
{
public IAbpSession AbpSession { get; set; }
private readonly INavigationManager _navigationManager;
private readonly ILocalizationContext _localizationContext;
private readonly IIocResolver _iocResolver;
private readonly IMenusAppService _menuAppService;
private readonly ISessionAppService _sessionAppService;
public IDictionary Menus { get; private set; }
public MenuDefinition MainMenu
{
get { return Menus["MainMenu"]; }
}
public UserNavigationManager(
INavigationManager navigationManager,
ILocalizationContext localizationContext,
IMenusAppService menuAppService,
ISessionAppService sessionAppService,
IIocResolver iocResolver)
{
_navigationManager = navigationManager;
_localizationContext = localizationContext;
_iocResolver = iocResolver;
AbpSession = NullAbpSession.Instance;
_menuAppService = menuAppService;
_sessionAppService = sessionAppService;
}
public async Task GetMenuAsync(string menuName, UserIdentifier user)
{
var loginInfo = await _sessionAppService.GetCurrentLoginInformations();
Menus = new Dictionary
{
{"MainMenu", new MenuDefinition("MainMenu", new LocalizableString("MainMenu", AbpConsts.LocalizationSourceName))}
};
var lists = await _menuAppService.GetAllAsync(new MenusPagedResultRequestDto() { ShowAll = true, TenantId = (loginInfo.Tenant == null ? 0 : loginInfo.Tenant.Id) });
var ParentMenu = lists.Items.Where(k => k.IsActive).ToList().Where(x => x.ParentId == 0).ToList();
if (ParentMenu.Any())
{
ParentMenu.ForEach(g =>
{
var menu = new MenuItemDefinition(
g.LName,
MenuL(g.MenuName),
g.Icon,
g.Url,
false,
g.Orders
);
BuildSubMenu(menu, g.Id, lists.Items.Where(k => k.IsActive).ToList());
MainMenu.AddItem(menu);
});
}
var menuDefinition = MainMenu;
if (menuDefinition == null)
{
throw new AbpException("There is no menu with given name: " + menuName);
}
var userMenu = new UserMenu();
userMenu.Name = menuDefinition.Name;
userMenu.DisplayName = menuDefinition.DisplayName.Localize(_localizationContext);
userMenu.CustomData = menuDefinition.CustomData;
userMenu.Items = new List();
await FillUserMenuItems(user, menuDefinition.Items, userMenu.Items);
return userMenu;
}
public async Task> GetMenusAsync(UserIdentifier user)
{
var userMenus = new List();
foreach (var menu in _navigationManager.Menus.Values)
{
userMenus.Add(await GetMenuAsync(menu.Name, user));
}
return userMenus;
}
public void BuildSubMenu(MenuItemDefinition menu, int parentId, List list)
{
var nList = list.Where(x => x.ParentId == parentId).ToList();
if (nList != null && nList.Count > 0)
{
nList.ForEach(g =>
{
var subMenu = new MenuItemDefinition(
g.PageName,
MenuL(g.MenuName),
g.Icon,
g.Url,
false,
g.Orders
);
menu.AddItem(subMenu);
BuildSubMenu(subMenu, g.Id, list);
});
}
}
private static ILocalizableString MenuL(string name)
{
return new LocalizableString(name, AbpLearnConsts.LocalizationSourceName);
}
private async Task FillUserMenuItems(UserIdentifier user, IList menuItemDefinitions, IList userMenuItems)
{
//TODO: Can be optimized by re-using FeatureDependencyContext.
var addedMenuItemCount = 0;
using (var scope = _iocResolver.CreateScope())
{
var permissionDependencyContext = scope.Resolve();
permissionDependencyContext.User = user;
var featureDependencyContext = scope.Resolve();
featureDependencyContext.TenantId = user == null ? null : user.TenantId;
foreach (var menuItemDefinition in menuItemDefinitions)
{
if (menuItemDefinition.RequiresAuthentication && user == null)
{
continue;
}
if (menuItemDefinition.PermissionDependency != null &&
(user == null || !(await menuItemDefinition.PermissionDependency.IsSatisfiedAsync(permissionDependencyContext))))
{
continue;
}
if (menuItemDefinition.FeatureDependency != null &&
(AbpSession.MultiTenancySide == MultiTenancySides.Tenant || (user != null && user.TenantId != null)) &&
!(await menuItemDefinition.FeatureDependency.IsSatisfiedAsync(featureDependencyContext)))
{
continue;
}
var userMenuItem = new UserMenuItem(menuItemDefinition, _localizationContext);
if (menuItemDefinition.IsLeaf || (await FillUserMenuItems(user, menuItemDefinition.Items, userMenuItem.Items)) > 0)
{
userMenuItems.Add(userMenuItem);
++addedMenuItemCount;
}
}
}
return addedMenuItemCount;
}
}
}
然后在Mvc项目的Startup.cs/ConfigureServices下增加
services.AddScoped();
因为在abp中菜单被做做成了模块,在程序初始化时模块添加进去,但是我们将菜单修改成了每次读取数据库加载,那么我们就不需要加载这个模块了
在mvc项目的AbpLearnWebMvcModule.cs注释下面这句话
//Configuration.Navigation.Providers.Add();
将AbpLearnNavigationProvider.cs/SetNavigation方法的内容全部注释掉
预览一下mvc,用Host登录一下
用企业1登陆下,登录切换Host和Tenant,是在登录界面 Current tenant:未选() 点击Change,在弹框中输入 E1(因为上面设置的企业1标识是E1),点击save,页面刷新后就变为了Current tenant:E1 () ,输入账号密码登录
OK,我们的动态菜单已经完成了
添加jstree
当然,我的菜单使用的是table来显示,你也可以使用tree来,我找到了一个jstree,下面修改一下
MenusAppService.cs
#region 获取当前账户的菜单树
///
/// 获取当前账户的菜单树
///
///
///
public async Task<string > GetTreeAsync(MenusPagedResultRequestDto input)
{
var query = CreateFilteredQuery(new MenusPagedResultRequestDto()).Where(o => o.TenantId == input.TenantId);
var systemMenus = await AsyncQueryableExecuter.ToListAsync(query);
var childJObject = new JObject();
var openJObject = new JObject();
openJObject.Add( " opened " , true );
childJObject.Add( " id " , 0 );
childJObject.Add( " text " , " 根目录 " );
childJObject.Add( " icon " , "" );
childJObject.Add( " state " , openJObject);
childJObject.Add( " children " , GetJArray(systemMenus, 0 ));
return childJObject.ToString();
}
#region 获取目录Array
///
/// 获取目录Array
///
///
///
///
private JArray GetJArray(List systemMenus, int parentdId)
{
JArray jArray = new JArray();
foreach (var menu in systemMenus.Where(o => o.ParentId == parentdId))
{
var jObject = new JObject();
jObject.Add( " id " , menu.Id);
jObject.Add( " text " , menu.MenuName);
jObject.Add( " icon " , menu.Icon);
// jObject.Add("state", menu.Icon);
if (systemMenus.Any(o => o.ParentId == menu.Id))
{
jObject.Add( " children " , GetJArray(systemMenus, menu.Id));
}
jArray.Add(jObject);
}
return jArray;
}
#endregion
#endregion
前端Index.cshtml jstree去https://github.com/vakata/jstree/zipball/3.3.8下载,下载后在mvc项目的wwwroot文件夹下添加jstree文件夹,下载文件的src里面内容全部赋值到jstree文件夹
注释掉table标签
添加jstree1
例如:
@section styles
{
} "jstree1" style="width:100%;">
@section scripts
{
$(function () {
var _menuService = abp.services.app.menus;
l = abp.localization.getSource('A_b_p');
$('#jstree1').jstree({
"core": {
"data": function (node, callback) {
var filter = $('#MenusSearchForm').serializeFormToObject(true);
this, _menuService.getTree(filter).done(function (result) {
callback.call(this, JSON.parse(result));
});
},
"themes": {
"variant": "large",//加大
"ellipsis": true //文字多时省略
},
"check_callback": true,
},
"plugins": ["contextmenu", "wholerow", "themes"],//"checkbox"
"contextmenu": {
select_node: false,
show_at_node: true,
"items": {
"create": {
"label": "新增子菜单",
"action": function (obj) {
var inst = jQuery.jstree.reference(obj.reference);
var clickedNode = inst.get_node(obj.reference);
if (parseInt(clickedNode.original.id) >= 0) {
$("#ParentId").val(clickedNode.original.id);
$("#MenuCreateModal").modal();
} else {
abp.notify.info("父节点获取出错");
}
},
},
"rename": {
"label": "修改",
"action": function (obj) {
var inst = jQuery.jstree.reference(obj.reference);
var clickedNode = inst.get_node(obj.reference);
if (parseInt(clickedNode.original.id) >= 0) {
abp.ajax({
url: abp.appPath + 'Menus/EditModal?menuId=' + clickedNode.original.id,
type: 'POST',
dataType: 'html',
success: function (content) {
$("#MenuEditModal").modal();
$('#MenuEditModal div.modal-content').html(content);
},
error: function (e) { }
});
} else {
abp.notify.info("菜单获取出错");
}
}
},
"delete": {
"label": "更改菜单状态",
"action": function (obj) {
var inst = jQuery.jstree.reference(obj.reference);
var clickedNode = inst.get_node(obj.reference);
abp.message.confirm(
abp.utils.formatString("是否" + (clickedNode.original.state.disabled?"启用":"禁用") + "当前菜单:" + clickedNode.original.text + "?"),
null,
(isConfirmed) => {
if (isConfirmed) {
_menuService
.delete({
id: clickedNode.original.id
})
.done(() => {
abp.notify.info(l('SuccessfullyDeleted'));
location.reload();
});
}
}
);
},
}
}
}
}).on('select_node.jstree', function (event, data) {
console.log(data.node);
}).on('changed.jstree', function (event, data) {
console.log("-----------changed.jstree");
console.log("action:" + data.action);
console.log(data.node);
});
});
}
预览一下吧
github地址
本文github:https://github.com/wangpengzong/AbpLearn
下一篇开始动态权限
吐槽区域(写的不好、不对,欢迎吐槽)
Original: https://www.cnblogs.com/spatxos/p/13096427.html Author: spatxos Title: .net core3.1 abp动态菜单和动态权限(动态菜单实现和动态权限添加) (三)