31 changed files with 1385 additions and 2051 deletions
@ -0,0 +1,13 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.MultiTenancy" Version="4.4.0" /> |
||||
|
<PackageReference Include="Volo.Abp.ObjectExtending" Version="4.4.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,14 @@ |
|||||
|
using Volo.Abp.Collections; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class AbpNavigationOptions |
||||
|
{ |
||||
|
public ITypeList<INavigationDefinitionProvider> DefinitionProviders { get; } |
||||
|
|
||||
|
public AbpNavigationOptions() |
||||
|
{ |
||||
|
DefinitionProviders = new TypeList<INavigationDefinitionProvider>(); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using Volo.Abp.ObjectExtending; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpMultiTenancyModule), |
||||
|
typeof(AbpObjectExtendingModule))] |
||||
|
public class AbpUINavigationModule : AbpModule |
||||
|
{ |
||||
|
public override void PreConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
AutoAddDefinitionProviders(context.Services); |
||||
|
} |
||||
|
|
||||
|
private static void AutoAddDefinitionProviders(IServiceCollection services) |
||||
|
{ |
||||
|
var definitionProviders = new List<Type>(); |
||||
|
|
||||
|
services.OnRegistred(context => |
||||
|
{ |
||||
|
if (typeof(INavigationDefinitionProvider).IsAssignableFrom(context.ImplementationType)) |
||||
|
{ |
||||
|
definitionProviders.Add(context.ImplementationType); |
||||
|
} |
||||
|
}); |
||||
|
|
||||
|
services.Configure<AbpNavigationOptions>(options => |
||||
|
{ |
||||
|
options.DefinitionProviders.AddIfNotContains(definitionProviders); |
||||
|
}); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,113 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class ApplicationMenu : IHasMenuItems, IHasExtraProperties |
||||
|
{ |
||||
|
public const int DefaultOrder = 1000; |
||||
|
/// <summary>
|
||||
|
/// 名称
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Name { get; } |
||||
|
/// <summary>
|
||||
|
/// 显示名称
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string DisplayName { get; } |
||||
|
/// <summary>
|
||||
|
/// 说明
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Description { get; } |
||||
|
/// <summary>
|
||||
|
/// 路径
|
||||
|
/// </summary>
|
||||
|
[NotNull] |
||||
|
public string Url { get; } |
||||
|
/// <summary>
|
||||
|
/// 组件
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Component { get; } |
||||
|
/// <summary>
|
||||
|
/// 重定向
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Redirect { get; } |
||||
|
/// <summary>
|
||||
|
/// 图标
|
||||
|
/// </summary>
|
||||
|
[CanBeNull] |
||||
|
public string Icon { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 排序
|
||||
|
/// </summary>
|
||||
|
public int Order { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 是否禁用
|
||||
|
/// </summary>
|
||||
|
public bool IsDisabled { get; set; } |
||||
|
/// <summary>
|
||||
|
/// 是否可视
|
||||
|
/// </summary>
|
||||
|
public bool IsVisible { get; set; } |
||||
|
|
||||
|
[NotNull] |
||||
|
public ApplicationMenuList Items { get; } |
||||
|
|
||||
|
public bool IsLeaf => Items.IsNullOrEmpty(); |
||||
|
|
||||
|
[NotNull] |
||||
|
public ExtraPropertyDictionary ExtraProperties { get; } |
||||
|
|
||||
|
public MultiTenancySides MultiTenancySides { get; } |
||||
|
|
||||
|
public ApplicationMenu( |
||||
|
[NotNull] string name, |
||||
|
[NotNull] string displayName, |
||||
|
[NotNull] string url, |
||||
|
[CanBeNull] string component, |
||||
|
string description = null, |
||||
|
string icon = null, |
||||
|
string redirect = null, |
||||
|
int order = DefaultOrder, |
||||
|
MultiTenancySides multiTenancySides = MultiTenancySides.Both) |
||||
|
{ |
||||
|
Check.NotNullOrWhiteSpace(name, nameof(name)); |
||||
|
Check.NotNullOrWhiteSpace(displayName, nameof(displayName)); |
||||
|
|
||||
|
Check.NotNullOrWhiteSpace(url, nameof(url)); |
||||
|
|
||||
|
Name = name; |
||||
|
DisplayName = displayName; |
||||
|
Url = url; |
||||
|
Component = component; |
||||
|
Description = description; |
||||
|
Icon = icon; |
||||
|
Redirect = redirect ?? ""; |
||||
|
Order = order; |
||||
|
MultiTenancySides = multiTenancySides; |
||||
|
|
||||
|
Items = new ApplicationMenuList(); |
||||
|
ExtraProperties = new ExtraPropertyDictionary(); |
||||
|
this.SetDefaultsForExtraProperties(); |
||||
|
} |
||||
|
|
||||
|
public ApplicationMenu AddItem([NotNull] ApplicationMenu menuItem) |
||||
|
{ |
||||
|
Items.Add(menuItem); |
||||
|
return menuItem; |
||||
|
} |
||||
|
|
||||
|
public override string ToString() |
||||
|
{ |
||||
|
return $"[ApplicationMenu] Name = {Name}"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,45 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Linq; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class ApplicationMenuList : List<ApplicationMenu> |
||||
|
{ |
||||
|
public ApplicationMenuList() |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public ApplicationMenuList(int capacity) |
||||
|
: base(capacity) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public ApplicationMenuList(IEnumerable<ApplicationMenu> collection) |
||||
|
: base(collection) |
||||
|
{ |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public void Normalize() |
||||
|
{ |
||||
|
RemoveEmptyItems(); |
||||
|
Order(); |
||||
|
} |
||||
|
|
||||
|
private void RemoveEmptyItems() |
||||
|
{ |
||||
|
RemoveAll(item => item.IsLeaf && item.Url.IsNullOrEmpty()); |
||||
|
} |
||||
|
|
||||
|
private void Order() |
||||
|
{ |
||||
|
//TODO: Is there any way that is more performant?
|
||||
|
var orderedItems = this.OrderBy(item => item.Order).ToArray(); |
||||
|
Clear(); |
||||
|
AddRange(orderedItems); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface IHasMenuItems |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
/// Menu items.
|
||||
|
/// </summary>
|
||||
|
ApplicationMenuList Items { get; } |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface INavigationDataSeeder |
||||
|
{ |
||||
|
/// <summary>
|
||||
|
///
|
||||
|
/// </summary>
|
||||
|
/// <param name="menus">菜单列表</param>
|
||||
|
/// <param name="multiTenancySides">让用户自行决定是否过滤菜单</param>
|
||||
|
/// <returns></returns>
|
||||
|
Task SeedAsync( |
||||
|
IReadOnlyCollection<ApplicationMenu> menus, |
||||
|
MultiTenancySides multiTenancySides = MultiTenancySides.Both); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface INavigationDefinitionContext |
||||
|
{ |
||||
|
void Add(params NavigationDefinition[] definitions); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface INavigationDefinitionManager |
||||
|
{ |
||||
|
IReadOnlyList<NavigationDefinition> GetAll(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,7 @@ |
|||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface INavigationDefinitionProvider |
||||
|
{ |
||||
|
void Define(INavigationDefinitionContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,10 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public interface INavigationProvider |
||||
|
{ |
||||
|
Task<IReadOnlyCollection<ApplicationMenu>> GetAllAsync(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class NavigationDataSeedContributor : IDataSeedContributor, ITransientDependency |
||||
|
{ |
||||
|
private readonly ICurrentTenant _currentTenant; |
||||
|
private readonly INavigationProvider _navigationProvider; |
||||
|
private readonly INavigationDataSeeder _navigationDataSeeder; |
||||
|
|
||||
|
public NavigationDataSeedContributor( |
||||
|
ICurrentTenant currentTenant, |
||||
|
INavigationProvider navigationProvider, |
||||
|
INavigationDataSeeder navigationDataSeeder) |
||||
|
{ |
||||
|
_currentTenant = currentTenant; |
||||
|
_navigationProvider = navigationProvider; |
||||
|
_navigationDataSeeder = navigationDataSeeder; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task SeedAsync(DataSeedContext context) |
||||
|
{ |
||||
|
using(_currentTenant.Change(context.TenantId)) |
||||
|
{ |
||||
|
var multiTenancySides = _currentTenant.Id.HasValue |
||||
|
? MultiTenancySides.Tenant |
||||
|
: MultiTenancySides.Host; |
||||
|
|
||||
|
var menus = await _navigationProvider.GetAllAsync(); |
||||
|
|
||||
|
await _navigationDataSeeder.SeedAsync(menus, multiTenancySides); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class NavigationDefinition |
||||
|
{ |
||||
|
public ApplicationMenu Menu { get; } |
||||
|
public NavigationDefinition(ApplicationMenu menu) |
||||
|
{ |
||||
|
Menu = menu; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,28 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class NavigationDefinitionContext : INavigationDefinitionContext |
||||
|
{ |
||||
|
protected List<NavigationDefinition> Navigations { get; } |
||||
|
public NavigationDefinitionContext(List<NavigationDefinition> navigations) |
||||
|
{ |
||||
|
Navigations = navigations; |
||||
|
} |
||||
|
public virtual IReadOnlyList<NavigationDefinition> GetAll() |
||||
|
{ |
||||
|
return Navigations.ToImmutableList(); |
||||
|
} |
||||
|
|
||||
|
public virtual void Add(params NavigationDefinition[] definitions) |
||||
|
{ |
||||
|
if (definitions.IsNullOrEmpty()) |
||||
|
{ |
||||
|
return; |
||||
|
} |
||||
|
Navigations.AddRange(definitions); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,54 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
using System.Linq; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class NavigationDefinitionManager : INavigationDefinitionManager, ISingletonDependency |
||||
|
{ |
||||
|
protected Lazy<IList<NavigationDefinition>> NavigationDefinitions { get; } |
||||
|
|
||||
|
protected AbpNavigationOptions Options { get; } |
||||
|
|
||||
|
protected IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
public NavigationDefinitionManager( |
||||
|
IOptions<AbpNavigationOptions> options, |
||||
|
IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
ServiceProvider = serviceProvider; |
||||
|
Options = options.Value; |
||||
|
|
||||
|
NavigationDefinitions = new Lazy<IList<NavigationDefinition>>(CreateSettingDefinitions, true); |
||||
|
} |
||||
|
|
||||
|
public virtual IReadOnlyList<NavigationDefinition> GetAll() |
||||
|
{ |
||||
|
return NavigationDefinitions.Value.ToImmutableList(); |
||||
|
} |
||||
|
|
||||
|
protected virtual IList<NavigationDefinition> CreateSettingDefinitions() |
||||
|
{ |
||||
|
var settings = new List<NavigationDefinition>(); |
||||
|
|
||||
|
using (var scope = ServiceProvider.CreateScope()) |
||||
|
{ |
||||
|
var providers = Options |
||||
|
.DefinitionProviders |
||||
|
.Select(p => scope.ServiceProvider.GetRequiredService(p) as INavigationDefinitionProvider) |
||||
|
.ToList(); |
||||
|
|
||||
|
foreach (var provider in providers) |
||||
|
{ |
||||
|
provider.Define(new NavigationDefinitionContext(settings)); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return settings; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public abstract class NavigationDefinitionProvider : INavigationDefinitionProvider, ITransientDependency |
||||
|
{ |
||||
|
protected NavigationDefinitionProvider() |
||||
|
{ |
||||
|
} |
||||
|
public abstract void Define(INavigationDefinitionContext context); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,30 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Collections.Immutable; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
public class NavigationProvider : INavigationProvider, ITransientDependency |
||||
|
{ |
||||
|
protected INavigationDefinitionManager NavigationDefinitionManager { get; } |
||||
|
public NavigationProvider( |
||||
|
INavigationDefinitionManager navigationDefinitionManager) |
||||
|
{ |
||||
|
NavigationDefinitionManager = navigationDefinitionManager; |
||||
|
} |
||||
|
public Task<IReadOnlyCollection<ApplicationMenu>> GetAllAsync() |
||||
|
{ |
||||
|
var navigations = new List<ApplicationMenu>(); |
||||
|
var navigationDefineitions = NavigationDefinitionManager.GetAll(); |
||||
|
foreach (var navigationDefineition in navigationDefineitions) |
||||
|
{ |
||||
|
navigations.Add(navigationDefineition.Menu); |
||||
|
} |
||||
|
|
||||
|
IReadOnlyCollection<ApplicationMenu> menus = navigations.ToImmutableList(); |
||||
|
|
||||
|
return Task.FromResult(menus); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,18 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation |
||||
|
{ |
||||
|
[Dependency(TryRegister = true)] |
||||
|
public class NullNavigationDataSeeder : INavigationDataSeeder, ISingletonDependency |
||||
|
{ |
||||
|
public Task SeedAsync( |
||||
|
IReadOnlyCollection<ApplicationMenu> menus, |
||||
|
MultiTenancySides multiTenancySides = MultiTenancySides.Both) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,55 @@ |
|||||
|
# LINGYUN.Abp.UI.Navigation |
||||
|
|
||||
|
菜单导航模块,提供可扩展自定义的菜单项 |
||||
|
|
||||
|
## 配置使用 |
||||
|
|
||||
|
应用初始化时扫描所有实现 **INavigationDefinitionProvider** 接口的用户定义菜单项 |
||||
|
|
||||
|
通过 **INavigationDataSeeder** 接口初始化菜单种子数据 |
||||
|
|
||||
|
**INavigationDataSeeder** 的实现交给具体的实现 |
||||
|
|
||||
|
```csharp |
||||
|
[DependsOn(typeof(AbpUINavigationModule))] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
// other |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
```csharp |
||||
|
|
||||
|
public class FakeNavigationDefinitionProvider : NavigationDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(INavigationDefinitionContext context) |
||||
|
{ |
||||
|
context.Add(GetNavigationDefinition()); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetNavigationDefinition() |
||||
|
{ |
||||
|
var dashboard = new ApplicationMenu( |
||||
|
name: "Vben Dashboard", |
||||
|
displayName: "仪表盘", |
||||
|
url: "/dashboard", |
||||
|
component: "", |
||||
|
description: "仪表盘", |
||||
|
icon: "ion:grid-outline", |
||||
|
redirect: "/dashboard/analysis"); |
||||
|
|
||||
|
dashboard.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Analysis", |
||||
|
displayName: "分析页", |
||||
|
url: "/dashboard/analysis", |
||||
|
component: "/dashboard/analysis/index", |
||||
|
description: "分析页")); |
||||
|
|
||||
|
return new NavigationDefinition(dashboard); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
``` |
||||
|
|
||||
|
## 其他 |
||||
@ -0,0 +1,17 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Data" Version="4.4.0" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\navigation\LINGYUN.Abp.UI.Navigation\LINGYUN.Abp.UI.Navigation.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Platform.Domain\LINGYUN.Platform.Domain.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,399 @@ |
|||||
|
using LINGYUN.Platform.Datas; |
||||
|
using LINGYUN.Platform.Layouts; |
||||
|
using LINGYUN.Platform.Menus; |
||||
|
using LINGYUN.Platform.Routes; |
||||
|
using LINGYUN.Platform.Utils; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using System.Threading; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
using Volo.Abp.Guids; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
using ValueType = LINGYUN.Platform.Datas.ValueType; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation.VueVbenAdmin |
||||
|
{ |
||||
|
public class AbpUINavigationVueVbenAdminDataSeeder : INavigationDataSeeder, ITransientDependency |
||||
|
{ |
||||
|
private static int _lastCodeNumber = 0; |
||||
|
protected ICurrentTenant CurrentTenant { get; } |
||||
|
protected IGuidGenerator GuidGenerator { get; } |
||||
|
protected IRouteDataSeeder RouteDataSeeder { get; } |
||||
|
protected IDataDictionaryDataSeeder DataDictionaryDataSeeder { get; } |
||||
|
protected IMenuRepository MenuRepository { get; } |
||||
|
protected ILayoutRepository LayoutRepository { get; } |
||||
|
protected AbpUINavigationVueVbenAdminOptions Options { get; } |
||||
|
|
||||
|
public AbpUINavigationVueVbenAdminDataSeeder( |
||||
|
ICurrentTenant currentTenant, |
||||
|
IRouteDataSeeder routeDataSeeder, |
||||
|
IMenuRepository menuRepository, |
||||
|
ILayoutRepository layoutRepository, |
||||
|
IGuidGenerator guidGenerator, |
||||
|
IDataDictionaryDataSeeder dataDictionaryDataSeeder, |
||||
|
IOptions<AbpUINavigationVueVbenAdminOptions> options) |
||||
|
{ |
||||
|
CurrentTenant = currentTenant; |
||||
|
GuidGenerator = guidGenerator; |
||||
|
RouteDataSeeder = routeDataSeeder; |
||||
|
MenuRepository = menuRepository; |
||||
|
LayoutRepository = layoutRepository; |
||||
|
DataDictionaryDataSeeder = dataDictionaryDataSeeder; |
||||
|
|
||||
|
Options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task SeedAsync( |
||||
|
IReadOnlyCollection<ApplicationMenu> menus, |
||||
|
MultiTenancySides multiTenancySides = MultiTenancySides.Both) |
||||
|
{ |
||||
|
var uiDataItem = await SeedUIFrameworkDataAsync(CurrentTenant.Id); |
||||
|
|
||||
|
var layoutData = await SeedLayoutDataAsync(CurrentTenant.Id); |
||||
|
|
||||
|
var layout = await SeedDefaultLayoutAsync(layoutData, uiDataItem); |
||||
|
|
||||
|
var latMenu = await MenuRepository.GetLastMenuAsync(); |
||||
|
|
||||
|
if (int.TryParse(CodeNumberGenerator.GetLastCode(latMenu?.Code ?? "0"), out int _lastNumber)) |
||||
|
{ |
||||
|
Interlocked.Exchange(ref _lastCodeNumber, _lastNumber); |
||||
|
} |
||||
|
|
||||
|
await SeedDefinitionMenusAsync(layout, layoutData, menus, multiTenancySides); |
||||
|
} |
||||
|
|
||||
|
private async Task SeedDefinitionMenusAsync( |
||||
|
Layout layout, |
||||
|
Data data, |
||||
|
IReadOnlyCollection<ApplicationMenu> menus, |
||||
|
MultiTenancySides multiTenancySides) |
||||
|
{ |
||||
|
foreach (var menu in menus) |
||||
|
{ |
||||
|
if (!menu.MultiTenancySides.HasFlag(multiTenancySides)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var menuMeta = new Dictionary<string, object>() |
||||
|
{ |
||||
|
{ "title", menu.DisplayName }, |
||||
|
{ "icon", menu.Icon ?? "" }, |
||||
|
{ "hideTab", false }, |
||||
|
{ "ignoreAuth", false }, |
||||
|
}; |
||||
|
menuMeta.AddIfNotContains(menu.ExtraProperties); |
||||
|
|
||||
|
var seedMenu = await SeedMenuAsync( |
||||
|
layout: layout, |
||||
|
data: data, |
||||
|
name: menu.Name, |
||||
|
path: menu.Url, |
||||
|
code: CodeNumberGenerator.CreateCode(GetNextCode()), |
||||
|
component: layout.Path, |
||||
|
displayName: menu.DisplayName, |
||||
|
redirect: "", |
||||
|
description: menu.Description, |
||||
|
parentId: null, |
||||
|
tenantId: layout.TenantId, |
||||
|
meta: menuMeta, |
||||
|
roles: new string[] { "admin" }); |
||||
|
|
||||
|
await SeedDefinitionMenuItemsAsync(layout, data, seedMenu, menu.Items, multiTenancySides); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task SeedDefinitionMenuItemsAsync( |
||||
|
Layout layout, |
||||
|
Data data, |
||||
|
Menu menu, |
||||
|
ApplicationMenuList items, |
||||
|
MultiTenancySides multiTenancySides) |
||||
|
{ |
||||
|
int index = 1; |
||||
|
foreach (var item in items) |
||||
|
{ |
||||
|
if (!item.MultiTenancySides.HasFlag(multiTenancySides)) |
||||
|
{ |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
var menuMeta = new Dictionary<string, object>() |
||||
|
{ |
||||
|
{ "title", item.DisplayName }, |
||||
|
{ "icon", item.Icon ?? "" }, |
||||
|
{ "hideTab", false }, |
||||
|
{ "ignoreAuth", false }, |
||||
|
}; |
||||
|
menuMeta.AddIfNotContains(item.ExtraProperties); |
||||
|
|
||||
|
var seedMenu = await SeedMenuAsync( |
||||
|
layout: layout, |
||||
|
data: data, |
||||
|
name: item.Name, |
||||
|
path: item.Url, |
||||
|
code: CodeNumberGenerator.AppendCode(menu.Code, CodeNumberGenerator.CreateCode(index)), |
||||
|
component: item.Component.IsNullOrWhiteSpace() ? layout.Path : item.Component, |
||||
|
displayName: item.DisplayName, |
||||
|
redirect: "", |
||||
|
description: item.Description, |
||||
|
parentId: menu.Id, |
||||
|
tenantId: menu.TenantId, |
||||
|
meta: menuMeta, |
||||
|
roles: new string[] { "admin" }); |
||||
|
|
||||
|
await SeedDefinitionMenuItemsAsync(layout, data, seedMenu, item.Items, multiTenancySides); |
||||
|
|
||||
|
index++; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
private async Task<Menu> SeedMenuAsync( |
||||
|
Layout layout, |
||||
|
Data data, |
||||
|
string name, |
||||
|
string path, |
||||
|
string code, |
||||
|
string component, |
||||
|
string displayName, |
||||
|
string redirect = "", |
||||
|
string description = "", |
||||
|
Guid? parentId = null, |
||||
|
Guid? tenantId = null, |
||||
|
Dictionary<string, object> meta = null, |
||||
|
string[] roles = null, |
||||
|
Guid[] users = null, |
||||
|
bool isPublic = false |
||||
|
) |
||||
|
{ |
||||
|
var menu = await RouteDataSeeder.SeedMenuAsync( |
||||
|
layout, |
||||
|
name, |
||||
|
path, |
||||
|
code, |
||||
|
component, |
||||
|
displayName, |
||||
|
redirect, |
||||
|
description, |
||||
|
parentId, |
||||
|
tenantId, |
||||
|
isPublic |
||||
|
); |
||||
|
foreach (var item in data.Items) |
||||
|
{ |
||||
|
menu.SetProperty(item.Name, item.DefaultValue); |
||||
|
} |
||||
|
if (meta != null) |
||||
|
{ |
||||
|
foreach (var item in meta) |
||||
|
{ |
||||
|
menu.SetProperty(item.Key, item.Value); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (roles != null) |
||||
|
{ |
||||
|
foreach (var role in roles) |
||||
|
{ |
||||
|
await RouteDataSeeder.SeedRoleMenuAsync(role, menu, tenantId); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if (users != null) |
||||
|
{ |
||||
|
foreach (var user in users) |
||||
|
{ |
||||
|
await RouteDataSeeder.SeedUserMenuAsync(user, menu, tenantId); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return menu; |
||||
|
} |
||||
|
|
||||
|
private async Task<DataItem> SeedUIFrameworkDataAsync(Guid? tenantId) |
||||
|
{ |
||||
|
var data = await DataDictionaryDataSeeder |
||||
|
.SeedAsync( |
||||
|
"UI Framework", |
||||
|
CodeNumberGenerator.CreateCode(10), |
||||
|
"UI框架", |
||||
|
"UI Framework", |
||||
|
null, |
||||
|
tenantId, |
||||
|
true); |
||||
|
|
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
Options.UI, |
||||
|
Options.UI, |
||||
|
Options.UI, |
||||
|
ValueType.String, |
||||
|
Options.UI, |
||||
|
isStatic: true); |
||||
|
|
||||
|
return data.FindItem(Options.UI); |
||||
|
} |
||||
|
|
||||
|
private async Task<Layout> SeedDefaultLayoutAsync(Data data, DataItem uiDataItem) |
||||
|
{ |
||||
|
var layout = await RouteDataSeeder.SeedLayoutAsync( |
||||
|
Options.LayoutName, |
||||
|
Options.LayoutPath, // 路由层面已经处理好了,只需要传递LAYOUT可自动引用布局
|
||||
|
Options.LayoutName, |
||||
|
data.Id, |
||||
|
uiDataItem.Name, |
||||
|
"", |
||||
|
Options.LayoutName, |
||||
|
data.TenantId |
||||
|
); |
||||
|
|
||||
|
return layout; |
||||
|
} |
||||
|
|
||||
|
private async Task<Data> SeedLayoutDataAsync(Guid? tenantId) |
||||
|
{ |
||||
|
var data = await DataDictionaryDataSeeder |
||||
|
.SeedAsync( |
||||
|
Options.LayoutName, |
||||
|
CodeNumberGenerator.CreateCode(10), |
||||
|
"Vben Admin 布局约束", |
||||
|
"Vben Admin Layout Meta Dictionary", |
||||
|
null, |
||||
|
tenantId, |
||||
|
true); |
||||
|
|
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"hideMenu", |
||||
|
"不在菜单显示", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"当前路由不在菜单显示", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"icon", |
||||
|
"图标", |
||||
|
"", |
||||
|
ValueType.String, |
||||
|
"图标,也是菜单图标", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"currentActiveMenu", |
||||
|
"当前激活的菜单", |
||||
|
"", |
||||
|
ValueType.String, |
||||
|
"用于配置详情页时左侧激活的菜单路径", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"ignoreKeepAlive", |
||||
|
"KeepAlive缓存", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"是否忽略KeepAlive缓存", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"frameSrc", |
||||
|
"IFrame地址", |
||||
|
"", |
||||
|
ValueType.String, |
||||
|
"内嵌iframe的地址", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"transitionName", |
||||
|
"路由切换动画", |
||||
|
"", |
||||
|
ValueType.String, |
||||
|
"指定该路由切换的动画名", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"roles", |
||||
|
"可以访问的角色", |
||||
|
"", |
||||
|
ValueType.Array, |
||||
|
"可以访问的角色,只在权限模式为Role的时候有效", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"title", |
||||
|
"路由标题", |
||||
|
"", |
||||
|
ValueType.String, |
||||
|
"路由title 一般必填", |
||||
|
false, |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"carryParam", |
||||
|
"在tab页显示", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"如果该路由会携带参数,且需要在tab页上面显示。则需要设置为true", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"hideBreadcrumb", |
||||
|
"隐藏面包屑", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"隐藏该路由在面包屑上面的显示", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"ignoreAuth", |
||||
|
"忽略权限", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"是否忽略权限,只在权限模式为Role的时候有效", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"hideChildrenInMenu", |
||||
|
"隐藏所有子菜单", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"隐藏所有子菜单", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"hideTab", |
||||
|
"不在标签页显示", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"当前路由不在标签页显示", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"affix", |
||||
|
"固定标签页", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"是否固定标签页", |
||||
|
isStatic: true); |
||||
|
data.AddItem( |
||||
|
GuidGenerator, |
||||
|
"frameFormat", |
||||
|
"格式化IFrame", |
||||
|
"false", |
||||
|
ValueType.Boolean, |
||||
|
"扩展的格式化frame,{token}: 在打开的iframe页面传递token请求头"); |
||||
|
|
||||
|
return data; |
||||
|
} |
||||
|
|
||||
|
private int GetNextCode() |
||||
|
{ |
||||
|
Interlocked.Increment(ref _lastCodeNumber); |
||||
|
return _lastCodeNumber; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,12 @@ |
|||||
|
using LINGYUN.Platform; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation.VueVbenAdmin |
||||
|
{ |
||||
|
[DependsOn( |
||||
|
typeof(AbpUINavigationModule), |
||||
|
typeof(PlatformDomainModule))] |
||||
|
public class AbpUINavigationVueVbenAdminModule : AbpModule |
||||
|
{ |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,353 @@ |
|||||
|
using Volo.Abp.Data; |
||||
|
using Volo.Abp.MultiTenancy; |
||||
|
|
||||
|
namespace LINGYUN.Abp.UI.Navigation.VueVbenAdmin |
||||
|
{ |
||||
|
public class AbpUINavigationVueVbenAdminNavigationDefinitionProvider : NavigationDefinitionProvider |
||||
|
{ |
||||
|
public override void Define(INavigationDefinitionContext context) |
||||
|
{ |
||||
|
context.Add(GetDashboard()); |
||||
|
context.Add(GetManage()); |
||||
|
context.Add(GetSaas()); |
||||
|
context.Add(GetPlatform()); |
||||
|
context.Add(GetApiGateway()); |
||||
|
context.Add(GetLocalization()); |
||||
|
context.Add(GetOssManagement()); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetDashboard() |
||||
|
{ |
||||
|
var dashboard = new ApplicationMenu( |
||||
|
name: "Vben Dashboard", |
||||
|
displayName: "仪表盘", |
||||
|
url: "/dashboard", |
||||
|
component: "", |
||||
|
description: "仪表盘", |
||||
|
icon: "ion:grid-outline", |
||||
|
redirect: "/dashboard/workbench"); |
||||
|
|
||||
|
dashboard.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Analysis", |
||||
|
displayName: "分析页", |
||||
|
url: "/dashboard/analysis", |
||||
|
component: "/dashboard/analysis/index", |
||||
|
description: "分析页")); |
||||
|
dashboard.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Workbench", |
||||
|
displayName: "工作台", |
||||
|
url: "/dashboard/workbench", |
||||
|
component: "/dashboard/workbench/index", |
||||
|
description: "工作台")); |
||||
|
|
||||
|
|
||||
|
return new NavigationDefinition(dashboard); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetManage() |
||||
|
{ |
||||
|
var manage = new ApplicationMenu( |
||||
|
name: "Manage", |
||||
|
displayName: "管理", |
||||
|
url: "/manage", |
||||
|
component: "", |
||||
|
description: "管理", |
||||
|
icon: "ant-design:control-outlined"); |
||||
|
|
||||
|
var identity = manage.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Identity", |
||||
|
displayName: "身份认证管理", |
||||
|
url: "/manage/identity", |
||||
|
component: "", |
||||
|
description: "身份认证管理")); |
||||
|
identity.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "User", |
||||
|
displayName: "用户", |
||||
|
url: "/manage/identity/user", |
||||
|
component: "/identity/user/index", |
||||
|
description: "用户")); |
||||
|
identity.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Role", |
||||
|
displayName: "角色", |
||||
|
url: "/manage/identity/role", |
||||
|
component: "/identity/role/index", |
||||
|
description: "角色")); |
||||
|
identity.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Claim", |
||||
|
displayName: "身份标识", |
||||
|
url: "/manage/identity/claim-types", |
||||
|
component: "/identity/claim-types/index", |
||||
|
description: "身份标识", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identity.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "OrganizationUnits", |
||||
|
displayName: "组织机构", |
||||
|
url: "/manage/identity/organization-units", |
||||
|
component: "/identity/organization-units/index", |
||||
|
description: "组织机构")); |
||||
|
identity.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "SecurityLogs", |
||||
|
displayName: "安全日志", |
||||
|
url: "/manage/identity/security-logs", |
||||
|
component: "/identity/security-logs/index", |
||||
|
description: "安全日志") |
||||
|
// 此路由需要依赖安全日志特性
|
||||
|
.SetProperty("requiredFeatures", "AbpAuditing.Logging.SecurityLog")); |
||||
|
|
||||
|
manage.AddItem(new ApplicationMenu( |
||||
|
name: "AuditLogs", |
||||
|
displayName: "审计日志", |
||||
|
url: "/manage/audit-logs", |
||||
|
component: "/auditing/index", |
||||
|
description: "审计日志") |
||||
|
// 此路由需要依赖审计日志特性
|
||||
|
.SetProperty("requiredFeatures", "AbpAuditing.Logging.AuditLog")); |
||||
|
|
||||
|
manage.AddItem(new ApplicationMenu( |
||||
|
name: "Settings", |
||||
|
displayName: "设置", |
||||
|
url: "/manage/settings", |
||||
|
component: "/sys/settings/index", |
||||
|
description: "设置") |
||||
|
// 此路由需要依赖设置管理特性
|
||||
|
.SetProperty("requiredFeatures", "SettingManagement.Enable")); |
||||
|
|
||||
|
var identityServer = manage.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "IdentityServer", |
||||
|
displayName: "身份认证服务器", |
||||
|
url: "/manage/identity-server", |
||||
|
component: "", |
||||
|
description: "身份认证服务器", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identityServer.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Clients", |
||||
|
displayName: "客户端", |
||||
|
url: "/manage/identity-server/clients", |
||||
|
component: "/identity-server/clients/index", |
||||
|
description: "客户端", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identityServer.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "ApiResources", |
||||
|
displayName: "Api 资源", |
||||
|
url: "/manage/identity-server/api-resources", |
||||
|
component: "/identity-server/api-resources/index", |
||||
|
description: "Api 资源", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identityServer.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "IdentityResources", |
||||
|
displayName: "身份资源", |
||||
|
url: "/manage/identity-server/identity-resources", |
||||
|
component: "/identity-server/identity-resources/index", |
||||
|
description: "身份资源", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identityServer.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "ApiScopes", |
||||
|
displayName: "Api 范围", |
||||
|
url: "/manage/identity-server/api-scopes", |
||||
|
component: "/identity-server/api-scopes/index", |
||||
|
description: "Api 范围", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
identityServer.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "PersistedGrants", |
||||
|
displayName: "持久授权", |
||||
|
url: "/manage/identity-server/persisted-grants", |
||||
|
component: "/identity-server/persisted-grants/index", |
||||
|
description: "持久授权", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
|
||||
|
|
||||
|
manage.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Logs", |
||||
|
displayName: "系统日志", |
||||
|
url: "/sys/logs", |
||||
|
component: "/sys/logging/index", |
||||
|
description: "系统日志")); |
||||
|
|
||||
|
return new NavigationDefinition(manage); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetSaas() |
||||
|
{ |
||||
|
var saas = new ApplicationMenu( |
||||
|
name: "Saas", |
||||
|
displayName: "Saas", |
||||
|
url: "/saas", |
||||
|
component: "", |
||||
|
description: "Saas", |
||||
|
icon: "ant-design:cloud-server-outlined", |
||||
|
multiTenancySides: MultiTenancySides.Host); |
||||
|
saas.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Tenants", |
||||
|
displayName: "租户管理", |
||||
|
url: "/saas/tenants", |
||||
|
component: "/saas/tenant/index", |
||||
|
description: "租户管理", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
|
||||
|
return new NavigationDefinition(saas); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetPlatform() |
||||
|
{ |
||||
|
var platform = new ApplicationMenu( |
||||
|
name: "Platform", |
||||
|
displayName: "平台管理", |
||||
|
url: "/platform", |
||||
|
component: "", |
||||
|
description: "平台管理"); |
||||
|
platform.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "DataDictionary", |
||||
|
displayName: "数据字典", |
||||
|
url: "/platform/data-dic", |
||||
|
component: "/platform/dataDic/index", |
||||
|
description: "数据字典")); |
||||
|
platform.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Layout", |
||||
|
displayName: "布局", |
||||
|
url: "/platform/layout", |
||||
|
component: "/platform/layout/index", |
||||
|
description: "布局")); |
||||
|
platform.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Menu", |
||||
|
displayName: "菜单", |
||||
|
url: "/platform/menu", |
||||
|
component: "/platform/menu/index", |
||||
|
description: "菜单")); |
||||
|
|
||||
|
return new NavigationDefinition(platform); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetApiGateway() |
||||
|
{ |
||||
|
var apiGateway = new ApplicationMenu( |
||||
|
name: "ApiGateway", |
||||
|
displayName: "网关管理", |
||||
|
url: "/api-gateway", |
||||
|
component: "", |
||||
|
description: "网关管理", |
||||
|
icon: "ant-design:gateway-outlined", |
||||
|
multiTenancySides: MultiTenancySides.Host); |
||||
|
apiGateway.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "RouteGroup", |
||||
|
displayName: "路由分组", |
||||
|
url: "/api-gateway/group", |
||||
|
component: "/api-gateway/group/index", |
||||
|
description: "路由分组", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
apiGateway.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "GlobalConfiguration", |
||||
|
displayName: "公共配置", |
||||
|
url: "/api-gateway/global", |
||||
|
component: "/api-gateway/global/index", |
||||
|
description: "公共配置", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
apiGateway.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Route", |
||||
|
displayName: "路由管理", |
||||
|
url: "/api-gateway/route", |
||||
|
component: "/api-gateway/route/index", |
||||
|
description: "路由管理", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
apiGateway.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "AggregateRoute", |
||||
|
displayName: "聚合路由", |
||||
|
url: "/api-gateway/aggregate", |
||||
|
component: "/api-gateway/aggregate/index", |
||||
|
description: "聚合路由", |
||||
|
multiTenancySides: MultiTenancySides.Host)); |
||||
|
|
||||
|
return new NavigationDefinition(apiGateway); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetLocalization() |
||||
|
{ |
||||
|
var localization = new ApplicationMenu( |
||||
|
name: "Localization", |
||||
|
displayName: "本地化管理", |
||||
|
url: "/localization", |
||||
|
component: "", |
||||
|
description: "本地化管理", |
||||
|
icon: "ant-design:translation-outlined", |
||||
|
multiTenancySides: MultiTenancySides.Host); |
||||
|
localization.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Languages", |
||||
|
displayName: "语言管理", |
||||
|
url: "/localization/languages", |
||||
|
component: "/localization/languages/index", |
||||
|
description: "语言管理", |
||||
|
multiTenancySides: MultiTenancySides.Host) |
||||
|
); |
||||
|
localization.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Resources", |
||||
|
displayName: "资源管理", |
||||
|
url: "/localization/resources", |
||||
|
component: "/localization/resources/index", |
||||
|
description: "资源管理", |
||||
|
multiTenancySides: MultiTenancySides.Host) |
||||
|
); |
||||
|
localization.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Texts", |
||||
|
displayName: "文档管理", |
||||
|
url: "/localization/texts", |
||||
|
component: "/localization/texts/index", |
||||
|
description: "文档管理", |
||||
|
multiTenancySides: MultiTenancySides.Host) |
||||
|
); |
||||
|
|
||||
|
return new NavigationDefinition(localization); |
||||
|
} |
||||
|
|
||||
|
private static NavigationDefinition GetOssManagement() |
||||
|
{ |
||||
|
var oss = new ApplicationMenu( |
||||
|
name: "OssManagement", |
||||
|
displayName: "对象存储", |
||||
|
url: "/oss", |
||||
|
component: "", |
||||
|
description: "对象存储", |
||||
|
icon: "ant-design:file-twotone"); |
||||
|
oss.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Containers", |
||||
|
displayName: "容器管理", |
||||
|
url: "/oss/containers", |
||||
|
component: "/oss-management/containers/index", |
||||
|
description: "容器管理")); |
||||
|
oss.AddItem( |
||||
|
new ApplicationMenu( |
||||
|
name: "Objects", |
||||
|
displayName: "文件管理", |
||||
|
url: "/oss/objects", |
||||
|
component: "/oss-management/objects/index", |
||||
|
description: "文件管理")); |
||||
|
|
||||
|
return new NavigationDefinition(oss); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
namespace LINGYUN.Abp.UI.Navigation.VueVbenAdmin |
||||
|
{ |
||||
|
public class AbpUINavigationVueVbenAdminOptions |
||||
|
{ |
||||
|
public string UI { get; set; } |
||||
|
public string LayoutName { get; set; } |
||||
|
public string LayoutPath { get; set; } |
||||
|
public AbpUINavigationVueVbenAdminOptions() |
||||
|
{ |
||||
|
UI = "Vue Vben Admin"; |
||||
|
LayoutName = "Vben Admin Layout"; |
||||
|
LayoutPath = "LAYOUT"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
# LINGYUN.Abp.UI.Navigation.VueVbenAdmin |
||||
|
|
||||
|
适用于 **abp-vue-vben-admin** 的初始化菜单数据模块 |
||||
|
|
||||
|
## 配置使用 |
||||
|
|
||||
|
```csharp |
||||
|
[DependsOn(typeof(AbpUINavigationVueVbenAdminModule))] |
||||
|
public class YouProjectModule : AbpModule |
||||
|
{ |
||||
|
// other |
||||
|
} |
||||
|
``` |
||||
|
|
||||
|
## 配置项 |
||||
|
|
||||
|
* AbpUINavigationVueVbenAdminOptions.UI UI名称,默认值: Vue Vben Admin,不建议变更,否则需要改变前端 |
||||
|
* AbpUINavigationVueVbenAdminOptions.LayoutName 布局名称,默认值: Vben Admin Layout,不建议变更,否则需要改变前端 |
||||
|
* AbpUINavigationVueVbenAdminOptions.LayoutPath 布局组件,默认值: LAYOUT,不建议变更,否则需要改变前端 |
||||
|
|
||||
|
## 其他 |
||||
@ -1,962 +0,0 @@ |
|||||
using LINGYUN.Platform.Datas; |
|
||||
using LINGYUN.Platform.Layouts; |
|
||||
using LINGYUN.Platform.Menus; |
|
||||
using LINGYUN.Platform.Routes; |
|
||||
using LINGYUN.Platform.Utils; |
|
||||
using System; |
|
||||
using System.Collections.Generic; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.Data; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
using Volo.Abp.Guids; |
|
||||
using Volo.Abp.MultiTenancy; |
|
||||
|
|
||||
namespace LINGYUN.Platform.DataSeeder |
|
||||
{ |
|
||||
public class ElementAdminDataSeedContributor : IDataSeedContributor, ITransientDependency |
|
||||
{ |
|
||||
protected ICurrentTenant CurrentTenant { get; } |
|
||||
protected IGuidGenerator GuidGenerator { get; } |
|
||||
protected IRouteDataSeeder RouteDataSeeder { get; } |
|
||||
protected IDataDictionaryDataSeeder DataDictionaryDataSeeder { get; } |
|
||||
protected IMenuRepository MenuRepository { get; } |
|
||||
protected ILayoutRepository LayoutRepository { get; } |
|
||||
|
|
||||
public ElementAdminDataSeedContributor( |
|
||||
ICurrentTenant currentTenant, |
|
||||
IRouteDataSeeder routeDataSeeder, |
|
||||
IMenuRepository menuRepository, |
|
||||
ILayoutRepository layoutRepository, |
|
||||
IGuidGenerator guidGenerator, |
|
||||
IDataDictionaryDataSeeder dataDictionaryDataSeeder) |
|
||||
{ |
|
||||
CurrentTenant = currentTenant; |
|
||||
GuidGenerator = guidGenerator; |
|
||||
RouteDataSeeder = routeDataSeeder; |
|
||||
MenuRepository = menuRepository; |
|
||||
LayoutRepository = layoutRepository; |
|
||||
DataDictionaryDataSeeder = dataDictionaryDataSeeder; |
|
||||
} |
|
||||
|
|
||||
public virtual async Task SeedAsync(DataSeedContext context) |
|
||||
{ |
|
||||
await Task.CompletedTask; |
|
||||
//using (CurrentTenant.Change(context.TenantId))
|
|
||||
//{
|
|
||||
// var uiItem = await SeedUIFrameworkDataAsync(context.TenantId);
|
|
||||
// var data = await SeedLayoutDataAsync(context.TenantId);
|
|
||||
// // 预置
|
|
||||
// var layout = await SeedDefaultLayoutAsync(data, uiItem);
|
|
||||
// // 首页
|
|
||||
// await SeedHomeMenuAsync(layout, data);
|
|
||||
// // 管理菜单预置菜单数据
|
|
||||
// await SeedAdminMenuAsync(layout, data);
|
|
||||
// // saas菜单数据
|
|
||||
// await SeedSaasMenuAsync(layout, data);
|
|
||||
// // 身份资源菜单数据
|
|
||||
// await SeedIdentityServerMenuAsync(layout, data);
|
|
||||
// // 审计日志菜单数据
|
|
||||
// await SeedAuditingMenuAsync(layout, data);
|
|
||||
// // 布局容器预置菜单数据
|
|
||||
// await SeedContainerMenuAsync(layout, data);
|
|
||||
// // 网关管理菜单数据
|
|
||||
// await SeedApiGatewayMenuAsync(layout, data);
|
|
||||
// // Oss对象管理菜单数据
|
|
||||
// await SeedOssManagementMenuAsync(layout, data);
|
|
||||
// // 本地化管理菜单数据
|
|
||||
// await SeedLocalizationManagementMenuAsync(layout, data);
|
|
||||
//}
|
|
||||
} |
|
||||
|
|
||||
private async Task<DataItem> SeedUIFrameworkDataAsync(Guid? tenantId) |
|
||||
{ |
|
||||
var data = await DataDictionaryDataSeeder |
|
||||
.SeedAsync( |
|
||||
"UI Framework", |
|
||||
CodeNumberGenerator.CreateCode(2), |
|
||||
"UI框架", |
|
||||
"UI Framework", |
|
||||
null, |
|
||||
tenantId, |
|
||||
true); |
|
||||
|
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"Vue Element Admin", |
|
||||
"Vue Element Admin", |
|
||||
"Vue Element Admin", |
|
||||
Datas.ValueType.String, |
|
||||
"Vue Element Admin", |
|
||||
isStatic: true); |
|
||||
|
|
||||
return data.FindItem("Vue Element Admin"); |
|
||||
} |
|
||||
|
|
||||
private async Task<Data> SeedLayoutDataAsync(Guid? tenantId) |
|
||||
{ |
|
||||
var data = await DataDictionaryDataSeeder |
|
||||
.SeedAsync( |
|
||||
"Layout", |
|
||||
CodeNumberGenerator.CreateCode(1), |
|
||||
"Vue Admin Layout Meta Dictionary", |
|
||||
"Vue Admin Layout Meta Dictionary", |
|
||||
null, |
|
||||
tenantId, |
|
||||
true); |
|
||||
|
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"roles", // TODO: 是否需要把这一项写入到预置数据?
|
|
||||
"roles", |
|
||||
"", |
|
||||
Datas.ValueType.Array, |
|
||||
"will control the page roles (allow setting multiple roles)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"title", |
|
||||
"title", |
|
||||
"component", |
|
||||
Datas.ValueType.String, |
|
||||
"the name showed in subMenu and breadcrumb (recommend set)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"icon", |
|
||||
"icon", |
|
||||
"icon", |
|
||||
Datas.ValueType.String, |
|
||||
"the icon showed in the sidebar", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"hidden", |
|
||||
"hidden", |
|
||||
"false", |
|
||||
Datas.ValueType.Boolean, |
|
||||
"if true, this route will not show in the sidebar (default is false)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"alwaysShow", |
|
||||
"alwaysShow", |
|
||||
"false", |
|
||||
Datas.ValueType.Boolean, |
|
||||
"if true, will always show the root menu (default is false)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"breadcrumb", |
|
||||
"breadcrumb", |
|
||||
"true", |
|
||||
Datas.ValueType.Boolean, |
|
||||
"if false, the item will be hidden in breadcrumb (default is true)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"noCache", |
|
||||
"noCache", |
|
||||
"false", |
|
||||
Datas.ValueType.Boolean, |
|
||||
"if true, the page will not be cached (default is false)", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"affix", |
|
||||
"affix", |
|
||||
"false", |
|
||||
Datas.ValueType.Boolean, |
|
||||
"if true, the tag will affix in the tags-view", |
|
||||
isStatic: true); |
|
||||
data.AddItem( |
|
||||
GuidGenerator, |
|
||||
"activeMenu", |
|
||||
"activeMenu", |
|
||||
"", |
|
||||
Datas.ValueType.String, |
|
||||
"if set path, the sidebar will highlight the path you set", |
|
||||
isStatic: true); |
|
||||
|
|
||||
return data; |
|
||||
} |
|
||||
|
|
||||
private async Task<Layout> SeedDefaultLayoutAsync(Data data, DataItem uiDataItem) |
|
||||
{ |
|
||||
var layout = await RouteDataSeeder.SeedLayoutAsync( |
|
||||
"Layout", |
|
||||
"layout/index.vue", |
|
||||
"Vue Admin Layout", |
|
||||
data.Id, |
|
||||
uiDataItem.Name, |
|
||||
"", |
|
||||
"Vue Admin Layout", |
|
||||
data.TenantId |
|
||||
); |
|
||||
|
|
||||
return layout; |
|
||||
} |
|
||||
|
|
||||
private async Task SeedHomeMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var adminMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"home", |
|
||||
"/", |
|
||||
CodeNumberGenerator.CreateCode(1), |
|
||||
layout.Path, |
|
||||
"Home", |
|
||||
"/dashboard", |
|
||||
"Home", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "home" }, |
|
||||
{ "icon", "home" }, |
|
||||
{ "alwaysShow", true } |
|
||||
}, |
|
||||
// isPublic: true,
|
|
||||
isPublic: false); // 首页应该是共有的页面
|
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"dashboard", |
|
||||
"dashboard", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/dashboard/index.vue", |
|
||||
"Dashboard", |
|
||||
"", |
|
||||
"Dashboard", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "dashboard" }, |
|
||||
{ "icon", "dashboard" } |
|
||||
}, |
|
||||
isPublic: false); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedAdminMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var adminMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"admin", |
|
||||
"/admin", |
|
||||
CodeNumberGenerator.CreateCode(2), |
|
||||
layout.Path, |
|
||||
"Admin", |
|
||||
"", |
|
||||
"Admin", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "admin" }, |
|
||||
{ "icon", "admin" }, |
|
||||
{ "alwaysShow", true } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"roles", |
|
||||
"roles", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/admin/roles/index.vue", |
|
||||
"Manage Roles", |
|
||||
"", |
|
||||
"Manage Roles", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "roles" }, |
|
||||
{ "icon", "role" }, |
|
||||
{ "roles", new string[] { "AbpIdentity.Roles" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"users", |
|
||||
"users", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/admin/users/index.vue", |
|
||||
"Manage Users", |
|
||||
"", |
|
||||
"Manage Users", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "users" }, |
|
||||
{ "icon", "users" }, |
|
||||
{ "roles", new string[] { "AbpIdentity.Users" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"organization-unit", |
|
||||
"organization-unit", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(3)), |
|
||||
"views/admin/organization-unit/index.vue", |
|
||||
"Manage Organization Units", |
|
||||
"", |
|
||||
"Manage Organization Units", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "organization-unit" }, |
|
||||
{ "icon", "organization-unit" }, |
|
||||
{ "roles", new string[] { "AbpIdentity.OrganizationUnits" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"claim-type", |
|
||||
"claim-type", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(4)), |
|
||||
"views/admin/claim-type/index.vue", |
|
||||
"Manage Claim Types", |
|
||||
"", |
|
||||
"Manage Claim Types", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "claim-type" }, |
|
||||
{ "icon", "claim-type" }, |
|
||||
{ "roles", new string[] { "AbpIdentity.IdentityClaimTypes" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"data-dictionary", |
|
||||
"data-dictionary", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(5)), |
|
||||
"views/admin/data-dictionary/index.vue", |
|
||||
"Manage Data Dictionarys", |
|
||||
"", |
|
||||
"Manage Data Dictionarys", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "data-dictionary" }, |
|
||||
{ "icon", "data-dictionary" }, |
|
||||
{ "roles", new string[] { "Platform.DataDictionary" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"settings", |
|
||||
"settings", |
|
||||
CodeNumberGenerator.AppendCode(adminMenu.Code, CodeNumberGenerator.CreateCode(6)), |
|
||||
"views/admin/settings/index.vue", |
|
||||
"Manage Settings", |
|
||||
"", |
|
||||
"Manage Settings", |
|
||||
adminMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "settings" }, |
|
||||
{ "icon", "settings" }, |
|
||||
{ "roles", new string[] { "AbpSettingManagement.Settings" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedSaasMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var saasMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"saas", |
|
||||
"/saas", |
|
||||
CodeNumberGenerator.CreateCode(3), |
|
||||
layout.Path, |
|
||||
"Saas", |
|
||||
"", |
|
||||
"Saas", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "saas" }, |
|
||||
{ "icon", "saas" }, |
|
||||
{ "alwaysShow", true } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"editions", |
|
||||
"editions", |
|
||||
CodeNumberGenerator.AppendCode(saasMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/admin/edition/index.vue", |
|
||||
"Manage Editions", |
|
||||
"", |
|
||||
"Manage Editions", |
|
||||
saasMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "editions" }, |
|
||||
{ "icon", "editions" } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"tenants", |
|
||||
"tenants", |
|
||||
CodeNumberGenerator.AppendCode(saasMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/admin/tenants/index.vue", |
|
||||
"Manage Tenants", |
|
||||
"", |
|
||||
"Manage Tenants", |
|
||||
saasMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "tenants" }, |
|
||||
{ "icon", "tenants" } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedIdentityServerMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var identityServerMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"identity-server", |
|
||||
"/identity-server", |
|
||||
CodeNumberGenerator.CreateCode(4), |
|
||||
layout.Path, |
|
||||
"Identity Server", |
|
||||
"", |
|
||||
"Identity Server", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "identity-server" }, |
|
||||
{ "icon", "identity-server" }, |
|
||||
{ "alwaysShow", true }, |
|
||||
{ "roles", new string[]{ "AbpIdentityServer.Clients", "AbpIdentityServer.ApiResources", "AbpIdentityServer.IdentityResources", "AbpIdentityServer.ApiScopes" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"clients", |
|
||||
"clients", |
|
||||
CodeNumberGenerator.AppendCode(identityServerMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/admin/identityServer/client/index.vue", |
|
||||
"Manage Clients", |
|
||||
"", |
|
||||
"Manage Clients", |
|
||||
identityServerMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "clients" }, |
|
||||
{ "icon", "client" }, |
|
||||
{ "roles", new string[]{ "AbpIdentityServer.Clients" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"api-resources", |
|
||||
"api-resources", |
|
||||
CodeNumberGenerator.AppendCode(identityServerMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/admin/identityServer/api-resources/index.vue", |
|
||||
"Manage Api Resources", |
|
||||
"", |
|
||||
"Manage Api Resources", |
|
||||
identityServerMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "api-resources" }, |
|
||||
{ "icon", "api" }, |
|
||||
{ "roles", new string[]{ "AbpIdentityServer.ApiResources" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"identity-resources", |
|
||||
"identity-resources", |
|
||||
CodeNumberGenerator.AppendCode(identityServerMenu.Code, CodeNumberGenerator.CreateCode(3)), |
|
||||
"views/admin/identityServer/identity-resources/index.vue", |
|
||||
"Manage Identity Resources", |
|
||||
"", |
|
||||
"Manage Identity Resources", |
|
||||
identityServerMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "identity-resources" }, |
|
||||
{ "icon", "identity" }, |
|
||||
{ "roles", new string[]{ "AbpIdentityServer.IdentityResources" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"api-scopes", |
|
||||
"api-scopes", |
|
||||
CodeNumberGenerator.AppendCode(identityServerMenu.Code, CodeNumberGenerator.CreateCode(4)), |
|
||||
"views/admin/identityServer/api-scopes/index.vue", |
|
||||
"Manage Api Scopes", |
|
||||
"", |
|
||||
"Manage Api Scopes", |
|
||||
identityServerMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "api-scopes" }, |
|
||||
{ "icon", "api-scopes" }, |
|
||||
{ "roles", new string[]{ "AbpIdentityServer.ApiScopes" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedAuditingMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var auditingMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"auditing", |
|
||||
"/auditing", |
|
||||
CodeNumberGenerator.CreateCode(5), |
|
||||
layout.Path, |
|
||||
"Auditing", |
|
||||
"", |
|
||||
"Auditing", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "auditing" }, |
|
||||
{ "icon", "auditing" }, |
|
||||
{ "alwaysShow", true }, |
|
||||
{ "roles", new string[]{ "AbpAuditing.AuditLog", "AbpAuditing.SecurityLog" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"audit-log", |
|
||||
"audit-log", |
|
||||
CodeNumberGenerator.AppendCode(auditingMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/admin/auditing/audit-log/index.vue", |
|
||||
"Manage AuditLog", |
|
||||
"", |
|
||||
"Manage AuditLog", |
|
||||
auditingMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "audit-log" }, |
|
||||
{ "icon", "audit-log" }, |
|
||||
{ "roles", new string[]{ "AbpAuditing.AuditLog" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"security-log", |
|
||||
"security-log", |
|
||||
CodeNumberGenerator.AppendCode(auditingMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/admin/auditing/security-log/index.vue", |
|
||||
"Manage SecurityLog", |
|
||||
"", |
|
||||
"Manage SecurityLog", |
|
||||
auditingMenu.Id, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "security-log" }, |
|
||||
{ "icon", "security-log" }, |
|
||||
{ "roles", new string[]{ "AbpAuditing.SecurityLog" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedContainerMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var containerRoot = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"container", |
|
||||
"/container", |
|
||||
CodeNumberGenerator.CreateCode(6), |
|
||||
layout.Path, |
|
||||
"Container", |
|
||||
"", |
|
||||
"Manage Container", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "container" }, |
|
||||
{ "icon", "container" }, |
|
||||
{ "alwaysShow", true } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"layouts", |
|
||||
"layouts", |
|
||||
CodeNumberGenerator.AppendCode(containerRoot.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/container/layouts/index.vue", |
|
||||
"Manage Layouts", |
|
||||
"", |
|
||||
"Manage Layouts", |
|
||||
containerRoot.Id, |
|
||||
containerRoot.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "layouts" }, |
|
||||
{ "icon", "layout" } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"menus", |
|
||||
"menus", |
|
||||
CodeNumberGenerator.AppendCode(containerRoot.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/container/menus/index.vue", |
|
||||
"Manage Menus", |
|
||||
"", |
|
||||
"Manage Menus", |
|
||||
containerRoot.Id, |
|
||||
containerRoot.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "menus" }, |
|
||||
{ "icon", "menu" } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedApiGatewayMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var apiGatewayMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"apigateway", |
|
||||
"/apigateway", |
|
||||
CodeNumberGenerator.CreateCode(7), |
|
||||
layout.Path, |
|
||||
"Manage Api Gateway", |
|
||||
"/group", |
|
||||
"Manage Api Gateway", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "api-gateway" }, |
|
||||
{ "icon", "api-gateway" }, |
|
||||
{ "alwaysShow", true }, |
|
||||
{ "roles", new string[] { "ApiGateway.RouteGroup", "ApiGateway.Global", "ApiGateway.Route", "ApiGateway.DynamicRoute", "ApiGateway.AggregateRoute" } }, |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"group", |
|
||||
"group", |
|
||||
CodeNumberGenerator.AppendCode(apiGatewayMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/admin/apigateway/group.vue", |
|
||||
"Manage Groups", |
|
||||
"", |
|
||||
"Manage Groups", |
|
||||
apiGatewayMenu.Id, |
|
||||
apiGatewayMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "group" }, |
|
||||
{ "icon", "group" }, |
|
||||
{ "roles", new string[] { "ApiGateway.RouteGroup" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"global", |
|
||||
"global", |
|
||||
CodeNumberGenerator.AppendCode(apiGatewayMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/admin/apigateway/global.vue", |
|
||||
"Manage Globals", |
|
||||
"", |
|
||||
"Manage Globals", |
|
||||
apiGatewayMenu.Id, |
|
||||
apiGatewayMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "global" }, |
|
||||
{ "icon", "global-setting" }, |
|
||||
{ "roles", new string[] { "ApiGateway.Global" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"route", |
|
||||
"route", |
|
||||
CodeNumberGenerator.AppendCode(apiGatewayMenu.Code, CodeNumberGenerator.CreateCode(3)), |
|
||||
"views/admin/apigateway/route.vue", |
|
||||
"Manage Routes", |
|
||||
"", |
|
||||
"Manage Routes", |
|
||||
apiGatewayMenu.Id, |
|
||||
apiGatewayMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "route" }, |
|
||||
{ "icon", "route" }, |
|
||||
{ "roles", new string[] { "ApiGateway.Route" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"aggregate-route", |
|
||||
"aggregate-route", |
|
||||
CodeNumberGenerator.AppendCode(apiGatewayMenu.Code, CodeNumberGenerator.CreateCode(4)), |
|
||||
"views/admin/apigateway/aggregateRoute.vue", |
|
||||
"Manage Aggregate Routes", |
|
||||
"", |
|
||||
"Manage Aggregate Routes", |
|
||||
apiGatewayMenu.Id, |
|
||||
apiGatewayMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "aggregate-route" }, |
|
||||
{ "icon", "aggregate" }, |
|
||||
{ "roles", new string[] { "ApiGateway.AggregateRoute " } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedOssManagementMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var ossManagementMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"oss-management", |
|
||||
"/oss-management", |
|
||||
CodeNumberGenerator.CreateCode(8), |
|
||||
layout.Path, |
|
||||
"Manage Object Storage", |
|
||||
"/oss-manager", |
|
||||
"Manage Object Storage", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "oss-management" }, |
|
||||
{ "icon", "file-system" }, |
|
||||
{ "alwaysShow", true }, |
|
||||
{ "roles", new string[] { "AbpOssManagement.Container", "AbpOssManagement.OssObject" } }, |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"oss-manager", |
|
||||
"oss-manager", |
|
||||
CodeNumberGenerator.AppendCode(ossManagementMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/oss-management/index.vue", |
|
||||
"Manage Oss Object", |
|
||||
"", |
|
||||
"Manage Oss Object", |
|
||||
ossManagementMenu.Id, |
|
||||
ossManagementMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "oss-objects" }, |
|
||||
{ "icon", "file-system" }, |
|
||||
{ "roles", new string[] { "AbpOssManagement.OssObject" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
} |
|
||||
|
|
||||
private async Task SeedLocalizationManagementMenuAsync(Layout layout, Data data) |
|
||||
{ |
|
||||
var localizationManagementMenu = await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"localization-management", |
|
||||
"/localization-management", |
|
||||
CodeNumberGenerator.CreateCode(9), |
|
||||
layout.Path, |
|
||||
"Manage Localization", |
|
||||
"/localization", |
|
||||
"Manage Localization", |
|
||||
null, |
|
||||
layout.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "localization" }, |
|
||||
{ "icon", "localization" }, |
|
||||
{ "alwaysShow", true }, |
|
||||
{ "roles", new string[] { "LocalizationManagement.Resource", "LocalizationManagement.Language", "LocalizationManagement.Text" } }, |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"resource", |
|
||||
"resource", |
|
||||
CodeNumberGenerator.AppendCode(localizationManagementMenu.Code, CodeNumberGenerator.CreateCode(1)), |
|
||||
"views/localization-management/resources/index.vue", |
|
||||
"Manage Resource", |
|
||||
"", |
|
||||
"Manage Resource", |
|
||||
localizationManagementMenu.Id, |
|
||||
localizationManagementMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "resource" }, |
|
||||
{ "icon", "resource" }, |
|
||||
{ "roles", new string[] { "LocalizationManagement.Resource" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"language", |
|
||||
"language", |
|
||||
CodeNumberGenerator.AppendCode(localizationManagementMenu.Code, CodeNumberGenerator.CreateCode(2)), |
|
||||
"views/localization-management/languages/index.vue", |
|
||||
"Manage Language", |
|
||||
"", |
|
||||
"Manage Language", |
|
||||
localizationManagementMenu.Id, |
|
||||
localizationManagementMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "language" }, |
|
||||
{ "icon", "language" }, |
|
||||
{ "roles", new string[] { "LocalizationManagement.Language" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
await SeedMenuAsync( |
|
||||
layout, |
|
||||
data, |
|
||||
"text", |
|
||||
"text", |
|
||||
CodeNumberGenerator.AppendCode(localizationManagementMenu.Code, CodeNumberGenerator.CreateCode(3)), |
|
||||
"views/localization-management/texts/index.vue", |
|
||||
"Manage Text", |
|
||||
"", |
|
||||
"Manage Text", |
|
||||
localizationManagementMenu.Id, |
|
||||
localizationManagementMenu.TenantId, |
|
||||
new Dictionary<string, object>() |
|
||||
{ |
|
||||
{ "title", "text" }, |
|
||||
{ "icon", "text" }, |
|
||||
{ "roles", new string[] { "LocalizationManagement.Text" } } |
|
||||
}, |
|
||||
new string[] { "admin" }); |
|
||||
|
|
||||
} |
|
||||
private async Task<Menu> SeedMenuAsync( |
|
||||
Layout layout, |
|
||||
Data data, |
|
||||
string name, |
|
||||
string path, |
|
||||
string code, |
|
||||
string component, |
|
||||
string displayName, |
|
||||
string redirect = "", |
|
||||
string description = "", |
|
||||
Guid? parentId = null, |
|
||||
Guid? tenantId = null, |
|
||||
Dictionary<string, object> meta = null, |
|
||||
string[] roles = null, |
|
||||
Guid[] users = null, |
|
||||
bool isPublic = false |
|
||||
) |
|
||||
{ |
|
||||
var menu = await RouteDataSeeder.SeedMenuAsync( |
|
||||
layout, |
|
||||
name, |
|
||||
path, |
|
||||
code, |
|
||||
component, |
|
||||
displayName, |
|
||||
redirect, |
|
||||
description, |
|
||||
parentId, |
|
||||
tenantId, |
|
||||
isPublic |
|
||||
); |
|
||||
foreach (var item in data.Items) |
|
||||
{ |
|
||||
menu.SetProperty(item.Name, item.DefaultValue); |
|
||||
} |
|
||||
if (meta != null) |
|
||||
{ |
|
||||
foreach (var item in meta) |
|
||||
{ |
|
||||
menu.SetProperty(item.Key, item.Value); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (roles != null) |
|
||||
{ |
|
||||
foreach (var role in roles) |
|
||||
{ |
|
||||
await RouteDataSeeder.SeedRoleMenuAsync(role, menu, tenantId); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
if (users != null) |
|
||||
{ |
|
||||
foreach (var user in users) |
|
||||
{ |
|
||||
await RouteDataSeeder.SeedUserMenuAsync(user, menu, tenantId); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return menu; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
File diff suppressed because it is too large
Loading…
Reference in new issue