From e9851f4b7c54bbe9e2d967cabf6d3e4e3eeafe5b Mon Sep 17 00:00:00 2001
From: cKey <35512826+colinin@users.noreply.github.com>
Date: Wed, 3 Nov 2021 21:49:10 +0800
Subject: [PATCH] added UI navigation custom module.
---
aspnet-core/LINGYUN.MicroService.All.sln | 17 +
aspnet-core/LINGYUN.MicroService.Platform.sln | 17 +
.../LINGYUN.Abp.UI.Navigation.csproj | 13 +
.../Abp/UI/Navigation/AbpNavigationOptions.cs | 14 +
.../UI/Navigation/AbpUINavigationModule.cs | 38 +
.../Abp/UI/Navigation/ApplicationMenu.cs | 113 ++
.../Abp/UI/Navigation/ApplicationMenuList.cs | 45 +
.../Abp/UI/Navigation/IHasMenuItems.cs | 10 +
.../UI/Navigation/INavigationDataSeeder.cs | 19 +
.../INavigationDefinitionContext.cs | 7 +
.../INavigationDefinitionManager.cs | 9 +
.../INavigationDefinitionProvider.cs | 7 +
.../Abp/UI/Navigation/INavigationProvider.cs | 10 +
.../NavigationDataSeedContributor.cs | 38 +
.../Abp/UI/Navigation/NavigationDefinition.cs | 11 +
.../Navigation/NavigationDefinitionContext.cs | 28 +
.../Navigation/NavigationDefinitionManager.cs | 54 +
.../NavigationDefinitionProvider.cs | 12 +
.../Abp/UI/Navigation/NavigationProvider.cs | 30 +
.../UI/Navigation/NullNavigationDataSeeder.cs | 18 +
.../LINGYUN.Abp.UI.Navigation/README.md | 55 +
...GYUN.Abp.UI.Navigation.VueVbenAdmin.csproj | 17 +
.../AbpUINavigationVueVbenAdminDataSeeder.cs | 399 ++++++
.../AbpUINavigationVueVbenAdminModule.cs | 12 +
...ueVbenAdminNavigationDefinitionProvider.cs | 353 ++++++
.../AbpUINavigationVueVbenAdminOptions.cs | 15 +
.../README.md | 21 +
.../AppPlatformHttpApiHostModule.cs | 2 +
.../ElementAdminDataSeedContributor.cs | 962 ---------------
.../VbenAdminDataSeedContributor.cs | 1089 -----------------
.../LINGYUN.Platform.HttpApi.Host.csproj | 1 +
31 files changed, 1385 insertions(+), 2051 deletions(-)
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN.Abp.UI.Navigation.csproj
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpNavigationOptions.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpUINavigationModule.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenu.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenuList.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/IHasMenuItems.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDataSeeder.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionContext.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionManager.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionProvider.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationProvider.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDataSeedContributor.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinition.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionContext.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionManager.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionProvider.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationProvider.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NullNavigationDataSeeder.cs
create mode 100644 aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/README.md
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminDataSeeder.cs
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminModule.cs
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminNavigationDefinitionProvider.cs
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminOptions.cs
create mode 100644 aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/README.md
delete mode 100644 aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/ElementAdminDataSeedContributor.cs
delete mode 100644 aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/DataSeeder/VbenAdminDataSeedContributor.cs
diff --git a/aspnet-core/LINGYUN.MicroService.All.sln b/aspnet-core/LINGYUN.MicroService.All.sln
index bec216761..4837ff981 100644
--- a/aspnet-core/LINGYUN.MicroService.All.sln
+++ b/aspnet-core/LINGYUN.MicroService.All.sln
@@ -353,6 +353,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Serilog.Enriche
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Data.DbMigrator", "modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj", "{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "navigation", "navigation", "{7D02D803-F9A9-492C-9B5E-454E4B258466}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation", "modules\navigation\LINGYUN.Abp.UI.Navigation\LINGYUN.Abp.UI.Navigation.csproj", "{FD04A084-BB8A-4733-B9C5-FACF40342A8A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation.VueVbenAdmin", "modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj", "{67A76560-D39F-4D49-B858-B476E1DFE37B}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -923,6 +929,14 @@ Global
{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {FD04A084-BB8A-4733-B9C5-FACF40342A8A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {67A76560-D39F-4D49-B858-B476E1DFE37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {67A76560-D39F-4D49-B858-B476E1DFE37B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {67A76560-D39F-4D49-B858-B476E1DFE37B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -1097,6 +1111,9 @@ Global
{F71A0D28-397D-4094-B1C2-7925E1310676} = {67DAB2A0-D407-4CAB-8414-AE3D0AC52FC4}
{CEAF0044-28D3-4585-B69D-D65FF6D4745E} = {6FC0578B-CDF1-43AD-9F7E-4AA7E4720A02}
{91D9F43A-BFD9-47CA-A6AD-430D1663EFF3} = {8AC72641-30D3-4ACF-89FA-808FADC55C2E}
+ {7D02D803-F9A9-492C-9B5E-454E4B258466} = {C5CAD011-DF84-4914-939C-0C029DCEF26F}
+ {FD04A084-BB8A-4733-B9C5-FACF40342A8A} = {7D02D803-F9A9-492C-9B5E-454E4B258466}
+ {67A76560-D39F-4D49-B858-B476E1DFE37B} = {F4923692-D343-4318-AECA-96F580B1A563}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {C95FDF91-16F2-4A8B-A4BE-0E62D1B66718}
diff --git a/aspnet-core/LINGYUN.MicroService.Platform.sln b/aspnet-core/LINGYUN.MicroService.Platform.sln
index 4ceb03051..31ed1fd60 100644
--- a/aspnet-core/LINGYUN.MicroService.Platform.sln
+++ b/aspnet-core/LINGYUN.MicroService.Platform.sln
@@ -86,6 +86,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Serilog.Enriche
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.Data.DbMigrator", "modules\common\LINGYUN.Abp.Data.DbMigrator\LINGYUN.Abp.Data.DbMigrator.csproj", "{FA49E154-CD90-4E11-8216-3EF545C32294}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation.VueVbenAdmin", "modules\platform\LINGYUN.Abp.UI.Navigation.VueVbenAdmin\LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj", "{2A69A38F-E98A-490D-BEAE-1BBBD87121DD}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "navigation", "navigation", "{D61721B8-B0F7-4C3D-AD1B-44FBE81DFA79}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LINGYUN.Abp.UI.Navigation", "modules\navigation\LINGYUN.Abp.UI.Navigation\LINGYUN.Abp.UI.Navigation.csproj", "{BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -212,6 +218,14 @@ Global
{FA49E154-CD90-4E11-8216-3EF545C32294}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FA49E154-CD90-4E11-8216-3EF545C32294}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FA49E154-CD90-4E11-8216-3EF545C32294}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2A69A38F-E98A-490D-BEAE-1BBBD87121DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2A69A38F-E98A-490D-BEAE-1BBBD87121DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2A69A38F-E98A-490D-BEAE-1BBBD87121DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2A69A38F-E98A-490D-BEAE-1BBBD87121DD}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -254,6 +268,9 @@ Global
{F90823E2-53DC-4751-BCCD-6C11B3899592} = {20E8BAE5-C13E-4F86-9EB0-EF24F50442B5}
{6C048526-5A14-4835-B8BA-1C0C6E887225} = {D845545B-57C4-43A1-985B-23C372340CD6}
{FA49E154-CD90-4E11-8216-3EF545C32294} = {265D5E44-682B-49BC-984A-BDD8CA45E60E}
+ {2A69A38F-E98A-490D-BEAE-1BBBD87121DD} = {4096EC6A-EEAD-4E5B-B087-393D7A4E5874}
+ {D61721B8-B0F7-4C3D-AD1B-44FBE81DFA79} = {15BDA03E-DE8E-46E4-96A8-CA3F2872E812}
+ {BE9131C0-7DD4-4032-A5F7-4B9D76EC16CF} = {D61721B8-B0F7-4C3D-AD1B-44FBE81DFA79}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {03D3B66F-8926-4C00-B7AB-A21761EC859E}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN.Abp.UI.Navigation.csproj b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN.Abp.UI.Navigation.csproj
new file mode 100644
index 000000000..d259062ac
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN.Abp.UI.Navigation.csproj
@@ -0,0 +1,13 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpNavigationOptions.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpNavigationOptions.cs
new file mode 100644
index 000000000..cac598435
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpNavigationOptions.cs
@@ -0,0 +1,14 @@
+using Volo.Abp.Collections;
+
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public class AbpNavigationOptions
+ {
+ public ITypeList DefinitionProviders { get; }
+
+ public AbpNavigationOptions()
+ {
+ DefinitionProviders = new TypeList();
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpUINavigationModule.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpUINavigationModule.cs
new file mode 100644
index 000000000..1a00ad813
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/AbpUINavigationModule.cs
@@ -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();
+
+ services.OnRegistred(context =>
+ {
+ if (typeof(INavigationDefinitionProvider).IsAssignableFrom(context.ImplementationType))
+ {
+ definitionProviders.Add(context.ImplementationType);
+ }
+ });
+
+ services.Configure(options =>
+ {
+ options.DefinitionProviders.AddIfNotContains(definitionProviders);
+ });
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenu.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenu.cs
new file mode 100644
index 000000000..4d2d5c088
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenu.cs
@@ -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;
+ ///
+ /// 名称
+ ///
+ [NotNull]
+ public string Name { get; }
+ ///
+ /// 显示名称
+ ///
+ [NotNull]
+ public string DisplayName { get; }
+ ///
+ /// 说明
+ ///
+ [CanBeNull]
+ public string Description { get; }
+ ///
+ /// 路径
+ ///
+ [NotNull]
+ public string Url { get; }
+ ///
+ /// 组件
+ ///
+ [CanBeNull]
+ public string Component { get; }
+ ///
+ /// 重定向
+ ///
+ [CanBeNull]
+ public string Redirect { get; }
+ ///
+ /// 图标
+ ///
+ [CanBeNull]
+ public string Icon { get; set; }
+ ///
+ /// 排序
+ ///
+ public int Order { get; set; }
+ ///
+ /// 是否禁用
+ ///
+ public bool IsDisabled { get; set; }
+ ///
+ /// 是否可视
+ ///
+ 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}";
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenuList.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenuList.cs
new file mode 100644
index 000000000..48e22e309
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/ApplicationMenuList.cs
@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public class ApplicationMenuList : List
+ {
+ public ApplicationMenuList()
+ {
+
+ }
+
+ public ApplicationMenuList(int capacity)
+ : base(capacity)
+ {
+
+ }
+
+ public ApplicationMenuList(IEnumerable 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);
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/IHasMenuItems.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/IHasMenuItems.cs
new file mode 100644
index 000000000..62d45878a
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/IHasMenuItems.cs
@@ -0,0 +1,10 @@
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface IHasMenuItems
+ {
+ ///
+ /// Menu items.
+ ///
+ ApplicationMenuList Items { get; }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDataSeeder.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDataSeeder.cs
new file mode 100644
index 000000000..67320c39e
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDataSeeder.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+using Volo.Abp.MultiTenancy;
+
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface INavigationDataSeeder
+ {
+ ///
+ ///
+ ///
+ /// 菜单列表
+ /// 让用户自行决定是否过滤菜单
+ ///
+ Task SeedAsync(
+ IReadOnlyCollection menus,
+ MultiTenancySides multiTenancySides = MultiTenancySides.Both);
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionContext.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionContext.cs
new file mode 100644
index 000000000..493b9fa29
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionContext.cs
@@ -0,0 +1,7 @@
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface INavigationDefinitionContext
+ {
+ void Add(params NavigationDefinition[] definitions);
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionManager.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionManager.cs
new file mode 100644
index 000000000..653321a63
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionManager.cs
@@ -0,0 +1,9 @@
+using System.Collections.Generic;
+
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface INavigationDefinitionManager
+ {
+ IReadOnlyList GetAll();
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionProvider.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionProvider.cs
new file mode 100644
index 000000000..1c101b040
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationDefinitionProvider.cs
@@ -0,0 +1,7 @@
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface INavigationDefinitionProvider
+ {
+ void Define(INavigationDefinitionContext context);
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationProvider.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationProvider.cs
new file mode 100644
index 000000000..6fd3ec37d
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/INavigationProvider.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public interface INavigationProvider
+ {
+ Task> GetAllAsync();
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDataSeedContributor.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDataSeedContributor.cs
new file mode 100644
index 000000000..d0eee9158
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDataSeedContributor.cs
@@ -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);
+ }
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinition.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinition.cs
new file mode 100644
index 000000000..b4456e285
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinition.cs
@@ -0,0 +1,11 @@
+namespace LINGYUN.Abp.UI.Navigation
+{
+ public class NavigationDefinition
+ {
+ public ApplicationMenu Menu { get; }
+ public NavigationDefinition(ApplicationMenu menu)
+ {
+ Menu = menu;
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionContext.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionContext.cs
new file mode 100644
index 000000000..191666961
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionContext.cs
@@ -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 Navigations { get; }
+ public NavigationDefinitionContext(List navigations)
+ {
+ Navigations = navigations;
+ }
+ public virtual IReadOnlyList GetAll()
+ {
+ return Navigations.ToImmutableList();
+ }
+
+ public virtual void Add(params NavigationDefinition[] definitions)
+ {
+ if (definitions.IsNullOrEmpty())
+ {
+ return;
+ }
+ Navigations.AddRange(definitions);
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionManager.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionManager.cs
new file mode 100644
index 000000000..a4d73c1ed
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionManager.cs
@@ -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> NavigationDefinitions { get; }
+
+ protected AbpNavigationOptions Options { get; }
+
+ protected IServiceProvider ServiceProvider { get; }
+
+ public NavigationDefinitionManager(
+ IOptions options,
+ IServiceProvider serviceProvider)
+ {
+ ServiceProvider = serviceProvider;
+ Options = options.Value;
+
+ NavigationDefinitions = new Lazy>(CreateSettingDefinitions, true);
+ }
+
+ public virtual IReadOnlyList GetAll()
+ {
+ return NavigationDefinitions.Value.ToImmutableList();
+ }
+
+ protected virtual IList CreateSettingDefinitions()
+ {
+ var settings = new List();
+
+ 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;
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionProvider.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionProvider.cs
new file mode 100644
index 000000000..d5179da5a
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationDefinitionProvider.cs
@@ -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);
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationProvider.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationProvider.cs
new file mode 100644
index 000000000..2c9d3dbd2
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NavigationProvider.cs
@@ -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> GetAllAsync()
+ {
+ var navigations = new List();
+ var navigationDefineitions = NavigationDefinitionManager.GetAll();
+ foreach (var navigationDefineition in navigationDefineitions)
+ {
+ navigations.Add(navigationDefineition.Menu);
+ }
+
+ IReadOnlyCollection menus = navigations.ToImmutableList();
+
+ return Task.FromResult(menus);
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NullNavigationDataSeeder.cs b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NullNavigationDataSeeder.cs
new file mode 100644
index 000000000..ba7540997
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/LINGYUN/Abp/UI/Navigation/NullNavigationDataSeeder.cs
@@ -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 menus,
+ MultiTenancySides multiTenancySides = MultiTenancySides.Both)
+ {
+ return Task.CompletedTask;
+ }
+ }
+}
diff --git a/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/README.md b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/README.md
new file mode 100644
index 000000000..18c68e1f8
--- /dev/null
+++ b/aspnet-core/modules/navigation/LINGYUN.Abp.UI.Navigation/README.md
@@ -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);
+ }
+}
+
+```
+
+## 其他
diff --git a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj
new file mode 100644
index 000000000..ec74698d6
--- /dev/null
+++ b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN.Abp.UI.Navigation.VueVbenAdmin.csproj
@@ -0,0 +1,17 @@
+
+
+
+ netstandard2.0
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminDataSeeder.cs b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminDataSeeder.cs
new file mode 100644
index 000000000..9c0709620
--- /dev/null
+++ b/aspnet-core/modules/platform/LINGYUN.Abp.UI.Navigation.VueVbenAdmin/LINGYUN/Abp/UI/Navigation/VueVbenAdmin/AbpUINavigationVueVbenAdminDataSeeder.cs
@@ -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 options)
+ {
+ CurrentTenant = currentTenant;
+ GuidGenerator = guidGenerator;
+ RouteDataSeeder = routeDataSeeder;
+ MenuRepository = menuRepository;
+ LayoutRepository = layoutRepository;
+ DataDictionaryDataSeeder = dataDictionaryDataSeeder;
+
+ Options = options.Value;
+ }
+
+ public virtual async Task SeedAsync(
+ IReadOnlyCollection 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 menus,
+ MultiTenancySides multiTenancySides)
+ {
+ foreach (var menu in menus)
+ {
+ if (!menu.MultiTenancySides.HasFlag(multiTenancySides))
+ {
+ continue;
+ }
+
+ var menuMeta = new Dictionary()
+ {
+ { "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()
+ {
+ { "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