Forráskód Böngészése

!1613 合并next-beta分支
Merge pull request !1613 from 喵你个汪/next

zuohuaijun 1 éve
szülő
commit
5c048f0f28
100 módosított fájl, 2913 hozzáadás és 2503 törlés
  1. 0 25
      Admin.NET/Admin.NET.Application/SeedData/SysAppSeedData.cs
  2. 93 0
      Admin.NET/Admin.NET.Core/Common/CommonValidationAttribute.cs
  3. 0 5
      Admin.NET/Admin.NET.Core/Const/ClaimConst.cs
  4. 0 5
      Admin.NET/Admin.NET.Core/Const/CommonConst.cs
  5. 43 53
      Admin.NET/Admin.NET.Core/Const/ConfigConst.cs
  6. 0 10
      Admin.NET/Admin.NET.Core/Const/SqlSugarConst.cs
  7. 0 82
      Admin.NET/Admin.NET.Core/Entity/SysApp.cs
  8. 0 41
      Admin.NET/Admin.NET.Core/Entity/SysAppMenu.cs
  9. 90 23
      Admin.NET/Admin.NET.Core/Entity/SysTenant.cs
  10. 28 0
      Admin.NET/Admin.NET.Core/Entity/SysTenantMenu.cs
  11. 59 0
      Admin.NET/Admin.NET.Core/Entity/SysUserRegWay.cs
  12. 82 28
      Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs
  13. 7 1
      Admin.NET/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs
  14. 3 3
      Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs
  15. 109 0
      Admin.NET/Admin.NET.Core/Extension/EnumerableExtension.cs
  16. 1 1
      Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs
  17. 0 25
      Admin.NET/Admin.NET.Core/SeedData/SysAppSeedData.cs
  18. 0 11
      Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
  19. 50 49
      Admin.NET/Admin.NET.Core/SeedData/SysDictDataSeedData.cs
  20. 7 7
      Admin.NET/Admin.NET.Core/SeedData/SysDictTypeSeedData.cs
  21. 192 189
      Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs
  22. 5 4
      Admin.NET/Admin.NET.Core/SeedData/SysOrgSeedData.cs
  23. 19 179
      Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs
  24. 4 5
      Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs
  25. 6 5
      Admin.NET/Admin.NET.Core/SeedData/SysTenantMenuSeedData.cs
  26. 3 2
      Admin.NET/Admin.NET.Core/SeedData/SysTenantSeedData.cs
  27. 11 2
      Admin.NET/Admin.NET.Core/SeedData/SysUserExtOrgSeedData.cs
  28. 6 5
      Admin.NET/Admin.NET.Core/SeedData/SysUserRoleSeedData.cs
  29. 7 7
      Admin.NET/Admin.NET.Core/SeedData/SysUserSeedData.cs
  30. 0 173
      Admin.NET/Admin.NET.Core/Service/Application/Dto/SysAppInput.cs
  31. 0 103
      Admin.NET/Admin.NET.Core/Service/Application/Dto/SysAppOutput.cs
  32. 0 192
      Admin.NET/Admin.NET.Core/Service/Application/SysAppService.cs
  33. 60 6
      Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginInput.cs
  34. 5 0
      Admin.NET/Admin.NET.Core/Service/Auth/Dto/SysLdapInput.cs
  35. 87 60
      Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs
  36. 4 1
      Admin.NET/Admin.NET.Core/Service/Auth/SysLdapService.cs
  37. 0 8
      Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs
  38. 21 11
      Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs
  39. 31 69
      Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs
  40. 1 1
      Admin.NET/Admin.NET.Core/Service/Dict/Dto/DictDataInput.cs
  41. 1 1
      Admin.NET/Admin.NET.Core/Service/Dict/Dto/DictTypeInput.cs
  42. 4 4
      Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs
  43. 5 5
      Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs
  44. 2 4
      Admin.NET/Admin.NET.Core/Service/Enum/SysEnumService.cs
  45. 5 0
      Admin.NET/Admin.NET.Core/Service/File/Dto/FileInput.cs
  46. 1 0
      Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs
  47. 5 0
      Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs
  48. 4 1
      Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs
  49. 4 1
      Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs
  50. 4 1
      Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs
  51. 4 1
      Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs
  52. 8 8
      Admin.NET/Admin.NET.Core/Service/Menu/Dto/MenuInput.cs
  53. 72 87
      Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs
  54. 5 4
      Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs
  55. 1 1
      Admin.NET/Admin.NET.Core/Service/OAuth/SysOAuthService.cs
  56. 5 0
      Admin.NET/Admin.NET.Core/Service/OnlineUser/Dto/OnlineUserInput.cs
  57. 5 1
      Admin.NET/Admin.NET.Core/Service/OnlineUser/SysOnlineUserService.cs
  58. 5 0
      Admin.NET/Admin.NET.Core/Service/Org/Dto/OrgInput.cs
  59. 11 6
      Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs
  60. 5 0
      Admin.NET/Admin.NET.Core/Service/Plugin/Dto/PluginInput.cs
  61. 5 1
      Admin.NET/Admin.NET.Core/Service/Plugin/SysPluginService.cs
  62. 5 0
      Admin.NET/Admin.NET.Core/Service/Pos/Dto/PosInput.cs
  63. 5 0
      Admin.NET/Admin.NET.Core/Service/Pos/SysPosService.cs
  64. 5 0
      Admin.NET/Admin.NET.Core/Service/Print/Dto/PrintInput.cs
  65. 4 1
      Admin.NET/Admin.NET.Core/Service/Print/SysPrintService.cs
  66. 0 3
      Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs
  67. 5 0
      Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleInput.cs
  68. 1 1
      Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleMenuInput.cs
  69. 5 0
      Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleOutput.cs
  70. 6 4
      Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs
  71. 5 0
      Admin.NET/Admin.NET.Core/Service/Schedule/Dto/ScheduleInput.cs
  72. 1 0
      Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs
  73. 67 7
      Admin.NET/Admin.NET.Core/Service/Tenant/Dto/TenantInput.cs
  74. 2 7
      Admin.NET/Admin.NET.Core/Service/Tenant/Dto/TenantOutput.cs
  75. 256 56
      Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs
  76. 5 0
      Admin.NET/Admin.NET.Core/Service/User/Dto/UserInput.cs
  77. 73 0
      Admin.NET/Admin.NET.Core/Service/User/Dto/UserRegWayInput.cs
  78. 28 0
      Admin.NET/Admin.NET.Core/Service/User/Dto/UserRegWayOutput.cs
  79. 118 0
      Admin.NET/Admin.NET.Core/Service/User/SysUserRegWayService.cs
  80. 39 5
      Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
  81. 6 6
      Admin.NET/Admin.NET.Core/Service/User/UserManager.cs
  82. 5 5
      Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs
  83. 4 4
      Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs
  84. 6 0
      Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewSys/Dto/GoViewLoginInput.cs
  85. 6 2
      Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewSys/GoViewSysService.cs
  86. 1 7
      Web/.env
  87. 7 1
      Web/.env.development
  88. 7 1
      Web/.env.production
  89. 14 12
      Web/src/App.vue
  90. 1 1
      Web/src/api-services/api.ts
  91. 0 720
      Web/src/api-services/apis/sys-app-api.ts
  92. 84 0
      Web/src/api-services/apis/sys-auth-api.ts
  93. 13 21
      Web/src/api-services/apis/sys-menu-api.ts
  94. 15 7
      Web/src/api-services/apis/sys-org-api.ts
  95. 15 7
      Web/src/api-services/apis/sys-pos-api.ts
  96. 364 33
      Web/src/api-services/apis/sys-tenant-api.ts
  97. 391 0
      Web/src/api-services/apis/sys-user-reg-way-api.ts
  98. 6 0
      Web/src/api-services/models/add-menu-input.ts
  99. 87 8
      Web/src/api-services/models/add-tenant-input.ts
  100. 56 67
      Web/src/api-services/models/add-user-reg-way-input.ts

+ 0 - 25
Admin.NET/Admin.NET.Application/SeedData/SysAppSeedData.cs

@@ -1,25 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Application;
-
-/// <summary>
-/// 系统应用表种子数据
-/// </summary>
-public class SysAppSeedData : ISqlSugarEntitySeedData<SysApp>
-{
-    /// <summary>
-    /// 种子数据
-    /// </summary>
-    /// <returns></returns>
-    public IEnumerable<SysApp> HasData()
-    {
-        return new[]
-        {
-            new SysApp{ Id=1310000000001, Name=ApplicationConst.GroupName, Logo="/upload/logo.png", Title="Admin.App", ViceTitle="Admin.App", ViceDesc="站在巨人肩膀上的 .NET 通用权限开发框架", Watermark="Admin.App", Copyright="Copyright \u00a9 2021-present Admin.NET All rights reserved.", Icp="省ICP备12345678号", Remark=ApplicationConst.GroupName, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-        };
-    }
-}

+ 93 - 0
Admin.NET/Admin.NET.Core/Common/CommonValidationAttribute.cs

@@ -0,0 +1,93 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+// 
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+// 
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Common;
+
+/// <summary>
+/// 通用接口参数验证特性类
+/// </summary>
+[AttributeUsage(AttributeTargets.Property)]
+public class CommonValidationAttribute : ValidationAttribute
+{
+    private readonly Dictionary<string, string> _conditions;
+    private static readonly Dictionary<string, Delegate> CompiledConditions = new();
+    
+    /// <summary>
+    /// </summary>
+    /// <param name="conditionPairs">条件对参数,长度必须为偶数<br/>
+    /// 奇数字符串参数:动态条件<br/>
+    /// 偶数字符串参数:提示消息
+    /// </param>
+    /// <example>
+    /// <code lang="C">
+    /// public class ModelInput {
+    ///
+    /// 
+    ///     public string A { get; set; }
+    ///
+    /// 
+    ///     [CommonValidation(
+    ///         "A == 1 <value>&amp;&amp;</value> B == null", "当 A == 1时,B不能为空",
+    ///         "C == 2 <value>&amp;&amp;</value> B == null", "当 C == 2时,B不能为空"
+    ///     )]
+    ///     public string B { get; set; }
+    /// }
+    /// </code>
+    /// </example>
+    public CommonValidationAttribute(params string[] conditionPairs)
+    {
+        if (conditionPairs.Length % 2 != 0) throw new ArgumentException("条件对必须以偶数个字符串的形式提供。");
+
+        var conditions = new Dictionary<string, string>();
+        for (int i = 0; i < conditionPairs.Length; i += 2)
+            conditions.Add(conditionPairs[i], conditionPairs[i + 1]);
+
+        _conditions = conditions;
+    }
+
+    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
+    {
+        
+        foreach (var (expr, errorMessage) in _conditions)
+        {
+            var conditionKey = $"{validationContext.ObjectType.FullName}.{expr}";
+            if (!CompiledConditions.TryGetValue(conditionKey, out var condition))
+            {
+                condition = CreateCondition(validationContext.ObjectType, expr);
+                CompiledConditions[conditionKey] = condition;
+            }
+            
+            if ((bool)condition.DynamicInvoke(validationContext.ObjectInstance)!)
+            {
+                return new ValidationResult(errorMessage ?? $"[{validationContext.MemberName}]校验失败");
+            }
+        }
+
+        return ValidationResult.Success;
+    }
+
+    private Delegate CreateCondition(Type modelType, string expression)
+    {
+        try
+        {
+            // 创建参数表达式
+            var parameter = Expression.Parameter(typeof(object), "x");
+            
+            // 构建 Lambda 表达式
+            var lambda = DynamicExpressionParser.ParseLambda(new[] { Expression.Parameter(modelType, "x") }, typeof(bool), expression);
+
+            // 创建新的 Lambda 表达式,接受 object 参数并调用编译后的表达式
+            var invokeExpression = Expression.Invoke(lambda, Expression.Convert(parameter, modelType));
+            var finalLambda = Expression.Lambda<Func<object, bool>>(invokeExpression, parameter);
+
+            return finalLambda.Compile();
+        }
+        catch (Exception ex)
+        {
+            throw new ArgumentException($"无法解析表达式 '{expression}': {ex.Message}", ex);
+        }
+    }
+}

+ 0 - 5
Admin.NET/Admin.NET.Core/Const/ClaimConst.cs

@@ -11,11 +11,6 @@ namespace Admin.NET.Core;
 /// </summary>
 public class ClaimConst
 {
-    /// <summary>
-    /// 应用Id
-    /// </summary>
-    public const string AppId = "AppId";
-
     /// <summary>
     /// 用户Id
     /// </summary>

+ 0 - 5
Admin.NET/Admin.NET.Core/Const/CommonConst.cs

@@ -12,11 +12,6 @@ namespace Admin.NET.Core;
 [Const("平台配置")]
 public class CommonConst
 {
-    /// <summary>
-    /// 系统管理员角色编码
-    /// </summary>
-    public const string SysAdminRole = "sys_admin";
-
     /// <summary>
     /// 日志分组名称
     /// </summary>

+ 43 - 53
Admin.NET/Admin.NET.Core/Const/ConfigConst.cs

@@ -41,16 +41,6 @@ public class ConfigConst
     /// </summary>
     public const string SysSingleLogin = "sys_single_login";
 
-    /// <summary>
-    /// 登录二次验证
-    /// </summary>
-    public const string SysSecondVer = "sys_second_ver";
-
-    /// <summary>
-    /// 图形验证码
-    /// </summary>
-    public const string SysCaptcha = "sys_captcha";
-
     /// <summary>
     /// Token过期时间
     /// </summary>
@@ -71,10 +61,10 @@ public class ConfigConst
     /// </summary>
     public const string SysDomainLogin = "sys_domain_login";
 
-    /// <summary>
-    /// 租户域名隔离登录验证
-    /// </summary>
-    public const string SysTenantHostLogin = "sys_tenant_host_login";
+    // /// <summary>
+    // /// 租户域名隔离登录验证
+    // /// </summary>
+    // public const string SysTenantHostLogin = "sys_tenant_host_login";
 
     /// <summary>
     /// 数据校验日志
@@ -96,43 +86,43 @@ public class ConfigConst
     /// </summary>
     public const string SysWebConfigGroup = "WebConfig";
 
-    /// <summary>
-    /// 系统图标
-    /// </summary>
-    public const string SysWebLogo = "sys_web_logo";
-
-    /// <summary>
-    /// 系统主标题
-    /// </summary>
-    public const string SysWebTitle = "sys_web_title";
-
-    /// <summary>
-    /// 系统副标题
-    /// </summary>
-    public const string SysWebViceTitle = "sys_web_viceTitle";
-
-    /// <summary>
-    /// 系统描述
-    /// </summary>
-    public const string SysWebViceDesc = "sys_web_viceDesc";
-
-    /// <summary>
-    /// 水印内容
-    /// </summary>
-    public const string SysWebWatermark = "sys_web_watermark";
-
-    /// <summary>
-    /// 版权说明
-    /// </summary>
-    public const string SysWebCopyright = "sys_web_copyright";
-
-    /// <summary>
-    /// ICP备案号
-    /// </summary>
-    public const string SysWebIcp = "sys_web_icp";
-
-    /// <summary>
-    /// ICP地址
-    /// </summary>
-    public const string SysWebIcpUrl = "sys_web_icpUrl";
+    // /// <summary>
+    // /// 系统图标
+    // /// </summary>
+    // public const string SysWebLogo = "sys_web_logo";
+    //
+    // /// <summary>
+    // /// 系统主标题
+    // /// </summary>
+    // public const string SysWebTitle = "sys_web_title";
+    //
+    // /// <summary>
+    // /// 系统副标题
+    // /// </summary>
+    // public const string SysWebViceTitle = "sys_web_viceTitle";
+    //
+    // /// <summary>
+    // /// 系统描述
+    // /// </summary>
+    // public const string SysWebViceDesc = "sys_web_viceDesc";
+    //
+    // /// <summary>
+    // /// 水印内容
+    // /// </summary>
+    // public const string SysWebWatermark = "sys_web_watermark";
+    //
+    // /// <summary>
+    // /// 版权说明
+    // /// </summary>
+    // public const string SysWebCopyright = "sys_web_copyright";
+    //
+    // /// <summary>
+    // /// ICP备案号
+    // /// </summary>
+    // public const string SysWebIcp = "sys_web_icp";
+    //
+    // /// <summary>
+    // /// ICP地址
+    // /// </summary>
+    // public const string SysWebIcpUrl = "sys_web_icpUrl";
 }

+ 0 - 10
Admin.NET/Admin.NET.Core/Const/SqlSugarConst.cs

@@ -26,18 +26,8 @@ public class SqlSugarConst
     /// </summary>
     public const string PrimaryKey = "Id";
 
-    /// <summary>
-    /// 默认租户Id
-    /// </summary>
-    public const long DefaultAppId = 1300000000001;
-
     /// <summary>
     /// 默认租户Id
     /// </summary>
     public const long DefaultTenantId = 1300000000001;
-
-    /// <summary>
-    /// 默认租户域名
-    /// </summary>
-    public const string DefaultTenantHost = "gitee.com";
 }

+ 0 - 82
Admin.NET/Admin.NET.Core/Entity/SysApp.cs

@@ -1,82 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 系统应用表
-/// </summary>
-[SysTable]
-[SugarTable(null, "系统应用表")]
-public partial class SysApp : EntityBase
-{
-    /// <summary>
-    /// 名称
-    /// </summary>
-    [SugarColumn(ColumnDescription = "名称", Length = 32), Required, MaxLength(32)]
-    public virtual string Name { get; set; }
-
-    /// <summary>
-    /// 图标
-    /// </summary>
-    [SugarColumn(ColumnDescription = "图标", Length = 256), Required, MaxLength(256)]
-    public virtual string? Logo { get; set; }
-
-    /// <summary>
-    /// 标题
-    /// </summary>
-    [SugarColumn(ColumnDescription = "标题", Length = 32), MaxLength(32)]
-    public string Title { get; set; }
-
-    /// <summary>
-    /// 副标题
-    /// </summary>
-    [SugarColumn(ColumnDescription = "副标题", Length = 32), MaxLength(32)]
-    public string ViceTitle { get; set; }
-
-    /// <summary>
-    /// 副描述
-    /// </summary>
-    [SugarColumn(ColumnDescription = "副描述", Length = 64), MaxLength(64)]
-    public string? ViceDesc { get; set; }
-
-    /// <summary>
-    /// 水印
-    /// </summary>
-    [SugarColumn(ColumnDescription = "水印", Length = 32), MaxLength(32)]
-    public string? Watermark { get; set; }
-
-    /// <summary>
-    /// 版权信息
-    /// </summary>
-    [SugarColumn(ColumnDescription = "版权信息", Length = 64), MaxLength(64)]
-    public string? Copyright { get; set; }
-
-    /// <summary>
-    /// ICP备案号
-    /// </summary>
-    [SugarColumn(ColumnDescription = "ICP备案号", Length = 32), MaxLength(32)]
-    public string? Icp { get; set; }
-
-    /// <summary>
-    /// 排序
-    /// </summary>
-    [IgnoreUpdateSeedColumn]
-    [SugarColumn(ColumnDescription = "排序")]
-    public int OrderNo { get; set; } = 100;
-
-    /// <summary>
-    /// 备注
-    /// </summary>
-    [SugarColumn(ColumnDescription = "备注", Length = 256), MaxLength(256)]
-    public string? Remark { get; set; }
-
-    /// <summary>
-    /// 应用租户
-    /// </summary>
-    [Navigate(NavigateType.OneToMany, nameof(SysTenant.AppId))]
-    public List<SysTenant> TenantList { get; set; }
-}

+ 0 - 41
Admin.NET/Admin.NET.Core/Entity/SysAppMenu.cs

@@ -1,41 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 系统应用菜单表
-/// </summary>
-[SugarTable(null, "系统应用菜单表")]
-[SysTable]
-public partial class SysAppMenu : EntityBaseId
-{
-    /// <summary>
-    /// 应用Id
-    /// </summary>
-    [SugarColumn(ColumnDescription = "应用Id")]
-    public long AppId { get; set; }
-
-    /// <summary>
-    /// 应用
-    /// </summary>
-    [Newtonsoft.Json.JsonIgnore]
-    [System.Text.Json.Serialization.JsonIgnore]
-    [Navigate(NavigateType.OneToOne, nameof(AppId))]
-    public SysApp SysApp { get; set; }
-
-    /// <summary>
-    /// 菜单Id
-    /// </summary>
-    [SugarColumn(ColumnDescription = "菜单Id")]
-    public long MenuId { get; set; }
-
-    /// <summary>
-    /// 菜单
-    /// </summary>
-    [Navigate(NavigateType.OneToOne, nameof(MenuId))]
-    public SysMenu SysMenu { get; set; }
-}

+ 90 - 23
Admin.NET/Admin.NET.Core/Entity/SysTenant.cs

@@ -4,6 +4,8 @@
 //
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
+using Tea.Utils;
+
 namespace Admin.NET.Core;
 
 /// <summary>
@@ -16,84 +18,149 @@ public partial class SysTenant : EntityBase
     /// <summary>
     /// 应用Id
     /// </summary>
+    [Obsolete("废弃字段, 请勿使用")]
     [SugarColumn(ColumnDescription = "应用Id")]
-    public long AppId { get; set; }
-
+    public virtual long? AppId { get; set; }
+    
     /// <summary>
-    /// 用户Id
+    /// 租管用户Id
     /// </summary>
-    [SugarColumn(ColumnDescription = "用户Id")]
-    public long UserId { get; set; }
+    [SugarColumn(ColumnDescription = "租管用户Id")]
+    public virtual long UserId { get; set; }
 
     /// <summary>
     /// 机构Id
     /// </summary>
     [SugarColumn(ColumnDescription = "机构Id")]
-    public long OrgId { get; set; }
+    public virtual long OrgId { get; set; }
 
     /// <summary>
     /// 域名
     /// </summary>
     [SugarColumn(ColumnDescription = "域名", Length = 128)]
     [MaxLength(128)]
-    public string? Host { get; set; }
+    public virtual string? Host { get; set; }
 
     /// <summary>
     /// 租户类型
     /// </summary>
     [SugarColumn(ColumnDescription = "租户类型")]
-    public TenantTypeEnum TenantType { get; set; }
+    public virtual TenantTypeEnum TenantType { get; set; }
 
     /// <summary>
     /// 数据库类型
     /// </summary>
     [SugarColumn(ColumnDescription = "数据库类型")]
-    public SqlSugar.DbType DbType { get; set; }
+    public virtual SqlSugar.DbType DbType { get; set; }
 
     /// <summary>
     /// 数据库连接
     /// </summary>
     [SugarColumn(ColumnDescription = "数据库连接", Length = 256)]
     [MaxLength(256)]
-    public string? Connection { get; set; }
+    public virtual string? Connection { get; set; }
 
     /// <summary>
     /// 数据库标识
     /// </summary>
     [SugarColumn(ColumnDescription = "数据库标识", Length = 64)]
     [MaxLength(64)]
-    public string? ConfigId { get; set; }
+    public virtual string? ConfigId { get; set; }
 
     /// <summary>
     /// 从库连接/读写分离
     /// </summary>
     [SugarColumn(ColumnDescription = "从库连接/读写分离", ColumnDataType = StaticConfig.CodeFirst_BigString)]
-    public string? SlaveConnections { get; set; }
+    public virtual string? SlaveConnections { get; set; }
+    
+    /// <summary>
+    /// 启用注册功能
+    /// </summary>
+    [SugarColumn(ColumnDescription = "启用注册功能")]
+    public virtual YesNoEnum? EnableReg { get; set; } = YesNoEnum.N;
+    
+    /// <summary>
+    /// 默认注册方案Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "默认注册方案")]
+    public virtual long? RegWayId { get; set; }
+
+    /// <summary>
+    /// 启用验证码
+    /// </summary>
+    [SugarColumn(ColumnDescription = "启用验证码")]
+    public virtual YesNoEnum? Captcha { get; set; } = YesNoEnum.Y;
+
+    /// <summary>
+    /// 启用二次验证
+    /// </summary>
+    [SugarColumn(ColumnDescription = "启用二次验证")]
+    public virtual YesNoEnum? SecondVer { get; set; } = YesNoEnum.N;
+
+    /// <summary>
+    /// 图标
+    /// </summary>
+    [SugarColumn(ColumnDescription = "图标", Length = 256), Required, MaxLength(256)]
+    public virtual string? Logo { get; set; }
+
+    /// <summary>
+    /// 标题
+    /// </summary>
+    [SugarColumn(ColumnDescription = "标题", Length = 32), MaxLength(32)]
+    public virtual string Title { get; set; }
+
+    /// <summary>
+    /// 副标题
+    /// </summary>
+    [SugarColumn(ColumnDescription = "副标题", Length = 32), MaxLength(32)]
+    public virtual string ViceTitle { get; set; }
+
+    /// <summary>
+    /// 副描述
+    /// </summary>
+    [SugarColumn(ColumnDescription = "副描述", Length = 64), MaxLength(64)]
+    public virtual string? ViceDesc { get; set; }
+
+    /// <summary>
+    /// 水印
+    /// </summary>
+    [SugarColumn(ColumnDescription = "水印", Length = 32), MaxLength(32)]
+    public virtual string? Watermark { get; set; }
+
+    /// <summary>
+    /// 版权信息
+    /// </summary>
+    [SugarColumn(ColumnDescription = "版权信息", Length = 64), MaxLength(64)]
+    public virtual string? Copyright { get; set; }
+
+    /// <summary>
+    /// ICP备案号
+    /// </summary>
+    [SugarColumn(ColumnDescription = "ICP备案号", Length = 32), MaxLength(32)]
+    public virtual string? Icp { get; set; }
+    
+    /// <summary>
+    /// ICP地址
+    /// </summary>
+    [SugarColumn(ColumnDescription = "ICP地址", Length = 32), MaxLength(32)]
+    public virtual string? IcpUrl { get; set; }
 
     /// <summary>
     /// 排序
     /// </summary>
     [SugarColumn(ColumnDescription = "排序")]
-    public int OrderNo { get; set; } = 100;
+    public virtual int OrderNo { get; set; } = 100;
 
     /// <summary>
     /// 备注
     /// </summary>
     [SugarColumn(ColumnDescription = "备注", Length = 128)]
     [MaxLength(128)]
-    public string? Remark { get; set; }
+    public virtual string? Remark { get; set; }
 
     /// <summary>
     /// 状态
     /// </summary>
     [SugarColumn(ColumnDescription = "状态")]
-    public StatusEnum Status { get; set; } = StatusEnum.Enable;
-
-    /// <summary>
-    /// 应用
-    /// </summary>
-    [Newtonsoft.Json.JsonIgnore]
-    [System.Text.Json.Serialization.JsonIgnore]
-    [Navigate(NavigateType.OneToOne, nameof(AppId))]
-    public SysApp SysApp { get; set; }
+    public virtual StatusEnum Status { get; set; } = StatusEnum.Enable;
 }

+ 28 - 0
Admin.NET/Admin.NET.Core/Entity/SysTenantMenu.cs

@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 系统租户菜单表
+/// </summary>
+[SysTable]
+[SugarTable(null, "系统租户菜单表")]
+[SugarIndex("index_{table}_TM", nameof(TenantId), OrderByType.Asc, nameof(MenuId), OrderByType.Asc, IsUnique=true)]
+public class SysTenantMenu : EntityBaseId
+{
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "租户Id")]
+    public long TenantId { get; set; }
+
+    /// <summary>
+    /// 菜单Id
+    /// </summary>
+    [SugarColumn(ColumnDescription = "菜单Id")]
+    public long MenuId { get; set; }
+}

+ 59 - 0
Admin.NET/Admin.NET.Core/Entity/SysUserRegWay.cs

@@ -0,0 +1,59 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 系统用户注册方案表
+/// </summary>
+[SugarTable(null, "系统用户注册方案表")]
+[SysTable]
+public partial class SysUserRegWay : EntityTenant
+{
+    /// <summary>
+    /// 方案名称
+    /// </summary>
+    [MaxLength(32)]
+    [SugarColumn(ColumnDescription = "方案名称", Length = 32)]
+    public virtual string Name { get; set; }
+    
+    /// <summary>
+    /// 账号类型
+    /// </summary>
+    [SugarColumn(ColumnDescription = "账号类型")]
+    public virtual AccountTypeEnum AccountType { get; set; } = AccountTypeEnum.NormalUser;
+    
+    /// <summary>
+    /// 注册用户默认角色
+    /// </summary>
+    [SugarColumn(ColumnDescription = "角色")]
+    public virtual long RoleId { get; set; }
+    
+    /// <summary>
+    /// 注册用户默认机构
+    /// </summary>
+    [SugarColumn(ColumnDescription = "机构")]
+    public virtual long OrgId { get; set; }
+    
+    /// <summary>
+    /// 注册用户默认职位
+    /// </summary>
+    [SugarColumn(ColumnDescription = "职位")]
+    public virtual long PosId { get; set; }
+    
+    /// <summary>
+    /// 排序
+    /// </summary>
+    [SugarColumn(ColumnDescription = "排序")]
+    public int OrderNo { get; set; } = 100;
+
+    /// <summary>
+    /// 备注
+    /// </summary>
+    [MaxLength(128)]
+    [SugarColumn(ColumnDescription = "备注", Length = 128)]
+    public string? Remark { get; set; }
+}

+ 82 - 28
Admin.NET/Admin.NET.Core/Enum/ErrorCodeEnum.cs

@@ -140,35 +140,11 @@ public enum ErrorCodeEnum
     D1017,
 
     /// <summary>
-    /// 禁止删除管理员
+    /// 该租户下角色菜单权限集为空
     /// </summary>
-    [ErrorCodeItemMetadata("禁止删除管理员")]
-    D1018,
-
-    /// <summary>
-    /// 禁止删除系统管理员角色
-    /// </summary>
-    [ErrorCodeItemMetadata("禁止删除系统管理员角色")]
+    [ErrorCodeItemMetadata("该租户下角色菜单权限集为空")]
     D1019,
 
-    /// <summary>
-    /// 禁止修改系统管理员角色
-    /// </summary>
-    [ErrorCodeItemMetadata("禁止修改系统管理员角色")]
-    D1020,
-
-    /// <summary>
-    /// 禁止为系统管理员角色分配权限
-    /// </summary>
-    [ErrorCodeItemMetadata("禁止为系统管理员角色分配权限")]
-    D1021,
-
-    /// <summary>
-    /// 禁止为超级管理员分配角色
-    /// </summary>
-    [ErrorCodeItemMetadata("禁止为超级管理员分配角色")]
-    D1022,
-
     /// <summary>
     /// 禁止删除默认租户
     /// </summary>
@@ -228,7 +204,37 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("手机号已存在")]
     D1032,
-
+    
+    /// <summary>
+    /// 此角色下存在注册方案禁止删除
+    /// </summary>
+    [ErrorCodeItemMetadata("此角色下存在注册方案禁止删除")]
+    D1033,
+    
+    /// <summary>
+    /// 注册功能未开启禁止注册
+    /// </summary>
+    [ErrorCodeItemMetadata("注册功能未开启禁止注册")]
+    D1034,
+    
+    /// <summary>
+    /// 注册方案不存在
+    /// </summary>
+    [ErrorCodeItemMetadata("注册方案不存在")]
+    D1035,
+    
+    /// <summary>
+    /// 角色不存在
+    /// </summary>
+    [ErrorCodeItemMetadata("角色不存在")]
+    D1036,
+    
+    /// <summary>
+    /// 禁止注册超级管理员和系统管理员
+    /// </summary>
+    [ErrorCodeItemMetadata("禁止注册超级管理员和系统管理员")]
+    D1037,
+    
     /// <summary>
     /// 父机构不存在
     /// </summary>
@@ -288,6 +294,18 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("禁止增加根节点机构")]
     D2009,
+    
+    /// <summary>
+    /// 此机构下存在注册方案禁止删除
+    /// </summary>
+    [ErrorCodeItemMetadata("此机构下存在注册方案禁止删除")]
+    D2010,
+    
+    /// <summary>
+    /// 机构不存在
+    /// </summary>
+    [ErrorCodeItemMetadata("机构不存在")]
+    D2011,
 
     /// <summary>
     /// 字典类型不存在
@@ -402,6 +420,24 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("父节点不能为按钮类型")]
     D4010,
+    
+    /// <summary>
+    /// 租户不能为空
+    /// </summary>
+    [ErrorCodeItemMetadata("租户不能为空")]
+    D4011,
+
+    /// <summary>
+    /// 系统菜单禁止修改
+    /// </summary>
+    [ErrorCodeItemMetadata("系统菜单禁止修改")]
+    D4012,
+
+    /// <summary>
+    /// 系统菜单禁止删除
+    /// </summary>
+    [ErrorCodeItemMetadata("系统菜单禁止删除")]
+    D4013,
 
     /// <summary>
     /// 已存在同名或同编码应用
@@ -450,6 +486,12 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("职位不存在")]
     D6003,
+    
+    /// <summary>
+    /// 此职位下存在注册方案禁止删除
+    /// </summary>
+    [ErrorCodeItemMetadata("此职位下存在注册方案禁止删除")]
+    D6004,
 
     /// <summary>
     /// 通知公告状态错误
@@ -558,6 +600,12 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("已存在同名的租户域名")]
     D1303,
+    
+    /// <summary>
+    /// 授权菜单存在重复项
+    /// </summary>
+    [ErrorCodeItemMetadata("授权菜单存在重复项")]
+    D1304,
 
     /// <summary>
     /// 该表代码模板已经生成过
@@ -654,6 +702,12 @@ public enum ErrorCodeEnum
     /// </summary>
     [ErrorCodeItemMetadata("已存在同名功能或同名程序及插件")]
     D1900,
+    
+    /// <summary>
+    /// 注册方案名称已存在
+    /// </summary>
+    [ErrorCodeItemMetadata("注册方案名称已存在")]
+    D2101,
 
     /// <summary>
     /// 禁止删除存在关联租户的应用
@@ -779,5 +833,5 @@ public enum ErrorCodeEnum
     /// 身份标识已存在
     /// </summary>
     [ErrorCodeItemMetadata("身份标识已存在")]
-    O1000,
+    O1000
 }

+ 7 - 1
Admin.NET/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs

@@ -59,5 +59,11 @@ public enum SysUserEventTypeEnum
     /// 解除登录锁定
     /// </summary>
     [Description("解除登录锁定")]
-    UnlockLogin = 888
+    UnlockLogin = 888,
+    
+    /// <summary>
+    /// 注册用户
+    /// </summary>
+    [Description("注册用户")]
+    Register = 999,
 }

+ 3 - 3
Admin.NET/Admin.NET.Core/EventBus/AppEventSubscriber.cs

@@ -41,9 +41,9 @@ public class AppEventSubscriber : IEventSubscriber, ISingleton, IDisposable
         //var mailTempPath = Path.Combine(App.WebHostEnvironment.WebRootPath, "Temp\\ErrorMail.tp");
         //var mailTemp = File.ReadAllText(mailTempPath);
         //var mail = await _serviceScope.ServiceProvider.GetRequiredService<IViewEngine>().RunCompileFromCachedAsync(mailTemp, );
-
-        var webTitle = await _serviceScope.ServiceProvider.GetRequiredService<SysConfigService>().GetConfigValue<string>(ConfigConst.SysWebTitle);
-        var title = $"{webTitle} 系统异常";
+        var tenantId = App.GetService<UserManager>()?.TenantId ?? SqlSugarConst.DefaultTenantId;
+        var tenant = await App.GetService<ISqlSugarClient>().Queryable<SysTenant>().FirstAsync(t => t.Id == tenantId);
+        var title = $"{tenant?.Title} 系统异常";
         await _serviceScope.ServiceProvider.GetRequiredService<SysEmailService>().SendEmail(JSON.Serialize(context.Source.Payload), title);
     }
 

+ 109 - 0
Admin.NET/Admin.NET.Core/Extension/EnumerableExtension.cs

@@ -0,0 +1,109 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+// 
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+// 
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core;
+
+/// <summary>
+/// 数据集合拓展类
+/// </summary>
+public static class EnumerableExtension 
+{
+    private static readonly ConcurrentDictionary<string, PropertyInfo> PropertyCache = new();
+    
+    /// <summary>
+    /// 查询有父子关系的数据集
+    /// </summary>
+    /// <param name="list">数据集</param>
+    /// <param name="idExpression">主键ID字段</param>
+    /// <param name="parentIdExpression">父级字段</param>
+    /// <param name="topParentIdValue">顶级节点父级字段值</param>
+    /// <param name="isContainOneself">是否包含顶级节点本身</param>
+    /// <returns></returns>
+    public static IEnumerable<T> ToChildList<T, P>(this IEnumerable<T> list,
+        Expression<Func<T, P>> idExpression,
+        Expression<Func<T, P>> parentIdExpression,
+        object topParentIdValue,
+        bool isContainOneself = true)
+    {
+        if (list == null || !list.Any()) return Enumerable.Empty<T>();
+
+        var propId = GetPropertyInfo(idExpression);
+        var propParentId = GetPropertyInfo(parentIdExpression);
+
+        // 查找所有顶级节点
+        var topNodes = list.Where(item => Equals(propId.GetValue(item), topParentIdValue)).ToList();
+
+        return TraverseHierarchy(list, propId, propParentId, topNodes, isContainOneself);
+    }
+
+    /// <summary>
+    /// 查询有父子关系的数据集
+    /// </summary>
+    /// <param name="list">数据集</param>
+    /// <param name="idExpression">主键ID字段</param>
+    /// <param name="parentIdExpression">父级字段</param>
+    /// <param name="topLevelPredicate">顶级节点的选择条件</param>
+    /// <param name="isContainOneself">是否包含顶级节点本身</param>
+    /// <returns></returns>
+    public static IEnumerable<T> ToChildList<T, P>(this IEnumerable<T> list,
+        Expression<Func<T, P>> idExpression,
+        Expression<Func<T, P>> parentIdExpression,
+        Expression<Func<T, bool>> topLevelPredicate,
+        bool isContainOneself = true)
+    {
+        if (list == null || !list.Any()) return Enumerable.Empty<T>();
+
+        // 获取顶级节点
+        var topNodes = list.Where(topLevelPredicate.Compile()).ToList();
+
+        if (!topNodes.Any()) return Enumerable.Empty<T>();
+
+        var idPropertyInfo = GetPropertyInfo(idExpression);
+        var parentPropertyInfo = GetPropertyInfo(parentIdExpression);
+
+        return TraverseHierarchy(list, idPropertyInfo, parentPropertyInfo, topNodes, isContainOneself);
+    }
+
+    /// <summary>
+    /// 辅助方法,从表达式中提取属性信息并使用临时缓存
+    /// </summary>
+    private static PropertyInfo GetPropertyInfo<T, P>(Expression<Func<T, P>> expression)
+    {
+        // 使用 ConcurrentDictionary 确保线程安全
+        return PropertyCache.GetOrAdd(typeof(T).FullName + "." + ((MemberExpression)expression.Body).Member.Name, k =>
+        {
+            if (expression.Body is UnaryExpression { Operand: MemberExpression member }) return (PropertyInfo)member.Member;
+            if (expression.Body is MemberExpression memberExpression) return (PropertyInfo)memberExpression.Member;
+            throw Oops.Oh("表达式必须是一个属性访问: " + expression);
+        });
+    }
+
+    /// <summary>
+    /// 使用队列遍历层级结构
+    /// </summary>
+    private static IEnumerable<T> TraverseHierarchy<T>(IEnumerable<T> list,
+        PropertyInfo idPropertyInfo,
+        PropertyInfo parentPropertyInfo,
+        List<T> topNodes,
+        bool isContainOneself)
+    {
+        var queue = new Queue<T>(topNodes);
+        var result = new HashSet<T>(topNodes);
+
+        while (queue.Count > 0)
+        {
+            var currentNode = queue.Dequeue();
+            var children = list.Where(item => Equals(parentPropertyInfo.GetValue(item), idPropertyInfo.GetValue(currentNode))).ToList();
+            children.Where(child => result.Add(child)).ForEach(child => queue.Enqueue(child));
+        }
+        if (isContainOneself) return result;
+
+        // 如果不需要包含顶级节点本身,则移除它们
+        topNodes.ForEach(e => result.Remove(e));
+        
+        return result;
+    }
+}

+ 1 - 1
Admin.NET/Admin.NET.Core/Job/EnumToDictJob.cs

@@ -37,7 +37,7 @@ public class EnumToDictJob : IJob
         // 校验枚举类命名规范,字典相关功能中需要通过后缀判断是否为枚举类型
         Console.ForegroundColor = ConsoleColor.Red;
         foreach (var dictType in sysDictTypeList.Where(x => !x.Code.EndsWith("Enum")))
-            Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典的枚举类名称必须以Enum结尾: {dictType.Code} ({dictType.Name}-{dictType.Remark})");
+            Console.WriteLine($"【{DateTime.Now}】系统枚举转换字典的枚举类名称必须以Enum结尾: {dictType.Code} ({dictType.Name})");
         sysDictTypeList = sysDictTypeList.Where(x => x.Code.EndsWith("Enum")).ToList();
 
         await SyncEnumToDictInfoAsync(db, sysDictTypeList);

+ 0 - 25
Admin.NET/Admin.NET.Core/SeedData/SysAppSeedData.cs

@@ -1,25 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core;
-
-/// <summary>
-/// 系统应用表种子数据
-/// </summary>
-public class SysAppSeedData : ISqlSugarEntitySeedData<SysApp>
-{
-    /// <summary>
-    /// 种子数据
-    /// </summary>
-    /// <returns></returns>
-    public IEnumerable<SysApp> HasData()
-    {
-        return new[]
-        {
-            new SysApp{ Id=SqlSugarConst.DefaultAppId, Name="默认应用", Logo="/upload/logo.png", Title="Admin.NET", ViceTitle="Admin.NET", ViceDesc="站在巨人肩膀上的 .NET 通用权限开发框架", Watermark="Admin.NET", Copyright="Copyright \u00a9 2021-present Admin.NET All rights reserved.", Icp="省ICP备12345678号", Remark="系统默认应用", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-        };
-    }
-}

+ 0 - 11
Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs

@@ -25,23 +25,12 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
             new SysConfig{ Id=1300000000131, Name="日志保留天数", Code=ConfigConst.SysLogRetentionDays, Value="180", SysFlag=YesNoEnum.Y, Remark="日志保留天数(天)", OrderNo=40, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000141, Name="记录操作日志", Code=ConfigConst.SysOpLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否记录操作日志", OrderNo=50, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000151, Name="单设备登录", Code=ConfigConst.SysSingleLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启单设备登录", OrderNo=60, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=1300000000161, Name="登录二次验证", Code=ConfigConst.SysSecondVer, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启登录二次验证", OrderNo=70, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=1300000000171, Name="图形验证码", Code=ConfigConst.SysCaptcha, Value="True", SysFlag=YesNoEnum.Y, Remark="是否开启图形验证码", OrderNo=80, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000181, Name="Token过期时间", Code=ConfigConst.SysTokenExpire, Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间(分钟)", OrderNo=90, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000191, Name="RefreshToken过期时间", Code=ConfigConst.SysRefreshTokenExpire, Value="20160", SysFlag=YesNoEnum.Y, Remark="刷新Token过期时间(分钟)(一般 refresh_token 的有效时间 > 2 * access_token 的有效时间)", OrderNo=100, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000201, Name="发送异常日志邮件", Code=ConfigConst.SysErrorMail, Value="False", SysFlag=YesNoEnum.Y, Remark="是否发送异常日志邮件", OrderNo=110, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000211, Name="域登录验证", Code=ConfigConst.SysDomainLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="是否开启域登录验证", OrderNo=120, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=1300000000212, Name="租户隔离登录验证", Code=ConfigConst.SysTenantHostLogin, Value="False", SysFlag=YesNoEnum.Y, Remark="租户隔离登录验证", OrderNo=370, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000221, Name="数据校验日志", Code=ConfigConst.SysValidationLog, Value="True", SysFlag=YesNoEnum.Y, Remark="是否数据校验日志", OrderNo=130, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=1300000000231, Name="行政区域同步层级", Code=ConfigConst.SysRegionSyncLevel, Value="3", SysFlag=YesNoEnum.Y, Remark="行政区域同步层级 1-省级,2-市级,3-区县级,4-街道级,5-村级", OrderNo=140, GroupCode=ConfigConst.SysDefaultGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000301, Name="系统主标题", Code=ConfigConst.SysWebTitle, Value="Admin.NET", SysFlag=YesNoEnum.Y, Remark="系统主标题", OrderNo=300, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000311, Name="系统副标题", Code=ConfigConst.SysWebViceTitle, Value="Admin.NET", SysFlag=YesNoEnum.Y, Remark="系统副标题", OrderNo=310, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000321, Name="系统描述", Code=ConfigConst.SysWebViceDesc, Value="站在巨人肩膀上的 .NET 通用权限开发框架", SysFlag=YesNoEnum.Y, Remark="系统描述", OrderNo=320, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000331, Name="水印内容", Code=ConfigConst.SysWebWatermark, Value="Admin.NET", SysFlag=YesNoEnum.Y, Remark="水印内容", OrderNo=330, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000341, Name="版权说明", Code=ConfigConst.SysWebCopyright, Value="Copyright © 2021-present Admin.NET All rights reserved.", SysFlag=YesNoEnum.Y, Remark="版权说明", OrderNo=340, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000351, Name="系统图标", Code=ConfigConst.SysWebLogo, Value="/upload/logo.png", SysFlag=YesNoEnum.Y, Remark="系统图标", OrderNo=350, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            // new SysConfig{ Id=1300000000361, Name="ICP备案号", Code=ConfigConst.SysWebIcp, Value="省ICP备12345678号", SysFlag=YesNoEnum.Y, Remark="ICP备案号", OrderNo=360, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=1300000000371, Name="ICP地址", Code=ConfigConst.SysWebIcpUrl, Value="https://beian.miit.gov.cn", SysFlag=YesNoEnum.Y, Remark="ICP地址", OrderNo=370, GroupCode=ConfigConst.SysWebConfigGroup, CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 50 - 49
Admin.NET/Admin.NET.Core/SeedData/SysDictDataSeedData.cs

@@ -17,63 +17,64 @@ public class SysDictDataSeedData : ISqlSugarEntitySeedData<SysDictData>
     /// <returns></returns>
     public IEnumerable<SysDictData> HasData()
     {
+        var typeList = new SysDictTypeSeedData().HasData().ToList();
         return new[]
         {
-            new SysDictData{ Id=1300000000101, DictTypeId=1300000000101, Label="输入框", Value="Input", OrderNo=100, Remark="输入框", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000102, DictTypeId=1300000000101, Label="字典选择器", Value="DictSelector", OrderNo=100, Remark="字典选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000103, DictTypeId=1300000000101, Label="常量选择器", Value="ConstSelector", OrderNo=100, Remark="常量选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000104, DictTypeId=1300000000101, Label="枚举选择器", Value="EnumSelector", OrderNo=100, Remark="枚举选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000105, DictTypeId=1300000000101, Label="树选择器", Value="ApiTreeSelector", OrderNo=100, Remark="树选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000106, DictTypeId=1300000000101, Label="外键", Value="ForeignKey", OrderNo=100, Remark="外键", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000107, DictTypeId=1300000000101, Label="数字输入框", Value="InputNumber", OrderNo=100, Remark="数字输入框", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000108, DictTypeId=1300000000101, Label="时间选择", Value="DatePicker", OrderNo=100, Remark="时间选择", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000109, DictTypeId=1300000000101, Label="文本域", Value="InputTextArea", OrderNo=100, Remark="文本域", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000110, DictTypeId=1300000000101, Label="上传", Value="Upload", OrderNo=100, Remark="上传", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000111, DictTypeId=1300000000101, Label="开关", Value="Switch", OrderNo=100, Remark="开关", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000101, DictTypeId=typeList[0].Id, Label="输入框", Value="Input", OrderNo=100, Remark="输入框", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000102, DictTypeId=typeList[0].Id, Label="字典选择器", Value="DictSelector", OrderNo=100, Remark="字典选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000103, DictTypeId=typeList[0].Id, Label="常量选择器", Value="ConstSelector", OrderNo=100, Remark="常量选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000104, DictTypeId=typeList[0].Id, Label="枚举选择器", Value="EnumSelector", OrderNo=100, Remark="枚举选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000105, DictTypeId=typeList[0].Id, Label="树选择器", Value="ApiTreeSelector", OrderNo=100, Remark="树选择器", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000106, DictTypeId=typeList[0].Id, Label="外键", Value="ForeignKey", OrderNo=100, Remark="外键", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000107, DictTypeId=typeList[0].Id, Label="数字输入框", Value="InputNumber", OrderNo=100, Remark="数字输入框", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000108, DictTypeId=typeList[0].Id, Label="时间选择", Value="DatePicker", OrderNo=100, Remark="时间选择", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000109, DictTypeId=typeList[0].Id, Label="文本域", Value="InputTextArea", OrderNo=100, Remark="文本域", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000110, DictTypeId=typeList[0].Id, Label="上传", Value="Upload", OrderNo=100, Remark="上传", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000111, DictTypeId=typeList[0].Id, Label="开关", Value="Switch", OrderNo=100, Remark="开关", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000201, DictTypeId=1300000000102, Label="等于", Value="==", OrderNo=1, Remark="等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000202, DictTypeId=1300000000102, Label="模糊", Value="like", OrderNo=1, Remark="模糊", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000203, DictTypeId=1300000000102, Label="大于", Value=">", OrderNo=1, Remark="大于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000204, DictTypeId=1300000000102, Label="小于", Value="<", OrderNo=1, Remark="小于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000205, DictTypeId=1300000000102, Label="不等于", Value="!=", OrderNo=1, Remark="不等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000206, DictTypeId=1300000000102, Label="大于等于", Value=">=", OrderNo=1, Remark="大于等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000207, DictTypeId=1300000000102, Label="小于等于", Value="<=", OrderNo=1, Remark="小于等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000208, DictTypeId=1300000000102, Label="不为空", Value="isNotNull", OrderNo=1, Remark="不为空", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000209, DictTypeId=1300000000102, Label="时间范围", Value="~", OrderNo=1, Remark="时间范围", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000201, DictTypeId=typeList[1].Id, Label="等于", Value="==", OrderNo=1, Remark="等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000202, DictTypeId=typeList[1].Id, Label="模糊", Value="like", OrderNo=1, Remark="模糊", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000203, DictTypeId=typeList[1].Id, Label="大于", Value=">", OrderNo=1, Remark="大于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000204, DictTypeId=typeList[1].Id, Label="小于", Value="<", OrderNo=1, Remark="小于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000205, DictTypeId=typeList[1].Id, Label="不等于", Value="!=", OrderNo=1, Remark="不等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000206, DictTypeId=typeList[1].Id, Label="大于等于", Value=">=", OrderNo=1, Remark="大于等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000207, DictTypeId=typeList[1].Id, Label="小于等于", Value="<=", OrderNo=1, Remark="小于等于", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000208, DictTypeId=typeList[1].Id, Label="不为空", Value="isNotNull", OrderNo=1, Remark="不为空", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000209, DictTypeId=typeList[1].Id, Label="时间范围", Value="~", OrderNo=1, Remark="时间范围", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000301, DictTypeId=1300000000103, Label="long", Value="long", OrderNo=1, Remark="long", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000302, DictTypeId=1300000000103, Label="string", Value="string", OrderNo=1, Remark="string", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000303, DictTypeId=1300000000103, Label="DateTime", Value="DateTime", OrderNo=1, Remark="DateTime", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000304, DictTypeId=1300000000103, Label="bool", Value="bool", OrderNo=1, Remark="bool", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000305, DictTypeId=1300000000103, Label="int", Value="int", OrderNo=1, Remark="int", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000306, DictTypeId=1300000000103, Label="double", Value="double", OrderNo=1, Remark="double", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000307, DictTypeId=1300000000103, Label="float", Value="float", OrderNo=1, Remark="float", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000308, DictTypeId=1300000000103, Label="decimal", Value="decimal", OrderNo=1, Remark="decimal", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000309, DictTypeId=1300000000103, Label="Guid", Value="Guid", OrderNo=1, Remark="Guid", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000310, DictTypeId=1300000000103, Label="DateTimeOffset", Value="DateTimeOffset", OrderNo=1, Remark="DateTimeOffset", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000301, DictTypeId=typeList[2].Id, Label="long", Value="long", OrderNo=1, Remark="long", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000302, DictTypeId=typeList[2].Id, Label="string", Value="string", OrderNo=1, Remark="string", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000303, DictTypeId=typeList[2].Id, Label="DateTime", Value="DateTime", OrderNo=1, Remark="DateTime", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000304, DictTypeId=typeList[2].Id, Label="bool", Value="bool", OrderNo=1, Remark="bool", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000305, DictTypeId=typeList[2].Id, Label="int", Value="int", OrderNo=1, Remark="int", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000306, DictTypeId=typeList[2].Id, Label="double", Value="double", OrderNo=1, Remark="double", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000307, DictTypeId=typeList[2].Id, Label="float", Value="float", OrderNo=1, Remark="float", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000308, DictTypeId=typeList[2].Id, Label="decimal", Value="decimal", OrderNo=1, Remark="decimal", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000309, DictTypeId=typeList[2].Id, Label="Guid", Value="Guid", OrderNo=1, Remark="Guid", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000310, DictTypeId=typeList[2].Id, Label="DateTimeOffset", Value="DateTimeOffset", OrderNo=1, Remark="DateTimeOffset", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000401, DictTypeId=1300000000104, Label="下载压缩包", Value="100", OrderNo=1, Remark="下载压缩包", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000402, DictTypeId=1300000000104, Label="下载压缩包(前端)", Value="111", OrderNo=2, Remark="下载压缩包(前端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000403, DictTypeId=1300000000104, Label="下载压缩包(后端)", Value="121", OrderNo=3, Remark="下载压缩包(后端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000404, DictTypeId=1300000000104, Label="生成到本项目", Value="200", OrderNo=4, Remark="生成到本项目", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000405, DictTypeId=1300000000104, Label="生成到本项目(前端)", Value="211", OrderNo=5, Remark="生成到本项目(前端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000406, DictTypeId=1300000000104, Label="生成到本项目(后端)", Value="221", OrderNo=6, Remark="生成到本项目(后端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000401, DictTypeId=typeList[3].Id, Label="下载压缩包", Value="100", OrderNo=1, Remark="下载压缩包", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000402, DictTypeId=typeList[3].Id, Label="下载压缩包(前端)", Value="111", OrderNo=2, Remark="下载压缩包(前端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000403, DictTypeId=typeList[3].Id, Label="下载压缩包(后端)", Value="121", OrderNo=3, Remark="下载压缩包(后端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000404, DictTypeId=typeList[3].Id, Label="生成到本项目", Value="200", OrderNo=4, Remark="生成到本项目", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000405, DictTypeId=typeList[3].Id, Label="生成到本项目(前端)", Value="211", OrderNo=5, Remark="生成到本项目(前端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000406, DictTypeId=typeList[3].Id, Label="生成到本项目(后端)", Value="221", OrderNo=6, Remark="生成到本项目(后端)", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000501, DictTypeId=1300000000105, Label="EntityBaseId【基础实体Id】", Value="EntityBaseId", OrderNo=1, Remark="【基础实体Id】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000502, DictTypeId=1300000000105, Label="EntityBase【基础实体】", Value="EntityBase", OrderNo=1, Remark="【基础实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000503, DictTypeId=1300000000105, Label="EntityTenantId【租户实体Id】", Value="EntityTenantId", OrderNo=1, Remark="【租户实体Id】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000504, DictTypeId=1300000000105, Label="EntityTenant【租户实体】", Value="EntityTenant", OrderNo=1, Remark="【租户实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000505, DictTypeId=1300000000105, Label="EntityBaseData【业务实体】", Value="EntityBaseData", OrderNo=1, Remark="【业务实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000506, DictTypeId=1300000000105, Label="EntityTenantBaseData【租户业务实体】", Value="EntityTenantBaseData", OrderNo=1, Remark="【租户业务实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000501, DictTypeId=typeList[4].Id, Label="EntityBaseId【基础实体Id】", Value="EntityBaseId", OrderNo=1, Remark="【基础实体Id】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000502, DictTypeId=typeList[4].Id, Label="EntityBase【基础实体】", Value="EntityBase", OrderNo=1, Remark="【基础实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000503, DictTypeId=typeList[4].Id, Label="EntityTenantId【租户实体Id】", Value="EntityTenantId", OrderNo=1, Remark="【租户实体Id】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000504, DictTypeId=typeList[4].Id, Label="EntityTenant【租户实体】", Value="EntityTenant", OrderNo=1, Remark="【租户实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000505, DictTypeId=typeList[4].Id, Label="EntityBaseData【业务实体】", Value="EntityBaseData", OrderNo=1, Remark="【业务实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000506, DictTypeId=typeList[4].Id, Label="EntityTenantBaseData【租户业务实体】", Value="EntityTenantBaseData", OrderNo=1, Remark="【租户业务实体】", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000601, DictTypeId=1300000000106, Label="不需要", Value="off", OrderNo=100, Remark="不需要打印支持", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000602, DictTypeId=1300000000106, Label="绑定打印模版", Value="custom", OrderNo=101, Remark="绑定打印模版", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000601, DictTypeId=typeList[5].Id, Label="不需要", Value="off", OrderNo=100, Remark="不需要打印支持", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000602, DictTypeId=typeList[5].Id, Label="绑定打印模版", Value="custom", OrderNo=101, Remark="绑定打印模版", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
 
-            new SysDictData{ Id=1300000000701, DictTypeId=1300000000201, Label="集团", Value="101", OrderNo=100, Remark="集团", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000702, DictTypeId=1300000000201, Label="公司", Value="201", OrderNo=101, Remark="公司", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000703, DictTypeId=1300000000201, Label="部门", Value="301", OrderNo=102, Remark="部门", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000704, DictTypeId=1300000000201, Label="区域", Value="401", OrderNo=103, Remark="区域", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictData{ Id=1300000000705, DictTypeId=1300000000201, Label="组", Value="501", OrderNo=104, Remark="组", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000701, DictTypeId=typeList[6].Id, Label="集团", Value="101", OrderNo=100, Remark="集团", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000702, DictTypeId=typeList[6].Id, Label="公司", Value="201", OrderNo=101, Remark="公司", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000703, DictTypeId=typeList[6].Id, Label="部门", Value="301", OrderNo=102, Remark="部门", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000704, DictTypeId=typeList[6].Id, Label="区域", Value="401", OrderNo=103, Remark="区域", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictData{ Id=1300000000705, DictTypeId=typeList[6].Id, Label="组", Value="501", OrderNo=104, Remark="组", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
         };
     }
 }

+ 7 - 7
Admin.NET/Admin.NET.Core/SeedData/SysDictTypeSeedData.cs

@@ -19,13 +19,13 @@ public class SysDictTypeSeedData : ISqlSugarEntitySeedData<SysDictType>
     {
         return new[]
         {
-            new SysDictType{ Id=1300000000101, Name="代码生成控件类型", Code="code_gen_effect_type", OrderNo=100, Remark="代码生成控件类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000102, Name="代码生成查询类型", Code="code_gen_query_type", OrderNo=101, Remark="代码生成查询类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000103, Name="代码生成.NET类型", Code="code_gen_net_type", OrderNo=102, Remark="代码生成.NET类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000104, Name="代码生成方式", Code="code_gen_create_type", OrderNo=103, Remark="代码生成方式", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000105, Name="代码生成基类", Code="code_gen_base_class", OrderNo=104, Remark="代码生成基类", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000106, Name="代码生成打印类型", Code="code_gen_print_type", OrderNo=105, Remark="代码生成打印类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
-            new SysDictType{ Id=1300000000201, Name="机构类型", Code="org_type", OrderNo=201, Remark="机构类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000111, Name="代码生成控件类型", Code="code_gen_effect_type", OrderNo=100, Remark="代码生成控件类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000121, Name="代码生成查询类型", Code="code_gen_query_type", OrderNo=101, Remark="代码生成查询类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000131, Name="代码生成.NET类型", Code="code_gen_net_type", OrderNo=102, Remark="代码生成.NET类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000141, Name="代码生成方式", Code="code_gen_create_type", OrderNo=103, Remark="代码生成方式", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000151, Name="代码生成基类", Code="code_gen_base_class", OrderNo=104, Remark="代码生成基类", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2022-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000161, Name="代码生成打印类型", Code="code_gen_print_type", OrderNo=105, Remark="代码生成打印类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-12-04 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
+            new SysDictType{ Id=1300000000171, Name="机构类型", Code="org_type", OrderNo=201, Remark="机构类型", Status=StatusEnum.Enable, CreateTime=DateTime.Parse("2023-02-10 00:00:00"),TenantId=SqlSugarConst.DefaultTenantId },
         };
     }
 }

+ 192 - 189
Admin.NET/Admin.NET.Core/SeedData/SysMenuSeedData.cs

@@ -19,197 +19,200 @@ public class SysMenuSeedData : ISqlSugarEntitySeedData<SysMenu>
     {
         return new[]
         {
-            new SysMenu{ Id=1300000000101, Pid=0, Title="工作台", Path="/dashboard", Name="dashboard", Component="Layout", Icon="ele-HomeFilled", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=0 },
-            new SysMenu{ Id=1300000000111, Pid=1300000000101, Title="工作台", Path="/dashboard/home", Name="home", Component="/home/index", IsAffix=true, Icon="ele-HomeFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1300000000121, Pid=1300000000101, Title="站内信", Path="/dashboard/notice", Name="notice", Component="/home/notice/index", Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=101 },
+            new SysMenu{ Id=1300100000101, Pid=0, Title="工作台", Path="/dashboard", Name="dashboard", Component="Layout", Icon="ele-HomeFilled", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=0 },
+            new SysMenu{ Id=1300100010101, Pid=1300100000101, Title="工作台", Path="/dashboard/home", Name="home", Component="/home/index", IsAffix=true, Icon="ele-HomeFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300100010201, Pid=1300100000101, Title="站内信", Path="/dashboard/notice", Name="notice", Component="/home/notice/index", Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=101 },
 
             // 建议此处Id范围之间放置具体业务应用菜单
-
-            new SysMenu{ Id=1310000000101, Pid=0, Title="系统管理", Path="/system", Name="system", Component="Layout", Icon="ele-Setting", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=10000 },
-
-            new SysMenu{ Id=1310000000111, Pid=1310000000101, Title="账号管理", Path="/system/user", Name="sysUser", Component="/system/user/index", Icon="ele-User", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000112, Pid=1310000000111, Title="查询", Permission="sysUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000113, Pid=1310000000111, Title="编辑", Permission="sysUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000114, Pid=1310000000111, Title="增加", Permission="sysUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000115, Pid=1310000000111, Title="删除", Permission="sysUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000116, Pid=1310000000111, Title="详情", Permission="sysUser:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000117, Pid=1310000000111, Title="授权角色", Permission="sysUser:grantRole", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000118, Pid=1310000000111, Title="重置密码", Permission="sysUser:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000119, Pid=1310000000111, Title="设置状态", Permission="sysUser:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000120, Pid=1310000000111, Title="强制下线", Permission="sysOnlineUser:forceOffline", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000121, Pid=1310000000111, Title="解除锁定", Permission="sysUser:unlockLogin", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000131, Pid=1310000000101, Title="角色管理", Path="/system/role", Name="sysRole", Component="/system/role/index", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000132, Pid=1310000000131, Title="查询", Permission="sysRole:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000133, Pid=1310000000131, Title="编辑", Permission="sysRole:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000134, Pid=1310000000131, Title="增加", Permission="sysRole:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000135, Pid=1310000000131, Title="删除", Permission="sysRole:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000136, Pid=1310000000131, Title="授权菜单", Permission="sysRole:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000137, Pid=1310000000131, Title="授权数据", Permission="sysRole:grantDataScope", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000138, Pid=1310000000131, Title="设置状态", Permission="sysRole:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000141, Pid=1310000000101, Title="机构管理", Path="/system/org", Name="sysOrg", Component="/system/org/index", Icon="ele-OfficeBuilding", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000142, Pid=1310000000141, Title="查询", Permission="sysOrg:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000143, Pid=1310000000141, Title="编辑", Permission="sysOrg:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000144, Pid=1310000000141, Title="增加", Permission="sysOrg:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000145, Pid=1310000000141, Title="删除", Permission="sysOrg:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000151, Pid=1310000000101, Title="职位管理", Path="/system/pos", Name="sysPos", Component="/system/pos/index",Icon="ele-Mug", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-            new SysMenu{ Id=1310000000152, Pid=1310000000151, Title="查询", Permission="sysPos:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000153, Pid=1310000000151, Title="编辑", Permission="sysPos:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000154, Pid=1310000000151, Title="增加", Permission="sysPos:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000155, Pid=1310000000151, Title="删除", Permission="sysPos:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000161, Pid=1310000000101, Title="个人中心", Path="/system/userCenter", Name="sysUserCenter", Component="/system/user/component/userCenter",Icon="ele-Medal", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
-            new SysMenu{ Id=1310000000162, Pid=1310000000161, Title="修改密码", Permission="sysUser:changePwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000163, Pid=1310000000161, Title="基本信息", Permission="sysUser:baseInfo", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000164, Pid=1310000000161, Title="电子签名", Permission="sysFile:uploadSignature", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000165, Pid=1310000000161, Title="上传头像", Permission="sysFile:uploadAvatar", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000171, Pid=1310000000101, Title="通知公告", Path="/system/notice", Name="sysNotice", Component="/system/notice/index",Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
-            new SysMenu{ Id=1310000000172, Pid=1310000000171, Title="查询", Permission="sysNotice:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000173, Pid=1310000000171, Title="编辑", Permission="sysNotice:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000174, Pid=1310000000171, Title="增加", Permission="sysNotice:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000175, Pid=1310000000171, Title="删除", Permission="sysNotice:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000176, Pid=1310000000171, Title="发布", Permission="sysNotice:public", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000177, Pid=1310000000171, Title="撤回", Permission="sysNotice:cancel", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000181, Pid=1310000000101, Title="三方账号", Path="/system/weChatUser", Name="sysWechatUser", Component="/system/weChatUser/index",Icon="ele-ChatDotRound", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
-            new SysMenu{ Id=1310000000182, Pid=1310000000181, Title="查询", Permission="sysWechatUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000183, Pid=1310000000181, Title="编辑", Permission="sysWechatUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000184, Pid=1310000000181, Title="增加", Permission="sysWechatUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000185, Pid=1310000000181, Title="删除", Permission="sysWechatUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000191, Pid=1310000000101, Title="AD域配置", Path="/system/ldap", Name="sysLdap", Component="/system/ldap/index",Icon="ele-Place", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=170 },
-            new SysMenu{ Id=1310000000192, Pid=1310000000191, Title="查询", Permission="sysLdap:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000193, Pid=1310000000191, Title="详情", Permission="sysLdap:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000194, Pid=1310000000191, Title="编辑", Permission="sysLdap:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000195, Pid=1310000000191, Title="增加", Permission="sysLdap:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-            new SysMenu{ Id=1310000000196, Pid=1310000000191, Title="删除", Permission="sysLdap:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
-            new SysMenu{ Id=1310000000197, Pid=1310000000191, Title="同步域账户", Permission="sysLdap:syncUser", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
-            new SysMenu{ Id=1310000000198, Pid=1310000000191, Title="同步域组织", Permission="sysLdap:syncOrg", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
-
-            new SysMenu{ Id=1310000000301, Pid=0, Title="平台管理", Path="/platform", Name="platform", Component="Layout", Icon="ele-Menu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=11000 },
-
-            new SysMenu{ Id=1310000001311, Pid=1310000000301, Title="应用管理", Path="/platform/app", Name="sysApp", Component="/system/app/index", Icon="ele-Orange", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=90 },
-            new SysMenu{ Id=1310000001312, Pid=1310000001311, Title="查询", Permission="sysApp:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000001313, Pid=1310000001311, Title="编辑", Permission="sysApp:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000001314, Pid=1310000001311, Title="增加", Permission="sysApp:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000001315, Pid=1310000001311, Title="删除", Permission="sysApp:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000001316, Pid=1310000001311, Title="授权菜单", Permission="sysApp:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000001317, Pid=1310000001311, Title="切换应用", Permission="sysApp:changeApp", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000311, Pid=1310000000301, Title="租户管理", Path="/platform/tenant", Name="sysTenant", Component="/system/tenant/index", Icon="ele-School", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000312, Pid=1310000000311, Title="查询", Permission="sysTenant:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000313, Pid=1310000000311, Title="编辑", Permission="sysTenant:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000314, Pid=1310000000311, Title="增加", Permission="sysTenant:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000315, Pid=1310000000311, Title="删除", Permission="sysTenant:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000316, Pid=1310000000311, Title="授权菜单", Permission="sysTenant:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000317, Pid=1310000000311, Title="重置密码", Permission="sysTenant:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000318, Pid=1310000000311, Title="生成库", Permission="sysTenant:createDb", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000319, Pid=1310000000311, Title="设置状态", Permission="sysTenant:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000321, Pid=1310000000301, Title="菜单管理", Path="/platform/menu", Name="sysMenu", Component="/system/menu/index", Icon="ele-Menu", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000322, Pid=1310000000321, Title="查询", Permission="sysMenu:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000323, Pid=1310000000321, Title="编辑", Permission="sysMenu:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000324, Pid=1310000000321, Title="增加", Permission="sysMenu:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000325, Pid=1310000000321, Title="删除", Permission="sysMenu:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000331, Pid=1310000000301, Title="参数配置", Path="/platform/config", Name="sysConfig", Component="/system/config/index", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000332, Pid=1310000000331, Title="查询", Permission="sysConfig:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000333, Pid=1310000000331, Title="编辑", Permission="sysConfig:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000334, Pid=1310000000331, Title="增加", Permission="sysConfig:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000335, Pid=1310000000331, Title="删除", Permission="sysConfig:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000341, Pid=1310000000301, Title="字典管理", Path="/platform/dict", Name="sysDict", Component="/system/dict/index", Icon="ele-Collection", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-            new SysMenu{ Id=1310000000342, Pid=1310000000341, Title="查询", Permission="sysDictType:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000343, Pid=1310000000341, Title="编辑", Permission="sysDictType:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000344, Pid=1310000000341, Title="增加", Permission="sysDictType:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000345, Pid=1310000000341, Title="删除", Permission="sysDictType:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000351, Pid=1310000000301, Title="任务调度", Path="/platform/job", Name="sysJob", Component="/system/job/index", Icon="ele-AlarmClock", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
-            new SysMenu{ Id=1310000000352, Pid=1310000000351, Title="查询", Permission="sysJob:pageJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000353, Pid=1310000000351, Title="编辑", Permission="sysJob:updateJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000354, Pid=1310000000351, Title="增加", Permission="sysJob:addJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000355, Pid=1310000000351, Title="删除", Permission="sysJob:deleteJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000361, Pid=1310000000301, Title="系统监控", Path="/platform/server", Name="sysServer", Component="/system/server/index", Icon="ele-Monitor", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
-
-            new SysMenu{ Id=1310000000371, Pid=1310000000301, Title="缓存管理", Path="/platform/cache", Name="sysCache", Component="/system/cache/index", Icon="ele-Loading", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
-            new SysMenu{ Id=1310000000372, Pid=1310000000371, Title="查询", Permission="sysCache:keyList", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000373, Pid=1310000000371, Title="删除", Permission="sysCache:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000374, Pid=1310000000371, Title="清空", Permission="sysCache:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000381, Pid=1310000000301, Title="行政区域", Path="/platform/region", Name="sysRegion", Component="/system/region/index", Icon="ele-LocationInformation", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=170 },
-            new SysMenu{ Id=1310000000382, Pid=1310000000381, Title="查询", Permission="sysRegion:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000383, Pid=1310000000381, Title="编辑", Permission="sysRegion:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000384, Pid=1310000000381, Title="增加", Permission="sysRegion:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000385, Pid=1310000000381, Title="删除", Permission="sysRegion:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000386, Pid=1310000000381, Title="同步", Permission="sysRegion:sync", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000391, Pid=1310000000301, Title="文件管理", Path="/platform/file", Name="sysFile", Component="/system/file/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=180 },
-            new SysMenu{ Id=1310000000392, Pid=1310000000391, Title="查询", Permission="sysFile:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000393, Pid=1310000000391, Title="上传", Permission="sysFile:uploadFile", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000394, Pid=1310000000391, Title="下载", Permission="sysFile:downloadFile", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000395, Pid=1310000000391, Title="删除", Permission="sysFile:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000396, Pid=1310000000391, Title="编辑", Permission="sysFile:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2023-10-27 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000401, Pid=1310000000301, Title="打印模板", Path="/platform/print", Name="sysPrint", Component="/system/print/index", Icon="ele-Printer", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=190 },
-            new SysMenu{ Id=1310000000402, Pid=1310000000401, Title="查询", Permission="sysPrint:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000403, Pid=1310000000401, Title="编辑", Permission="sysPrint:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000404, Pid=1310000000401, Title="增加", Permission="sysPrint:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000405, Pid=1310000000401, Title="删除", Permission="sysPrint:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000411, Pid=1310000000301, Title="动态插件", Path="/platform/plugin", Name="sysPlugin", Component="/system/plugin/index", Icon="ele-Connection", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=200 },
-            new SysMenu{ Id=1310000000412, Pid=1310000000411, Title="查询", Permission="sysPlugin:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000413, Pid=1310000000411, Title="编辑", Permission="sysPlugin:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000414, Pid=1310000000411, Title="增加", Permission="sysPlugin:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000415, Pid=1310000000411, Title="删除", Permission="sysPlugin:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000421, Pid=1310000000301, Title="开放接口", Path="/platform/openAccess", Name="sysOpenAccess", Component="/system/openAccess/index", Icon="ele-Link", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=210 },
-            new SysMenu{ Id=1310000000422, Pid=1310000000421, Title="查询", Permission="sysOpenAccess:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000423, Pid=1310000000421, Title="编辑", Permission="sysOpenAccess:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000424, Pid=1310000000421, Title="增加", Permission="sysOpenAccess:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000425, Pid=1310000000421, Title="删除", Permission="sysOpenAccess:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000431, Pid=1310000000301, Title="系统配置", Path="/platform/infoSetting", Name="sysInfoSetting", Component="/system/infoSetting/index", Icon="ele-Setting", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=220 },
-
-            new SysMenu{ Id=1310000000441, Pid=1310000000301, Title="微信支付", Path="/platform/wechatpay", Name="sysWechatPay", Component="/system/weChatPay/index", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=230 },
-            new SysMenu{ Id=1310000000442, Pid=1310000000441, Title="微信支付下单Native", Permission="sysWechatPay:payTransactionNative", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000443, Pid=1310000000441, Title="查询退款信息", Permission="sysWechatPay:listRefund", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000444, Pid=1310000000441, Title="获取支付订单详情(本地库)", Permission="sysWechatPay:payInfo", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000445, Pid=1310000000441, Title="获取支付订单详情(微信接口)", Permission="sysWechatPay:payInfoFromWechat", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000446, Pid=1310000000441, Title="退款申请", Permission="sysWechatPay:refundDomestic", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000501, Pid=0, Title="日志管理", Path="/log", Name="log", Component="Layout", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=12000 },
-            new SysMenu{ Id=1310000000511, Pid=1310000000501, Title="访问日志", Path="/log/vislog", Name="sysVisLog", Component="/system/log/vislog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000512, Pid=1310000000511, Title="查询", Permission="sysVislog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000513, Pid=1310000000511, Title="清空", Permission="sysVislog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000521, Pid=1310000000501, Title="操作日志", Path="/log/oplog", Name="sysOpLog", Component="/system/log/oplog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000522, Pid=1310000000521, Title="查询", Permission="sysOplog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000523, Pid=1310000000521, Title="清空", Permission="sysOplog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000524, Pid=1310000000521, Title="导出", Permission="sysOplog:export", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000531, Pid=1310000000501, Title="异常日志", Path="/log/exlog", Name="sysExLog", Component="/system/log/exlog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000532, Pid=1310000000531, Title="查询", Permission="sysExlog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000533, Pid=1310000000531, Title="清空", Permission="sysExlog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000534, Pid=1310000000531, Title="导出", Permission="sysExlog:export", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000541, Pid=1310000000501, Title="差异日志", Path="/log/difflog", Name="sysDiffLog", Component="/system/log/difflog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-            new SysMenu{ Id=1310000000542, Pid=1310000000541, Title="查询", Permission="sysDifflog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000543, Pid=1310000000541, Title="清空", Permission="sysDifflog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-
-            new SysMenu{ Id=1310000000601, Pid=0, Title="开发工具", Path="/develop", Name="develop", Component="Layout", Icon="ele-Cpu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=13000 },
-            new SysMenu{ Id=1310000000611, Pid=1310000000601, Title="库表管理", Path="/develop/database", Name="sysDatabase", Component="/system/database/index",Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000621, Pid=1310000000601, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000631, Pid=1310000000601, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000641, Pid=1310000000601, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-
-            new SysMenu{ Id=1310000000701, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 },
-            new SysMenu{ Id=1310000000711, Pid=1310000000701, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="http://101.43.53.74:5050/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
-            new SysMenu{ Id=1310000000712, Pid=1310000000701, Title="后台教程", Path="/doc/furion", Name="sysFurion", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://furion.baiqian.ltd/", Icon="ele-Promotion", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
-            new SysMenu{ Id=1310000000713, Pid=1310000000701, Title="前端教程", Path="/doc/element", Name="sysElement", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://element-plus.gitee.io/zh-CN/", Icon="ele-Position", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
-            new SysMenu{ Id=1310000000714, Pid=1310000000701, Title="SqlSugar", Path="/doc/SqlSugar", Name="sysSqlSugar", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://www.donet5.com/Home/Doc", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
-
-            new SysMenu{ Id=1310000000801, Pid=0, Title="关于项目", Path="/about", Name="about", Component="/about/index", Icon="ele-InfoFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2023-03-12 00:00:00"), OrderNo=15000 },
+            new SysMenu{ Id=1300200000101, Pid=0, Title="系统管理", Path="/system", Name="system", Component="Layout", Icon="ele-Setting", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=10000 },
+
+            new SysMenu{ Id=1300200010101, Pid=1300200000101, Title="账号管理", Path="/system/user", Name="sysUser", Component="/system/user/index", Icon="ele-User", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010201, Pid=1300200010101, Title="查询", Permission="sysUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010301, Pid=1300200010101, Title="编辑", Permission="sysUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010401, Pid=1300200010101, Title="增加", Permission="sysUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010501, Pid=1300200010101, Title="删除", Permission="sysUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010601, Pid=1300200010101, Title="详情", Permission="sysUser:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010701, Pid=1300200010101, Title="授权角色", Permission="sysUser:grantRole", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010801, Pid=1300200010101, Title="重置密码", Permission="sysUser:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200010901, Pid=1300200010101, Title="设置状态", Permission="sysUser:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200011001, Pid=1300200010101, Title="强制下线", Permission="sysOnlineUser:forceOffline", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200011101, Pid=1300200010101, Title="解除锁定", Permission="sysUser:unlockLogin", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200020101, Pid=1300200000101, Title="角色管理", Path="/system/role", Name="sysRole", Component="/system/role/index", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300200020201, Pid=1300200020101, Title="查询", Permission="sysRole:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020301, Pid=1300200020101, Title="编辑", Permission="sysRole:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020401, Pid=1300200020101, Title="增加", Permission="sysRole:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020501, Pid=1300200020101, Title="删除", Permission="sysRole:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020601, Pid=1300200020101, Title="授权菜单", Permission="sysRole:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020701, Pid=1300200020101, Title="授权数据", Permission="sysRole:grantDataScope", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200020801, Pid=1300200020101, Title="设置状态", Permission="sysRole:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200030101, Pid=1300200000101, Title="机构管理", Path="/system/org", Name="sysOrg", Component="/system/org/index", Icon="ele-OfficeBuilding", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300200030201, Pid=1300200030101, Title="查询", Permission="sysOrg:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200030301, Pid=1300200030101, Title="编辑", Permission="sysOrg:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200030401, Pid=1300200030101, Title="增加", Permission="sysOrg:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200030501, Pid=1300200030101, Title="删除", Permission="sysOrg:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200040101, Pid=1300200000101, Title="职位管理", Path="/system/pos", Name="sysPos", Component="/system/pos/index",Icon="ele-Mug", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+            new SysMenu{ Id=1300200040201, Pid=1300200040101, Title="查询", Permission="sysPos:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200040301, Pid=1300200040101, Title="编辑", Permission="sysPos:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200040401, Pid=1300200040101, Title="增加", Permission="sysPos:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200040501, Pid=1300200040101, Title="删除", Permission="sysPos:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200050101, Pid=1300200000101, Title="个人中心", Path="/system/userCenter", Name="sysUserCenter", Component="/system/user/component/userCenter",Icon="ele-Medal", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
+            new SysMenu{ Id=1300200050201, Pid=1300200050101, Title="修改密码", Permission="sysUser:changePwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200050301, Pid=1300200050101, Title="基本信息", Permission="sysUser:baseInfo", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200050401, Pid=1300200050101, Title="电子签名", Permission="sysFile:uploadSignature", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200050501, Pid=1300200050101, Title="上传头像", Permission="sysFile:uploadAvatar", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200060101, Pid=1300200000101, Title="通知公告", Path="/system/notice", Name="sysNotice", Component="/system/notice/index",Icon="ele-Bell", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
+            new SysMenu{ Id=1300200060201, Pid=1300200060101, Title="查询", Permission="sysNotice:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200060301, Pid=1300200060101, Title="编辑", Permission="sysNotice:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200060401, Pid=1300200060101, Title="增加", Permission="sysNotice:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200060501, Pid=1300200060101, Title="删除", Permission="sysNotice:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200060601, Pid=1300200060101, Title="发布", Permission="sysNotice:public", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200060701, Pid=1300200060101, Title="撤回", Permission="sysNotice:cancel", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200070101, Pid=1300200000101, Title="三方账号", Path="/system/weChatUser", Name="sysWechatUser", Component="/system/weChatUser/index",Icon="ele-ChatDotRound", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
+            new SysMenu{ Id=1300200070201, Pid=1300200070101, Title="查询", Permission="sysWechatUser:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200070301, Pid=1300200070101, Title="编辑", Permission="sysWechatUser:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200070401, Pid=1300200070101, Title="增加", Permission="sysWechatUser:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200070501, Pid=1300200070101, Title="删除", Permission="sysWechatUser:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300200080101, Pid=1300200000101, Title="AD域配置", Path="/system/ldap", Name="sysLdap", Component="/system/ldap/index",Icon="ele-Place", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=170 },
+            new SysMenu{ Id=1300200080201, Pid=1300200080101, Title="查询", Permission="sysLdap:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300200080301, Pid=1300200080101, Title="详情", Permission="sysLdap:detail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300200080401, Pid=1300200080101, Title="编辑", Permission="sysLdap:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300200080501, Pid=1300200080101, Title="增加", Permission="sysLdap:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+            new SysMenu{ Id=1300200080601, Pid=1300200080101, Title="删除", Permission="sysLdap:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
+            new SysMenu{ Id=1300200080701, Pid=1300200080101, Title="同步域账户", Permission="sysLdap:syncUser", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
+            new SysMenu{ Id=1300200080801, Pid=1300200080101, Title="同步域组织", Permission="sysLdap:syncOrg", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
+
+            new SysMenu{ Id=1300300000101, Pid=0, Title="平台管理", Path="/platform", Name="platform", Component="Layout", Icon="ele-Menu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=11000 },
+
+            new SysMenu{ Id=1300300010101, Pid=1300300000101, Title="租户管理", Path="/platform/tenant", Name="sysTenant", Component="/system/tenant/index", Icon="ele-School", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010201, Pid=1300300010101, Title="查询", Permission="sysTenant:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010301, Pid=1300300010101, Title="编辑", Permission="sysTenant:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010401, Pid=1300300010101, Title="增加", Permission="sysTenant:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010501, Pid=1300300010101, Title="删除", Permission="sysTenant:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010601, Pid=1300300010101, Title="授权菜单", Permission="sysTenant:grantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010701, Pid=1300300010101, Title="重置密码", Permission="sysTenant:resetPwd", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010801, Pid=1300300010101, Title="生成库", Permission="sysTenant:createDb", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300010901, Pid=1300300010101, Title="设置状态", Permission="sysTenant:setStatus", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300011001, Pid=1300300010101, Title="同步授权", Permission="sysTenant:syncGrantMenu", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300011101, Pid=1300300010101, Title="切换租户", Permission="sysTenant:changeTenant", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300011201, Pid=1300300010101, Title="进入租管端", Permission="sysTenant:goTenant", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300020101, Pid=1300300000101, Title="注册方案", Path="/platform/regWay", Name="sysUserRegWay", Component="/system/userRegWay/index", Icon="ele-Menu", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=105 },
+            new SysMenu{ Id=1300300020201, Pid=1300300020101, Title="查询", Permission="sysUserRegWay:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300020301, Pid=1300300020101, Title="编辑", Permission="sysUserRegWay:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300020401, Pid=1300300020101, Title="增加", Permission="sysUserRegWay:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300020501, Pid=1300300020101, Title="删除", Permission="sysUserRegWay:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300030101, Pid=1300300000101, Title="菜单管理", Path="/platform/menu", Name="sysMenu", Component="/system/menu/index", Icon="ele-Menu", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300300030201, Pid=1300300030101, Title="查询", Permission="sysMenu:list", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300030301, Pid=1300300030101, Title="编辑", Permission="sysMenu:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300030401, Pid=1300300030101, Title="增加", Permission="sysMenu:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300030501, Pid=1300300030101, Title="删除", Permission="sysMenu:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300040101, Pid=1300300000101, Title="参数配置", Path="/platform/config", Name="sysConfig", Component="/system/config/index", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300300040201, Pid=1300300040101, Title="查询", Permission="sysConfig:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300040301, Pid=1300300040101, Title="编辑", Permission="sysConfig:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300040401, Pid=1300300040101, Title="增加", Permission="sysConfig:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300040501, Pid=1300300040101, Title="删除", Permission="sysConfig:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300050101, Pid=1300300000101, Title="字典管理", Path="/platform/dict", Name="sysDict", Component="/system/dict/index", Icon="ele-Collection", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+            new SysMenu{ Id=1300300050201, Pid=1300300050101, Title="查询", Permission="sysDictType:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050301, Pid=1300300050101, Title="编辑", Permission="sysDictType:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050401, Pid=1300300050101, Title="增加", Permission="sysDictType:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050501, Pid=1300300050101, Title="删除", Permission="sysDictType:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050601, Pid=1300300050101, Title="增加字典值", Permission="sysDictData:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050701, Pid=1300300050101, Title="删除字典值", Permission="sysDictData:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300050801, Pid=1300300050101, Title="编辑字典值", Permission="sysDictData:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300060101, Pid=1300300000101, Title="任务调度", Path="/platform/job", Name="sysJob", Component="/system/job/index", Icon="ele-AlarmClock", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=140 },
+            new SysMenu{ Id=1300300060201, Pid=1300300060101, Title="查询", Permission="sysJob:pageJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300060301, Pid=1300300060101, Title="编辑", Permission="sysJob:updateJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300060401, Pid=1300300060101, Title="增加", Permission="sysJob:addJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300060501, Pid=1300300060101, Title="删除", Permission="sysJob:deleteJobDetail", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300070101, Pid=1300300000101, Title="系统监控", Path="/platform/server", Name="sysServer", Component="/system/server/index", Icon="ele-Monitor", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=150 },
+
+            new SysMenu{ Id=1300300080101, Pid=1300300000101, Title="缓存管理", Path="/platform/cache", Name="sysCache", Component="/system/cache/index", Icon="ele-Loading", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=160 },
+            new SysMenu{ Id=1300300080201, Pid=1300300080101, Title="查询", Permission="sysCache:keyList", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300080301, Pid=1300300080101, Title="删除", Permission="sysCache:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300080401, Pid=1300300080101, Title="清空", Permission="sysCache:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300090101, Pid=1300300000101, Title="行政区域", Path="/platform/region", Name="sysRegion", Component="/system/region/index", Icon="ele-LocationInformation", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=170 },
+            new SysMenu{ Id=1300300090201, Pid=1300300090101, Title="查询", Permission="sysRegion:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300090301, Pid=1300300090101, Title="编辑", Permission="sysRegion:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300090401, Pid=1300300090101, Title="增加", Permission="sysRegion:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300090501, Pid=1300300090101, Title="删除", Permission="sysRegion:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300090601, Pid=1300300090101, Title="同步", Permission="sysRegion:sync", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300100101, Pid=1300300000101, Title="文件管理", Path="/platform/file", Name="sysFile", Component="/system/file/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=180 },
+            new SysMenu{ Id=1300300100201, Pid=1300300100101, Title="查询", Permission="sysFile:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300100301, Pid=1300300100101, Title="上传", Permission="sysFile:uploadFile", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300100401, Pid=1300300100101, Title="下载", Permission="sysFile:downloadFile", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300100501, Pid=1300300100101, Title="删除", Permission="sysFile:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300100601, Pid=1300300100101, Title="编辑", Permission="sysFile:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2023-10-27 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300110101, Pid=1300300000101, Title="打印模板", Path="/platform/print", Name="sysPrint", Component="/system/print/index", Icon="ele-Printer", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=190 },
+            new SysMenu{ Id=1300300110201, Pid=1300300110101, Title="查询", Permission="sysPrint:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300110301, Pid=1300300110101, Title="编辑", Permission="sysPrint:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300110401, Pid=1300300110101, Title="增加", Permission="sysPrint:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300110501, Pid=1300300110101, Title="删除", Permission="sysPrint:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300120101, Pid=1300300000101, Title="动态插件", Path="/platform/plugin", Name="sysPlugin", Component="/system/plugin/index", Icon="ele-Connection", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=200 },
+            new SysMenu{ Id=1300300120201, Pid=1300300120101, Title="查询", Permission="sysPlugin:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300120301, Pid=1300300120101, Title="编辑", Permission="sysPlugin:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300120401, Pid=1300300120101, Title="增加", Permission="sysPlugin:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300120501, Pid=1300300120101, Title="删除", Permission="sysPlugin:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300130101, Pid=1300300000101, Title="开放接口", Path="/platform/openAccess", Name="sysOpenAccess", Component="/system/openAccess/index", Icon="ele-Link", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=210 },
+            new SysMenu{ Id=1300300130201, Pid=1300300130101, Title="查询", Permission="sysOpenAccess:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300130301, Pid=1300300130101, Title="编辑", Permission="sysOpenAccess:update", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300130401, Pid=1300300130101, Title="增加", Permission="sysOpenAccess:add", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300130501, Pid=1300300130101, Title="删除", Permission="sysOpenAccess:delete", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300300140101, Pid=1300300000101, Title="系统配置", Path="/platform/infoSetting", Name="sysInfoSetting", Component="/system/infoSetting/index", Icon="ele-Setting", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=220 },
+
+            new SysMenu{ Id=1300300150101, Pid=1300300000101, Title="微信支付", Path="/platform/wechatpay", Name="sysWechatPay", Component="/system/weChatPay/index", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=230 },
+            new SysMenu{ Id=1300300150201, Pid=1300300150101, Title="微信支付下单Native", Permission="sysWechatPay:payTransactionNative", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300150301, Pid=1300300150101, Title="查询退款信息", Permission="sysWechatPay:listRefund", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300150401, Pid=1300300150101, Title="获取支付订单详情(本地库)", Permission="sysWechatPay:payInfo", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300150501, Pid=1300300150101, Title="获取支付订单详情(微信接口)", Permission="sysWechatPay:payInfoFromWechat", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300300150601, Pid=1300300150101, Title="退款申请", Permission="sysWechatPay:refundDomestic", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300400000101, Pid=0, Title="日志管理", Path="/log", Name="log", Component="Layout", Icon="ele-DocumentCopy", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=12000 },
+            new SysMenu{ Id=1300400010101, Pid=1300400000101, Title="访问日志", Path="/log/vislog", Name="sysVisLog", Component="/system/log/vislog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400010201, Pid=1300400010101, Title="查询", Permission="sysVislog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400010301, Pid=1300400010101, Title="清空", Permission="sysVislog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400020101, Pid=1300400000101, Title="操作日志", Path="/log/oplog", Name="sysOpLog", Component="/system/log/oplog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300400020201, Pid=1300400020101, Title="查询", Permission="sysOplog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400020301, Pid=1300400020101, Title="清空", Permission="sysOplog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400020401, Pid=1300400020101, Title="导出", Permission="sysOplog:export", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400030101, Pid=1300400000101, Title="异常日志", Path="/log/exlog", Name="sysExLog", Component="/system/log/exlog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300400030201, Pid=1300400030101, Title="查询", Permission="sysExlog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400030301, Pid=1300400030101, Title="清空", Permission="sysExlog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400030401, Pid=1300400030101, Title="导出", Permission="sysExlog:export", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400040101, Pid=1300400000101, Title="差异日志", Path="/log/difflog", Name="sysDiffLog", Component="/system/log/difflog/index", Icon="ele-Document", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+            new SysMenu{ Id=1300400040201, Pid=1300400040101, Title="查询", Permission="sysDifflog:page", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300400040301, Pid=1300400040101, Title="清空", Permission="sysDifflog:clear", Type=MenuTypeEnum.Btn, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+
+            new SysMenu{ Id=1300500000101, Pid=0, Title="开发工具", Path="/develop", Name="develop", Component="Layout", Icon="ele-Cpu", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=13000 },
+            new SysMenu{ Id=1300500010101, Pid=1300500000101, Title="库表管理", Path="/develop/database", Name="sysDatabase", Component="/system/database/index",Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300500020101, Pid=1300500000101, Title="代码生成", Path="/develop/codeGen", Name="sysCodeGen", Component="/system/codeGen/index", Icon="ele-Crop", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300500030101, Pid=1300500000101, Title="表单设计", Path="/develop/formDes", Name="sysFormDes", Component="/system/formDes/index", Icon="ele-Edit", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300500040101, Pid=1300500000101, Title="系统接口", Path="/develop/api", Name="sysApi", Component="layout/routerView/iframe", IsIframe=true, OutLink="http://localhost:5005", Icon="ele-Help", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+
+            new SysMenu{ Id=1300600000101, Pid=0, Title="帮助文档", Path="/doc", Name="doc", Component="Layout", Icon="ele-Notebook", Type=MenuTypeEnum.Dir, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=14000 },
+            new SysMenu{ Id=1300600010101, Pid=1300600000101, Title="框架教程", Path="/doc/admin", Name="sysAdmin", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="http://101.43.53.74:5050/", Icon="ele-Sunny", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=100 },
+            new SysMenu{ Id=1300600020101, Pid=1300600000101, Title="后台教程", Path="/doc/furion", Name="sysFurion", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://furion.baiqian.ltd/", Icon="ele-Promotion", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=110 },
+            new SysMenu{ Id=1300600030101, Pid=1300600000101, Title="前端教程", Path="/doc/element", Name="sysElement", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://element-plus.gitee.io/zh-CN/", Icon="ele-Position", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=120 },
+            new SysMenu{ Id=1300600040101, Pid=1300600000101, Title="SqlSugar", Path="/doc/SqlSugar", Name="sysSqlSugar", Component="layout/routerView/link", IsIframe=false, IsKeepAlive=false, OutLink="https://www.donet5.com/Home/Doc", Icon="ele-Coin", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrderNo=130 },
+
+            new SysMenu{ Id=1300700000101, Pid=0, Title="关于项目", Path="/about", Name="about", Component="/about/index", Icon="ele-InfoFilled", Type=MenuTypeEnum.Menu, CreateTime=DateTime.Parse("2023-03-12 00:00:00"), OrderNo=15000 },
         };
     }
 }

+ 5 - 4
Admin.NET/Admin.NET.Core/SeedData/SysOrgSeedData.cs

@@ -18,13 +18,14 @@ public class SysOrgSeedData : ISqlSugarEntitySeedData<SysOrg>
     /// <returns></returns>
     public IEnumerable<SysOrg> HasData()
     {
+        var admin = new SysUserSeedData().HasData().First(u => u.Account == "admin");
         return new[]
         {
             new SysOrg{ Id=SqlSugarConst.DefaultTenantId, Pid=0, Name="系统默认", Code="1001", Type="101", Level=1, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统默认", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 1, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 2, Pid=SqlSugarConst.DefaultTenantId, Name="开发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="开发部", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 3, Pid=SqlSugarConst.DefaultTenantId, Name="售后部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="售后部", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 4, Pid=SqlSugarConst.DefaultTenantId, Name="其他", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", TenantId=SqlSugarConst.DefaultTenantId },
+            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 1, Pid=SqlSugarConst.DefaultTenantId, Name="市场部", Code="100101", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="市场部", CreateUserId=admin.Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 2, Pid=SqlSugarConst.DefaultTenantId, Name="开发部", Code="100102", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="开发部", CreateUserId=admin.Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 3, Pid=SqlSugarConst.DefaultTenantId, Name="售后部", Code="100103", Level=2, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="售后部", CreateUserId=admin.Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysOrg{ Id=SqlSugarConst.DefaultTenantId + 4, Pid=SqlSugarConst.DefaultTenantId, Name="其他", Code="10010301", Level=3, CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="其他", CreateUserId=admin.Id, TenantId=SqlSugarConst.DefaultTenantId },
         };
     }
 }

+ 19 - 179
Admin.NET/Admin.NET.Core/SeedData/SysRoleMenuSeedData.cs

@@ -17,187 +17,27 @@ public class SysRoleMenuSeedData : ISqlSugarEntitySeedData<SysRoleMenu>
     /// <returns></returns>
     public IEnumerable<SysRoleMenu> HasData()
     {
-        return new[]
-        {
-            ////// 数据面板【admin/1300000000101】
-            new SysRoleMenu{ Id=1300000000101, RoleId=1300000000101, MenuId=1300000000101 },
-            new SysRoleMenu{ Id=1300000000102, RoleId=1300000000101, MenuId=1300000000111 },
-            new SysRoleMenu{ Id=1300000000103, RoleId=1300000000101, MenuId=1300000000121 },
-            ////// 系统管理
-            new SysRoleMenu{ Id=1300000000111, RoleId=1300000000101, MenuId=1310000000101 },
-            // 账号管理
-            new SysRoleMenu{ Id=1300000000121, RoleId=1300000000101, MenuId=1310000000111 },
-            new SysRoleMenu{ Id=1300000000122, RoleId=1300000000101, MenuId=1310000000112 },
-            new SysRoleMenu{ Id=1300000000123, RoleId=1300000000101, MenuId=1310000000113 },
-            new SysRoleMenu{ Id=1300000000124, RoleId=1300000000101, MenuId=1310000000114 },
-            new SysRoleMenu{ Id=1300000000125, RoleId=1300000000101, MenuId=1310000000115 },
-            new SysRoleMenu{ Id=1300000000126, RoleId=1300000000101, MenuId=1310000000116 },
-            new SysRoleMenu{ Id=1300000000127, RoleId=1300000000101, MenuId=1310000000117 },
-            new SysRoleMenu{ Id=1300000000128, RoleId=1300000000101, MenuId=1310000000118 },
-            new SysRoleMenu{ Id=1300000000129, RoleId=1300000000101, MenuId=1310000000119 },
-            new SysRoleMenu{ Id=1300000000130, RoleId=1300000000101, MenuId=1310000000120 },
-            new SysRoleMenu{ Id=1300000000131, RoleId=1300000000101, MenuId=1310000000121 },
-            // 角色管理
-            new SysRoleMenu{ Id=1300000000141, RoleId=1300000000101, MenuId=1310000000131 },
-            new SysRoleMenu{ Id=1300000000142, RoleId=1300000000101, MenuId=1310000000132 },
-            new SysRoleMenu{ Id=1300000000143, RoleId=1300000000101, MenuId=1310000000133 },
-            new SysRoleMenu{ Id=1300000000144, RoleId=1300000000101, MenuId=1310000000134 },
-            new SysRoleMenu{ Id=1300000000145, RoleId=1300000000101, MenuId=1310000000135 },
-            new SysRoleMenu{ Id=1300000000146, RoleId=1300000000101, MenuId=1310000000136 },
-            new SysRoleMenu{ Id=1300000000147, RoleId=1300000000101, MenuId=1310000000137 },
-            new SysRoleMenu{ Id=1300000000148, RoleId=1300000000101, MenuId=1310000000138 },
-            // 机构管理
-            new SysRoleMenu{ Id=1300000000151, RoleId=1300000000101, MenuId=1310000000141 },
-            new SysRoleMenu{ Id=1300000000152, RoleId=1300000000101, MenuId=1310000000142 },
-            new SysRoleMenu{ Id=1300000000153, RoleId=1300000000101, MenuId=1310000000143 },
-            new SysRoleMenu{ Id=1300000000154, RoleId=1300000000101, MenuId=1310000000144 },
-            new SysRoleMenu{ Id=1300000000155, RoleId=1300000000101, MenuId=1310000000145 },
-            // 职位管理
-            new SysRoleMenu{ Id=1300000000161, RoleId=1300000000101, MenuId=1310000000151 },
-            new SysRoleMenu{ Id=1300000000162, RoleId=1300000000101, MenuId=1310000000152 },
-            new SysRoleMenu{ Id=1300000000163, RoleId=1300000000101, MenuId=1310000000153 },
-            new SysRoleMenu{ Id=1300000000164, RoleId=1300000000101, MenuId=1310000000154 },
-            new SysRoleMenu{ Id=1300000000165, RoleId=1300000000101, MenuId=1310000000155 },
-            new SysRoleMenu{ Id=1300000000166, RoleId=1300000000101, MenuId=1310000000156 },
-            // 个人中心
-            new SysRoleMenu{ Id=1300000000171, RoleId=1300000000101, MenuId=1310000000161 },
-            new SysRoleMenu{ Id=1300000000172, RoleId=1300000000101, MenuId=1310000000162 },
-            new SysRoleMenu{ Id=1300000000173, RoleId=1300000000101, MenuId=1310000000163 },
-            new SysRoleMenu{ Id=1300000000174, RoleId=1300000000101, MenuId=1310000000164 },
-            new SysRoleMenu{ Id=1300000000175, RoleId=1300000000101, MenuId=1310000000165 },
-            // 通知公告
-            new SysRoleMenu{ Id=1300000000181, RoleId=1300000000101, MenuId=1310000000171 },
-            new SysRoleMenu{ Id=1300000000182, RoleId=1300000000101, MenuId=1310000000172 },
-            new SysRoleMenu{ Id=1300000000183, RoleId=1300000000101, MenuId=1310000000173 },
-            new SysRoleMenu{ Id=1300000000184, RoleId=1300000000101, MenuId=1310000000174 },
-            new SysRoleMenu{ Id=1300000000185, RoleId=1300000000101, MenuId=1310000000175 },
-            new SysRoleMenu{ Id=1300000000186, RoleId=1300000000101, MenuId=1310000000176 },
-            new SysRoleMenu{ Id=1300000000187, RoleId=1300000000101, MenuId=1310000000177 },
-            // 三方账号
-            new SysRoleMenu{ Id=1300000000191, RoleId=1300000000101, MenuId=1310000000181 },
-            new SysRoleMenu{ Id=1300000000192, RoleId=1300000000101, MenuId=1310000000182 },
-            new SysRoleMenu{ Id=1300000000193, RoleId=1300000000101, MenuId=1310000000183 },
-            new SysRoleMenu{ Id=1300000000194, RoleId=1300000000101, MenuId=1310000000184 },
-            new SysRoleMenu{ Id=1300000000195, RoleId=1300000000101, MenuId=1310000000185 },
-            ////// 平台管理
-            new SysRoleMenu{ Id=1300000000201, RoleId=1300000000101, MenuId=1310000000301 },
-            // 菜单管理
-            new SysRoleMenu{ Id=1300000000221, RoleId=1300000000101, MenuId=1310000000322 },
-            // 字典管理
-            new SysRoleMenu{ Id=1300000000231, RoleId=1300000000101, MenuId=1310000000331 },
-            new SysRoleMenu{ Id=1300000000232, RoleId=1300000000101, MenuId=1310000000332 },
-            new SysRoleMenu{ Id=1300000000233, RoleId=1300000000101, MenuId=1310000000333 },
-            new SysRoleMenu{ Id=1300000000234, RoleId=1300000000101, MenuId=1310000000334 },
-            new SysRoleMenu{ Id=1300000000235, RoleId=1300000000101, MenuId=1310000000335 },
-            // 字典管理
-            new SysRoleMenu{ Id=1300000000241, RoleId=1300000000101, MenuId=1310000000341 },
-            new SysRoleMenu{ Id=1300000000242, RoleId=1300000000101, MenuId=1310000000342 },
-            new SysRoleMenu{ Id=1300000000243, RoleId=1300000000101, MenuId=1310000000343 },
-            new SysRoleMenu{ Id=1300000000244, RoleId=1300000000101, MenuId=1310000000344 },
-            new SysRoleMenu{ Id=1300000000245, RoleId=1300000000101, MenuId=1310000000345 },
-            // 任务调度
-            new SysRoleMenu{ Id=1300000000251, RoleId=1300000000101, MenuId=1310000000351 },
-            new SysRoleMenu{ Id=1300000000252, RoleId=1300000000101, MenuId=1310000000352 },
-            new SysRoleMenu{ Id=1300000000253, RoleId=1300000000101, MenuId=1310000000353 },
-            new SysRoleMenu{ Id=1300000000254, RoleId=1300000000101, MenuId=1310000000354 },
-            new SysRoleMenu{ Id=1300000000255, RoleId=1300000000101, MenuId=1310000000355 },
-            // 系统监控
-            new SysRoleMenu{ Id=1300000000261, RoleId=1300000000101, MenuId=1310000000361 },
-            // 缓存管理
-            new SysRoleMenu{ Id=1300000000271, RoleId=1300000000101, MenuId=1310000000371 },
-            new SysRoleMenu{ Id=1300000000272, RoleId=1300000000101, MenuId=1310000000372 },
-            new SysRoleMenu{ Id=1300000000273, RoleId=1300000000101, MenuId=1310000000373 },
-            new SysRoleMenu{ Id=1300000000274, RoleId=1300000000101, MenuId=1310000000374 },
-            // 行政区域
-            new SysRoleMenu{ Id=1300000000281, RoleId=1300000000101, MenuId=1310000000381 },
-            new SysRoleMenu{ Id=1300000000282, RoleId=1300000000101, MenuId=1310000000382 },
-            new SysRoleMenu{ Id=1300000000283, RoleId=1300000000101, MenuId=1310000000383 },
-            new SysRoleMenu{ Id=1300000000284, RoleId=1300000000101, MenuId=1310000000384 },
-            new SysRoleMenu{ Id=1300000000285, RoleId=1300000000101, MenuId=1310000000385 },
-            new SysRoleMenu{ Id=1300000000286, RoleId=1300000000101, MenuId=1310000000386 },
-            // 文件管理
-            new SysRoleMenu{ Id=1300000000291, RoleId=1300000000101, MenuId=1310000000391 },
-            new SysRoleMenu{ Id=1300000000292, RoleId=1300000000101, MenuId=1310000000392 },
-            new SysRoleMenu{ Id=1300000000293, RoleId=1300000000101, MenuId=1310000000393 },
-            new SysRoleMenu{ Id=1300000000294, RoleId=1300000000101, MenuId=1310000000394 },
-            new SysRoleMenu{ Id=1300000000295, RoleId=1300000000101, MenuId=1310000000395 },
-            new SysRoleMenu{ Id=1300000000296, RoleId=1300000000101, MenuId=1310000000396 },
-            ////// 日志管理
-            new SysRoleMenu{ Id=1300000000301, RoleId=1300000000101, MenuId=1310000000501 },
-            new SysRoleMenu{ Id=1300000000311, RoleId=1300000000101, MenuId=1310000000511 },
-            new SysRoleMenu{ Id=1300000000312, RoleId=1300000000101, MenuId=1310000000512 },
-            new SysRoleMenu{ Id=1300000000313, RoleId=1300000000101, MenuId=1310000000513 },
-            new SysRoleMenu{ Id=1300000000321, RoleId=1300000000101, MenuId=1310000000521 },
-            new SysRoleMenu{ Id=1300000000322, RoleId=1300000000101, MenuId=1310000000522 },
-            new SysRoleMenu{ Id=1300000000323, RoleId=1300000000101, MenuId=1310000000523 },
-            new SysRoleMenu{ Id=1300000000324, RoleId=1300000000101, MenuId=1310000000524 },
-            new SysRoleMenu{ Id=1300000000331, RoleId=1300000000101, MenuId=1310000000531 },
-            new SysRoleMenu{ Id=1300000000332, RoleId=1300000000101, MenuId=1310000000532 },
-            new SysRoleMenu{ Id=1300000000333, RoleId=1300000000101, MenuId=1310000000533 },
-            new SysRoleMenu{ Id=1300000000334, RoleId=1300000000101, MenuId=1310000000534 },
-            new SysRoleMenu{ Id=1300000000341, RoleId=1300000000101, MenuId=1310000000541 },
-            new SysRoleMenu{ Id=1300000000342, RoleId=1300000000101, MenuId=1310000000542 },
-            new SysRoleMenu{ Id=1300000000343, RoleId=1300000000101, MenuId=1310000000543 },
-            ////// 帮助文档
-            new SysRoleMenu{ Id=1300000000401, RoleId=1300000000101, MenuId=1310000000701 },
-            new SysRoleMenu{ Id=1300000000402, RoleId=1300000000101, MenuId=1310000000711 },
-            new SysRoleMenu{ Id=1300000000403, RoleId=1300000000101, MenuId=1310000000712 },
-            new SysRoleMenu{ Id=1300000000404, RoleId=1300000000101, MenuId=1310000000713 },
-            new SysRoleMenu{ Id=1300000000405, RoleId=1300000000101, MenuId=1310000000714 },
-            new SysRoleMenu{ Id=1300000000455, RoleId=1300000000101, MenuId=1310000000801 },
+        var id = 1300000000000;
+        var roleList = new SysRoleSeedData().HasData().ToList();
+        var menuList = new SysMenuSeedData().HasData().ToList();
+        
+        var dashboardMenus = menuList.ToChildList(u => u.Id, u => u.Pid, u => u.Type == MenuTypeEnum.Menu && u.Title == "工作台");
+        var systemMenu = menuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "系统管理");
+        var orgMenus = menuList.ToChildList(u => u.Id, u => u.Pid, u => u.Type == MenuTypeEnum.Menu && u.Title == "机构管理");
+        var personMenus = menuList.ToChildList(u => u.Id, u => u.Pid, u => u.Type == MenuTypeEnum.Menu && u.Title == "个人中心");
 
-            // 其他角色默认菜单
-            // 数据面板【1300000000102】
-            new SysRoleMenu{ Id=1300000000501, RoleId=1300000000102, MenuId=1300000000101 },
-            new SysRoleMenu{ Id=1300000000502, RoleId=1300000000102, MenuId=1300000000111 },
-            new SysRoleMenu{ Id=1300000000503, RoleId=1300000000102, MenuId=1300000000121 },
-            // 机构管理
-            new SysRoleMenu{ Id=1300000000511, RoleId=1300000000102, MenuId=1310000000142 },
-            // 个人中心
-            new SysRoleMenu{ Id=1300000000521, RoleId=1300000000102, MenuId=1310000000161 },
-            new SysRoleMenu{ Id=1300000000522, RoleId=1300000000102, MenuId=1310000000162 },
-            new SysRoleMenu{ Id=1300000000523, RoleId=1300000000102, MenuId=1310000000163 },
-            new SysRoleMenu{ Id=1300000000524, RoleId=1300000000102, MenuId=1310000000164 },
-            new SysRoleMenu{ Id=1300000000525, RoleId=1300000000102, MenuId=1310000000165 },
-
-            // 数据面板【1300000000103】
-            new SysRoleMenu{ Id=1300000000601, RoleId=1300000000103, MenuId=1300000000101 },
-            new SysRoleMenu{ Id=1300000000602, RoleId=1300000000103, MenuId=1300000000111 },
-            new SysRoleMenu{ Id=1300000000603, RoleId=1300000000103, MenuId=1300000000121 },
-            // 机构管理
-            new SysRoleMenu{ Id=1300000000611, RoleId=1300000000103, MenuId=1310000000142 },
-            // 个人中心
-            new SysRoleMenu{ Id=1300000000621, RoleId=1300000000103, MenuId=1310000000161 },
-            new SysRoleMenu{ Id=1300000000622, RoleId=1300000000103, MenuId=1310000000162 },
-            new SysRoleMenu{ Id=1300000000623, RoleId=1300000000103, MenuId=1310000000163 },
-            new SysRoleMenu{ Id=1300000000624, RoleId=1300000000103, MenuId=1310000000164 },
-            new SysRoleMenu{ Id=1300000000625, RoleId=1300000000103, MenuId=1310000000165 },
-
-            // 数据面板【1300000000104】
-            new SysRoleMenu{ Id=1300000000701, RoleId=1300000000104, MenuId=1300000000101 },
-            new SysRoleMenu{ Id=1300000000702, RoleId=1300000000104, MenuId=1300000000111 },
-            new SysRoleMenu{ Id=1300000000703, RoleId=1300000000104, MenuId=1300000000121 },
-            // 机构管理
-            new SysRoleMenu{ Id=1300000000711, RoleId=1300000000104, MenuId=1310000000142 },
-            // 个人中心
-            new SysRoleMenu{ Id=1300000000721, RoleId=1300000000104, MenuId=1310000000161 },
-            new SysRoleMenu{ Id=1300000000722, RoleId=1300000000104, MenuId=1310000000162 },
-            new SysRoleMenu{ Id=1300000000723, RoleId=1300000000104, MenuId=1310000000163 },
-            new SysRoleMenu{ Id=1300000000724, RoleId=1300000000104, MenuId=1310000000164 },
-            new SysRoleMenu{ Id=1300000000725, RoleId=1300000000104, MenuId=1310000000165 },
-
-            // 数据面板【1300000000105】
-            new SysRoleMenu{ Id=1300000000801, RoleId=1300000000105, MenuId=1300000000101 },
-            new SysRoleMenu{ Id=1300000000802, RoleId=1300000000105, MenuId=1300000000111 },
-            new SysRoleMenu{ Id=1300000000803, RoleId=1300000000105, MenuId=1300000000121 },
+        var roleMenuList = new List<SysRoleMenu>();
+        foreach (var role in roleList)
+        {
+            // 工作台
+            dashboardMenus.ForEach(m => roleMenuList.Add(new SysRoleMenu { Id=id+=100, RoleId=role.Id, MenuId=m.Id }));
+            // 系统管理
+            roleMenuList.Add(new SysRoleMenu { Id=id+=100, RoleId=role.Id, MenuId=systemMenu.Id });
             // 机构管理
-            new SysRoleMenu{ Id=1300000000811, RoleId=1300000000105, MenuId=1310000000142 },
+            orgMenus.ForEach(m => roleMenuList.Add(new SysRoleMenu { Id=id+=100, RoleId=role.Id, MenuId=m.Id }));
             // 个人中心
-            new SysRoleMenu{ Id=1300000000821, RoleId=1300000000105, MenuId=1310000000161 },
-            new SysRoleMenu{ Id=1300000000822, RoleId=1300000000105, MenuId=1310000000162 },
-            new SysRoleMenu{ Id=1300000000823, RoleId=1300000000105, MenuId=1310000000163 },
-            new SysRoleMenu{ Id=1300000000824, RoleId=1300000000105, MenuId=1310000000164 },
-            new SysRoleMenu{ Id=1300000000825, RoleId=1300000000105, MenuId=1310000000165 },
-        };
+            personMenus.ForEach(m => roleMenuList.Add(new SysRoleMenu { Id=id+=100, RoleId=role.Id, MenuId=m.Id }));
+        }
+        return roleMenuList;
     }
 }

+ 4 - 5
Admin.NET/Admin.NET.Core/SeedData/SysRoleSeedData.cs

@@ -19,11 +19,10 @@ public class SysRoleSeedData : ISqlSugarEntitySeedData<SysRole>
     {
         return new[]
         {
-            new SysRole{ Id=1300000000101, Name="系统管理员", DataScope=DataScopeEnum.All, Code="sys_admin", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="系统管理员", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysRole{ Id=1300000000102, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_deptChild", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysRole{ Id=1300000000103, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysRole{ Id=1300000000104, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=SqlSugarConst.DefaultTenantId },
-            new SysRole{ Id=1300000000105, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=SqlSugarConst.DefaultTenantId },
+            new SysRole{ Id=1300000000101, Name="本部门及以下数据", DataScope=DataScopeEnum.DeptChild, Code="sys_deptChild", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门及以下数据", TenantId=SqlSugarConst.DefaultTenantId },
+            new SysRole{ Id=1300000000102, Name="本部门数据", DataScope=DataScopeEnum.Dept, Code="sys_dept", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="本部门数据", TenantId=SqlSugarConst.DefaultTenantId },
+            new SysRole{ Id=1300000000103, Name="仅本人数据", DataScope=DataScopeEnum.Self, Code="sys_self", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="仅本人数据", TenantId=SqlSugarConst.DefaultTenantId },
+            new SysRole{ Id=1300000000104, Name="自定义数据", DataScope=DataScopeEnum.Define, Code="sys_define", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), Remark="自定义数据", TenantId=SqlSugarConst.DefaultTenantId },
         };
     }
 }

+ 6 - 5
Admin.NET/Admin.NET.Core/SeedData/SysAppMenuSeedData.cs → Admin.NET/Admin.NET.Core/SeedData/SysTenantMenuSeedData.cs

@@ -7,17 +7,18 @@
 namespace Admin.NET.Core;
 
 /// <summary>
-/// 系统应用菜单表种子数据
+/// 系统租户菜单表种子数据
 /// </summary>
-public class SysAppMenuSeedData : ISqlSugarEntitySeedData<SysAppMenu>
+[IgnoreUpdateSeed]
+public class SysTenantMenuSeedData : ISqlSugarEntitySeedData<SysTenantMenu>
 {
     /// <summary>
     /// 种子数据
     /// </summary>
     /// <returns></returns>
-    public IEnumerable<SysAppMenu> HasData()
+    public IEnumerable<SysTenantMenu> HasData()
     {
-        long id = 1300000000001;
-        return new SysMenuSeedData().HasData().Select(m => new SysAppMenu { Id = id++, AppId = SqlSugarConst.DefaultAppId, MenuId = m.Id });
+        var id = 1300000000000;
+        return App.GetService<SysTenantService>().GetTenantDefaultMenuList().Select(u => new SysTenantMenu { Id=id+=100, TenantId=SqlSugarConst.DefaultTenantId, MenuId=u.MenuId });
     }
 }

+ 3 - 2
Admin.NET/Admin.NET.Core/SeedData/SysTenantSeedData.cs

@@ -18,10 +18,11 @@ public class SysTenantSeedData : ISqlSugarEntitySeedData<SysTenant>
     public IEnumerable<SysTenant> HasData()
     {
         var defaultDbConfig = App.GetOptions<DbConnectionOptions>().ConnectionConfigs[0];
-
+        var userList = new SysUserSeedData().HasData().ToList();
+        var admin = userList.First(u => u.Account == "admin");
         return new[]
         {
-            new SysTenant{ Id=SqlSugarConst.DefaultTenantId, AppId=SqlSugarConst.DefaultAppId, OrgId=SqlSugarConst.DefaultTenantId, UserId=1300000000111, Host=SqlSugarConst.DefaultTenantHost, TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysTenant{ Id=SqlSugarConst.DefaultTenantId, OrgId=SqlSugarConst.DefaultTenantId, UserId=admin.Id, Host="gitee.com", TenantType=TenantTypeEnum.Id, DbType=defaultDbConfig.DbType, Connection=defaultDbConfig.ConnectionString, ConfigId=SqlSugarConst.MainConfigId, Logo="/upload/logo.png", Title="Admin.NET", ViceTitle="Admin.NET", ViceDesc="站在巨人肩膀上的 .NET 通用权限开发框架", Watermark="Admin.NET", Copyright="Copyright \u00a9 2021-present Admin.NET All rights reserved.", Icp="省ICP备12345678号", IcpUrl="https://beian.miit.gov.cn", Remark="系统默认", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

+ 11 - 2
Admin.NET/Admin.NET.Core/SeedData/SysUserExtOrgSeedData.cs

@@ -17,10 +17,19 @@ public class SysUserExtOrgSeedData : ISqlSugarEntitySeedData<SysUserExtOrg>
     /// <returns></returns>
     public IEnumerable<SysUserExtOrg> HasData()
     {
+        var userList = new SysUserSeedData().HasData().ToList();
+        var orgList = new SysOrgSeedData().HasData().ToList();
+        var posList = new SysPosSeedData().HasData().ToList();
+        var admin = userList.First(u => u.Account == "admin");
+        var user3 = userList.First(u => u.Account == "user3");
+        var org1 = orgList.First(u => u.Name == "系统默认");
+        var org2 = orgList.First(u => u.Name == "开发部");
+        var pos1 = posList.First(u => u.Name == "部门经理");
+        var pos2 = posList.First(u => u.Name == "主任");
         return new[]
         {
-            new SysUserExtOrg{ Id=1300000000101, UserId=1300000000111, OrgId=1300000000202, PosId=1300000000106 },
-            new SysUserExtOrg{ Id=1300000000102, UserId=1300000000114, OrgId=1300000000302, PosId=1300000000108  }
+            new SysUserExtOrg{ Id=1300000000101, UserId=admin.Id, OrgId=org1.Id, PosId=pos1.Id },
+            new SysUserExtOrg{ Id=1300000000102, UserId=user3.Id, OrgId=org2.Id, PosId=pos2.Id  }
         };
     }
 }

+ 6 - 5
Admin.NET/Admin.NET.Core/SeedData/SysUserRoleSeedData.cs

@@ -17,13 +17,14 @@ public class SysUserRoleSeedData : ISqlSugarEntitySeedData<SysUserRole>
     /// <returns></returns>
     public IEnumerable<SysUserRole> HasData()
     {
+        var userList = new SysUserSeedData().HasData().ToList();
+        var roleList = new SysRoleSeedData().HasData().ToList();
         return new[]
         {
-            new SysUserRole{ Id=1300000000101, UserId=1300000000111, RoleId=1300000000101 },
-            new SysUserRole{ Id=1300000000102, UserId=1300000000112, RoleId=1300000000102 },
-            new SysUserRole{ Id=1300000000103, UserId=1300000000113, RoleId=1300000000103 },
-            new SysUserRole{ Id=1300000000104, UserId=1300000000114, RoleId=1300000000104 },
-            new SysUserRole{ Id=1300000000105, UserId=1300000000115, RoleId=1300000000105 },
+            new SysUserRole{ Id=1300000000101, UserId=userList.First(u => u.Account == "user1").Id, RoleId=roleList.First(u => u.Code == "sys_deptChild").Id },
+            new SysUserRole{ Id=1300000000102, UserId=userList.First(u => u.Account == "user2").Id, RoleId=roleList.First(u => u.Code == "sys_dept").Id },
+            new SysUserRole{ Id=1300000000103, UserId=userList.First(u => u.Account == "user3").Id, RoleId=roleList.First(u => u.Code == "sys_self").Id },
+            new SysUserRole{ Id=1300000000104, UserId=userList.First(u => u.Account == "user4").Id, RoleId=roleList.First(u => u.Code == "sys_define").Id },
         };
     }
 }

+ 7 - 7
Admin.NET/Admin.NET.Core/SeedData/SysUserSeedData.cs

@@ -18,16 +18,16 @@ public class SysUserSeedData : ISqlSugarEntitySeedData<SysUser>
     /// <returns></returns>
     public IEnumerable<SysUser> HasData()
     {
-        var encryptPassword = CryptogramUtil.Encrypt("123456");
-
+        var encryptPassword = CryptogramUtil.Encrypt(new SysConfigSeedData().HasData().First(u => u.Code == ConfigConst.SysPassword).Value);
+        var posList = new SysPosSeedData().HasData().ToList();
         return new[]
         {
             new SysUser{ Id=1300000000101, Account="superadmin", Password=encryptPassword, NickName="超级管理员", RealName="超级管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SuperAdmin, Remark="超级管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), TenantId=SqlSugarConst.DefaultTenantId },
-            new SysUser{ Id=1300000000111, Account="admin", Password=encryptPassword, NickName="系统管理员", RealName="系统管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SysAdmin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId, PosId=1300000000102, TenantId=SqlSugarConst.DefaultTenantId },
-            new SysUser{ Id=1300000000112, Account="user1", Password=encryptPassword, NickName="部门主管", RealName="部门主管", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门主管", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 1, PosId=1300000000108, TenantId=SqlSugarConst.DefaultTenantId },
-            new SysUser{ Id=1300000000113, Account="user2", Password=encryptPassword, NickName="部门职员", RealName="部门职员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 2, PosId=1300000000110, TenantId=SqlSugarConst.DefaultTenantId },
-            new SysUser{ Id=1300000000114, Account="user3", Password=encryptPassword, NickName="普通用户", RealName="普通用户", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 3, PosId=1300000000115, TenantId=SqlSugarConst.DefaultTenantId },
-            new SysUser{ Id=1300000000115, Account="user4", Password=encryptPassword, NickName="其他", RealName="其他", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.Member, Remark="会员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 4, PosId=1300000000116, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysUser{ Id=1300000000111, Account="admin", Password=encryptPassword, NickName="系统管理员", RealName="系统管理员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Male, AccountType=AccountTypeEnum.SysAdmin, Remark="系统管理员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId, PosId=posList[0].Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysUser{ Id=1300000000112, Account="user1", Password=encryptPassword, NickName="部门主管", RealName="部门主管", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门主管", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 1, PosId=posList[1].Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysUser{ Id=1300000000113, Account="user2", Password=encryptPassword, NickName="部门职员", RealName="部门职员", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="部门职员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 2, PosId=posList[2].Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysUser{ Id=1300000000114, Account="user3", Password=encryptPassword, NickName="普通用户", RealName="普通用户", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.NormalUser, Remark="普通用户", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 3, PosId=posList[3].Id, TenantId=SqlSugarConst.DefaultTenantId },
+            new SysUser{ Id=1300000000115, Account="user4", Password=encryptPassword, NickName="其他", RealName="其他", Phone="18012345678", Birthday=DateTime.Parse("2000-01-01"), Sex=GenderEnum.Female, AccountType=AccountTypeEnum.Member, Remark="会员", CreateTime=DateTime.Parse("2022-02-10 00:00:00"), OrgId=SqlSugarConst.DefaultTenantId + 4, PosId=posList[4].Id, TenantId=SqlSugarConst.DefaultTenantId },
         };
     }
 }

+ 0 - 173
Admin.NET/Admin.NET.Core/Service/Application/Dto/SysAppInput.cs

@@ -1,173 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 应用基础输入参数
-/// </summary>
-public class SysAppBaseInput
-{
-    /// <summary>
-    /// 主键Id
-    /// </summary>
-    public virtual long? Id { get; set; }
-
-    /// <summary>
-    /// 名称
-    /// </summary>
-    [Required(ErrorMessage = "名称不能为空")]
-    public virtual string Name { get; set; }
-
-    /// <summary>
-    /// 标题
-    /// </summary>
-    [Required(ErrorMessage = "标题不能为空")]
-    public virtual string Title { get; set; }
-
-    /// <summary>
-    /// 副标题
-    /// </summary>
-    [Required(ErrorMessage = "副标题不能为空")]
-    public virtual string ViceTitle { get; set; }
-
-    /// <summary>
-    /// 副描述
-    /// </summary>
-    public virtual string? ViceDesc { get; set; }
-
-    /// <summary>
-    /// 水印
-    /// </summary>
-    public virtual string? Watermark { get; set; }
-
-    /// <summary>
-    /// 版权信息
-    /// </summary>
-    public virtual string? Copyright { get; set; }
-
-    /// <summary>
-    /// ICP备案号
-    /// </summary>
-    public virtual string? Icp { get; set; }
-
-    /// <summary>
-    /// 排序
-    /// </summary>
-    [Required(ErrorMessage = "排序不能为空")]
-    public virtual int? OrderNo { get; set; }
-
-    /// <summary>
-    /// 备注
-    /// </summary>
-    public virtual string? Remark { get; set; }
-
-    /// <summary>
-    /// 图标
-    /// </summary>
-    public virtual string? Logo { get; set; }
-}
-
-/// <summary>
-/// 应用增加输入参数
-/// </summary>
-public class AddSysAppInput
-{
-    /// <summary>
-    /// 图标
-    /// </summary>
-    [Required(ErrorMessage = "Logo不能为空")]
-    public string Logo { get; set; }
-
-    /// <summary>
-    /// 名称
-    /// </summary>
-    [Required(ErrorMessage = "名称不能为空")]
-    public string Name { get; set; }
-
-    /// <summary>
-    /// 标题
-    /// </summary>
-    [Required(ErrorMessage = "标题不能为空")]
-    public string Title { get; set; }
-
-    /// <summary>
-    /// 副标题
-    /// </summary>
-    [Required(ErrorMessage = "副标题不能为空")]
-    public string ViceTitle { get; set; }
-
-    /// <summary>
-    /// 副描述
-    /// </summary>
-    [Required(ErrorMessage = "副描述不能为空")]
-    public string ViceDesc { get; set; }
-
-    /// <summary>
-    /// 水印
-    /// </summary>
-    [Required(ErrorMessage = "水印不能为空")]
-    public string Watermark { get; set; }
-
-    /// <summary>
-    /// 版权信息
-    /// </summary>
-    [Required(ErrorMessage = "版权信息不能为空")]
-    public string Copyright { get; set; }
-
-    /// <summary>
-    /// ICP备案号
-    /// </summary>
-    [Required(ErrorMessage = "备案号不能为空")]
-    public string Icp { get; set; }
-
-    /// <summary>
-    /// 排序
-    /// </summary>
-    [Required(ErrorMessage = "排序不能为空")]
-    public int OrderNo { get; set; } = 100;
-
-    /// <summary>
-    /// 备注
-    /// </summary>
-    [MaxLength(256, ErrorMessage = "备注字符长度不能超过256")]
-    public string Remark { get; set; }
-}
-
-/// <summary>
-/// 应用更新输入参数
-/// </summary>
-public class UpdateSysAppInput : AddSysAppInput
-{
-    /// <summary>
-    /// 主键Id
-    /// </summary>
-    [Required(ErrorMessage = "主键Id不能为空")]
-    public long Id { get; set; }
-}
-
-/// <summary>
-/// 授权应用菜单
-/// </summary>
-public class UpdateAppMenuInput : BaseIdInput
-{
-    /// <summary>
-    /// 菜单Id集合
-    /// </summary>
-    public List<long> MenuIdList { get; set; }
-}
-
-/// <summary>
-/// 租户iId
-/// </summary>
-public class ChangeAppInput : BaseIdInput
-{
-    /// <summary>
-    /// 租户Id
-    /// </summary>
-    [Required(ErrorMessage = "租户不能为空")]
-    public long TenantId { get; set; }
-}

+ 0 - 103
Admin.NET/Admin.NET.Core/Service/Application/Dto/SysAppOutput.cs

@@ -1,103 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 应用输出参数
-/// </summary>
-public class SysAppOutput
-{
-    /// <summary>
-    /// 主键Id
-    /// </summary>
-    public long Id { get; set; }
-
-    /// <summary>
-    /// 名称
-    /// </summary>
-    public string Name { get; set; }
-
-    /// <summary>
-    /// 图标
-    /// </summary>
-    public string? Logo { get; set; }
-
-    /// <summary>
-    /// 标题
-    /// </summary>
-    public string Title { get; set; }
-
-    /// <summary>
-    /// 副标题
-    /// </summary>
-    public string ViceTitle { get; set; }
-
-    /// <summary>
-    /// 副描述
-    /// </summary>
-    public string? ViceDesc { get; set; }
-
-    /// <summary>
-    /// 水印
-    /// </summary>
-    public string? Watermark { get; set; }
-
-    /// <summary>
-    /// 版权信息
-    /// </summary>
-    public string? Copyright { get; set; }
-
-    /// <summary>
-    /// ICP备案号
-    /// </summary>
-    public string? Icp { get; set; }
-
-    /// <summary>
-    /// 排序
-    /// </summary>
-    public int OrderNo { get; set; }
-
-    /// <summary>
-    /// 备注
-    /// </summary>
-    public string? Remark { get; set; }
-
-    /// <summary>
-    /// 创建时间
-    /// </summary>
-    public DateTime? CreateTime { get; set; }
-
-    /// <summary>
-    /// 更新时间
-    /// </summary>
-    public DateTime? UpdateTime { get; set; }
-
-    /// <summary>
-    /// 创建者Id
-    /// </summary>
-    public long? CreateUserId { get; set; }
-
-    /// <summary>
-    /// 创建者姓名
-    /// </summary>
-    public string? CreateUserName { get; set; }
-
-    /// <summary>
-    /// 修改者Id
-    /// </summary>
-    public long? UpdateUserId { get; set; }
-
-    /// <summary>
-    /// 修改者姓名
-    /// </summary>
-    public string? UpdateUserName { get; set; }
-
-    /// <summary>
-    /// 软删除
-    /// </summary>
-    public bool IsDelete { get; set; }
-}

+ 0 - 192
Admin.NET/Admin.NET.Core/Service/Application/SysAppService.cs

@@ -1,192 +0,0 @@
-// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
-//
-// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
-//
-// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
-
-namespace Admin.NET.Core.Service;
-
-/// <summary>
-/// 系统应用服务 🧩
-/// </summary>
-[ApiDescriptionSettings(Name = "SysApp", Order = 495)]
-public class SysAppService : IDynamicApiController, ITransient
-{
-    private readonly SqlSugarRepository<SysAppMenu> _sysAppMenuRep;
-    private readonly SqlSugarRepository<SysApp> _sysAppRep;
-    private readonly SysAuthService _sysAuthService;
-    private readonly UserManager _userManager;
-
-    public SysAppService(SqlSugarRepository<SysApp> sysAppRep, SqlSugarRepository<SysAppMenu> sysAppMenuRep, SysAuthService sysAuthService, UserManager userManager)
-    {
-        _sysAppRep = sysAppRep;
-        _userManager = userManager;
-        _sysAppMenuRep = sysAppMenuRep;
-        _sysAuthService = sysAuthService;
-    }
-
-    /// <summary>
-    /// 分页查询应用 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [DisplayName("分页查询应用")]
-    [ApiDescriptionSettings(Name = "Page"), HttpPost]
-    public async Task<SqlSugarPagedList<SysAppOutput>> Page(BasePageInput input)
-    {
-        input.Keyword = input.Keyword?.Trim();
-        var query = _sysAppRep.AsQueryable()
-            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword) ||
-               u.Title.Contains(input.Keyword) || u.ViceTitle.Contains(input.Keyword) ||
-               u.ViceDesc.Contains(input.Keyword) || u.Remark.Contains(input.Keyword))
-            .OrderBy(u => new { u.OrderNo, u.Id })
-            .Select<SysAppOutput>();
-        return await query.OrderBuilder(input).ToPagedListAsync(input.Page, input.PageSize);
-    }
-
-    /// <summary>
-    /// 增加应用 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [DisplayName("增加应用")]
-    [ApiDescriptionSettings(Name = "Add"), HttpPost]
-    public async Task<long> Add(AddSysAppInput input)
-    {
-        var entity = input.Adapt<SysApp>();
-        return await _sysAppRep.InsertAsync(entity) ? entity.Id : 0;
-    }
-
-    /// <summary>
-    /// 更新应用 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [DisplayName("更新应用")]
-    [ApiDescriptionSettings(Name = "Update"), HttpPost]
-    public async Task Update(UpdateSysAppInput input)
-    {
-        _ = await _sysAppRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-
-        var entity = input.Adapt<SysApp>();
-        await _sysAppRep.AsUpdateable(entity).ExecuteCommandAsync();
-    }
-
-    /// <summary>
-    /// 删除应用 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [DisplayName("删除应用")]
-    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
-    public async Task Delete(BaseIdInput input)
-    {
-        var entity = await _sysAppRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-
-        // 禁止删除存在关联租户的应用
-        if (await _sysAppRep.Context.Queryable<SysTenant>().AnyAsync(u => u.AppId == input.Id)) throw Oops.Oh(ErrorCodeEnum.A1001);
-
-        // 禁止删除存在关联菜单的应用
-        if (await _sysAppMenuRep.AsQueryable().AnyAsync(u => u.AppId == input.Id)) throw Oops.Oh(ErrorCodeEnum.A1002);
-
-        await _sysAppRep.DeleteAsync(entity);
-    }
-
-    /// <summary>
-    /// 获取授权菜单 🔖
-    /// </summary>
-    /// <param name="id"></param>
-    /// <returns></returns>
-    [UnitOfWork]
-    [DisplayName("获取授权菜单")]
-    [ApiDescriptionSettings(Name = "GrantMenu"), HttpGet]
-    public async Task<List<long>> GrantMenu([FromQuery] long id)
-    {
-        return await _sysAppMenuRep.AsQueryable().Where(u => u.AppId == id).Select(u => u.MenuId).ToListAsync();
-    }
-
-    /// <summary>
-    /// 授权菜单 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [UnitOfWork]
-    [DisplayName("授权菜单")]
-    [ApiDescriptionSettings(Name = "GrantMenu"), HttpPost]
-    public async Task GrantMenu(UpdateAppMenuInput input)
-    {
-        input.MenuIdList ??= new();
-
-        await _sysAppMenuRep.DeleteAsync(u => u.AppId == input.Id);
-
-        var list = input.MenuIdList.Select(id => new SysAppMenu { AppId = input.Id, MenuId = id }).ToList();
-
-        await _sysAppMenuRep.InsertRangeAsync(list);
-
-        // 清除应用下其他模块越权的授权数据,包括角色菜单,用户收藏菜单
-        var tenantIds = await _sysAppRep.Context.Queryable<SysTenant>().Where(u => u.AppId == input.Id).Select(u => u.Id).ToListAsync();
-        var roleIds = await _sysAppRep.Context.Queryable<SysRole>().Where(u => tenantIds.Contains((long)u.TenantId)).Select(u => u.Id).ToListAsync();
-        var userIds = await _sysAppRep.Context.Queryable<SysUser>().Where(u => tenantIds.Contains((long)u.TenantId)).Select(u => u.Id).ToListAsync();
-        await _sysAppRep.Context.Deleteable<SysRoleMenu>().Where(u => roleIds.Contains(u.RoleId) && !input.MenuIdList.Contains(u.MenuId)).ExecuteCommandAsync();
-        await _sysAppRep.Context.Deleteable<SysUserMenu>().Where(u => userIds.Contains(u.UserId) && !input.MenuIdList.Contains(u.MenuId)).ExecuteCommandAsync();
-    }
-
-    /// <summary>
-    /// 获取切换应用数据 🔖
-    /// </summary>
-    /// <returns></returns>
-    [UnitOfWork]
-    [DisplayName("切换应用")]
-    [ApiDescriptionSettings(Name = "ChangeApp"), HttpGet]
-    public async Task<dynamic> GetChangeAppData()
-    {
-        var list = await _sysAppRep.AsQueryable().Includes(u => u.TenantList).ToListAsync();
-        return new
-        {
-            _userManager.AppId,
-            _userManager.TenantId,
-            SelectList = list.Where(u => u.TenantList.Count > 0).Select(u => new
-            {
-                u.Id,
-                Value = u.Id,
-                Label = u.Name,
-                Children = u.TenantList.Select(t => new
-                {
-                    t.Id,
-                    Value = t.Id,
-                    Label = t.Host ?? (t.Id + ""),
-                })
-            })
-        };
-    }
-
-    /// <summary>
-    /// 切换应用 🔖
-    /// </summary>
-    /// <param name="input"></param>
-    /// <returns></returns>
-    [UnitOfWork]
-    [DisplayName("切换应用")]
-    [ApiDescriptionSettings(Name = "ChangeApp"), HttpPost]
-    public async Task<LoginOutput> ChangeApp(ChangeAppInput input)
-    {
-        _ = await _sysAppRep.Context.Queryable<SysTenant>().FirstAsync(u => u.Id == input.TenantId) ?? throw Oops.Oh(ErrorCodeEnum.Z1003);
-        _ = await _sysAppRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-
-        var user = await _sysAppRep.Context.Queryable<SysUser>().FirstAsync(u => u.Id == _userManager.UserId);
-        user.TenantId = input.TenantId;
-
-        return await _sysAuthService.CreateToken(user, input.Id);
-    }
-
-    /// <summary>
-    /// 获取当前应用信息
-    /// </summary>
-    /// <returns></returns>
-    [NonAction]
-    public async Task<SysApp> GetCurrentAppInfo()
-    {
-        var appId = _userManager.AppId > 0 ? _userManager.AppId : SqlSugarConst.DefaultAppId;
-        return await _sysAppRep.GetFirstAsync(u => u.Id == appId) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-    }
-}

+ 60 - 6
Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginInput.cs

@@ -26,10 +26,10 @@ public class LoginInput
     public string Password { get; set; }
 
     /// <summary>
-    /// 租户域名
+    /// 租户
     /// </summary>
-    [Required(ErrorMessage = "租户域名不能为空")]
-    public string? Host { get; set; }
+    [Required(ErrorMessage = "租户不能为空")]
+    public long? TenantId { get; set; }
 
     /// <summary>
     /// 验证码Id
@@ -60,8 +60,62 @@ public class LoginPhoneInput
     public string Code { get; set; }
 
     /// <summary>
-    /// 租户域名
+    /// 租户
     /// </summary>
-    [Required(ErrorMessage = "租户域名不能为空")]
-    public string? Host { get; set; }
+    [Required(ErrorMessage = "租户不能为空")]
+    public long? TenantId { get; set; }
+}
+
+/// <summary>
+/// 用户注册输入参数
+/// </summary>
+public class UserRegistrationInput
+{
+    /// <summary>
+    /// 真实姓名
+    /// </summary>
+    [Required(ErrorMessage = "真实姓名不能为空"), MinLength(2, ErrorMessage = "真实姓名不能少于2个字符")]
+    public string RealName { get; set; }
+    
+    /// <summary>
+    /// 账号
+    /// </summary>
+    [Required(ErrorMessage = "账号不能为空"), MinLength(6, ErrorMessage = "账号不能少于6个字符")]
+    public string Account { get; set; }
+    
+    /// <summary>
+    /// 手机号码
+    /// </summary>
+    /// <example>admin</example>
+    [Required(ErrorMessage = "手机号码不能为空")]
+    [DataValidation(ValidationTypes.PhoneNumber, ErrorMessage = "手机号码不正确")]
+    public string Phone { get; set; }
+    
+    /// <summary>
+    /// 验证码
+    /// </summary>
+    /// <example>123456</example>
+    [Required(ErrorMessage = "验证码不能为空")]
+    public string Code { get; set; }
+    
+    /// <summary>
+    /// 验证码Id
+    /// </summary>
+    public long CodeId { get; set; }
+    
+    /// <summary>
+    /// 租户
+    /// </summary>
+    [Required(ErrorMessage = "租户不能为空")]
+    public long TenantId { get; set; }
+    
+    /// <summary>
+    /// 密码
+    /// </summary>
+    public string Password { get; set; }
+    
+    /// <summary>
+    /// 注册方案
+    /// </summary>
+    public long WayId { get; set; }
 }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Auth/Dto/SysLdapInput.cs

@@ -15,6 +15,11 @@ public class SysLdapInput : BasePageInput
     /// 主机
     /// </summary>
     public string? Host { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddSysLdapInput : SysLdap

+ 87 - 60
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -6,6 +6,7 @@
 
 using Furion.SpecificationDocument;
 using Lazy.Captcha.Core;
+using NewLife.Reflection;
 
 namespace Admin.NET.Core.Service;
 
@@ -53,9 +54,6 @@ public class SysAuthService : IDynamicApiController, ITransient
     [DisplayName("账号密码登录")]
     public virtual async Task<LoginOutput> Login([Required] LoginInput input)
     {
-        //// 可以根据域名获取具体租户
-        //var host = _httpContextAccessor.HttpContext.Request.Host;
-
         // 判断密码错误次数(缓存30分钟)
         var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}";
         var passwordErrorTimes = _sysCacheService.Get<int>(keyPasswordErrorTimes);
@@ -64,11 +62,8 @@ public class SysAuthService : IDynamicApiController, ITransient
         if (passwordMaxErrorTimes < 1) passwordMaxErrorTimes = 10;
         if (passwordErrorTimes > passwordMaxErrorTimes) throw Oops.Oh(ErrorCodeEnum.D1027);
 
-        // 判断是否开启验证码,其校验验证码
-        if (await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysCaptcha) && !_captcha.Validate(input.CodeId.ToString(), input.Code)) throw Oops.Oh(ErrorCodeEnum.D0008);
-
         // 获取登录租户和用户
-        var (tenant, user) = await GetLoginUserAndTenant(input.Host, account: input.Account);
+        var (tenant, user) = await GetLoginUserAndTenant(input.TenantId, codeId: input.CodeId, code: input.Code, account: input.Account);
 
         // 账号是否被冻结
         if (user.Status == StatusEnum.Disable) throw Oops.Oh(ErrorCodeEnum.D1017);
@@ -93,59 +88,41 @@ public class SysAuthService : IDynamicApiController, ITransient
         // 登录成功则清空密码错误次数
         _sysCacheService.Remove(keyPasswordErrorTimes);
 
-        return await CreateToken(user, tenant.AppId);
+        return await CreateToken(user);
     }
 
     /// <summary>
     /// 获取登录租户和用户
     /// </summary>
-    /// <param name="host"></param>
+    /// <param name="tenantId"></param>
+    /// <param name="codeId"></param>
+    /// <param name="code"></param>
     /// <param name="account"></param>
     /// <param name="phone"></param>
     /// <returns></returns>
     [NonAction]
-    public async Task<(SysTenant tenant, SysUser user)> GetLoginUserAndTenant(string host, string account = null, string phone = null)
+    public async Task<(SysTenant tenant, SysUser user)> GetLoginUserAndTenant(long? tenantId, long codeId = 0, string code = null, string account = null, string phone = null)
     {
-        // 是否租户隔离登录验证
-        var isTenantHostLogin = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysTenantHostLogin);
-
-        SysUser user;
-        SysTenant tenant;
+        // 如果租户为空,使用默认租户
+        tenantId ??= SqlSugarConst.DefaultTenantId;
+        var tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Id == tenantId);
+
+        // 校验验证码
+        if (tenant?.Captcha == YesNoEnum.Y && !_captcha.Validate(codeId.ToString(), code)) throw Oops.Oh(ErrorCodeEnum.D0008);
+
+        // 租户是否存在或已禁用
+        if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
+        
+        // 判断账号是否存在
+        var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
+            .Where(u => u.AccountType == AccountTypeEnum.SuperAdmin || u.TenantId == tenantId)
+            .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
+            .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
+            .FirstAsync();
+        _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
 
-        // 租户隔离登录
-        if (isTenantHostLogin)
-        {
-            // 若租户域名为空或为本地域名,则取默认租户域名
-            if (string.IsNullOrWhiteSpace(host) || host.StartsWith("localhost")) host = SqlSugarConst.DefaultTenantHost;
-
-            // 租户是否存在或已禁用
-            tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Host == host.ToLower());
-            if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
-
-            // 根据入参类型、租户查询登录用户
-            user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
-                .Where(u => u.TenantId == tenant.Id || u.AccountType == AccountTypeEnum.SuperAdmin)
-                .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
-                .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
-                .FirstAsync();
-            _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
-
-            // 若登录的是超级管理员,则引用当前绑定的租户,这样登陆后操作的租户数据会与该租户关联
-            if (user.AccountType == AccountTypeEnum.SuperAdmin) user.TenantId = tenant.Id;
-        }
-        else
-        {
-            // 根据入参类型查询登录用户
-            user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter()
-                .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account))
-                .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone))
-                .FirstAsync();
-            _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
-
-            // 租户是否存在或已禁用
-            tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Id == user.TenantId);
-            if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003);
-        }
+        // 如果是超级管理员,则引用登录选择的租户进入系统
+        if (user.AccountType == AccountTypeEnum.SuperAdmin) user.TenantId = tenantId;
 
         return (tenant, user);
     }
@@ -229,19 +206,18 @@ public class SysAuthService : IDynamicApiController, ITransient
         App.GetRequiredService<SysSmsService>().VerifyCode(new SmsVerifyCodeInput { Phone = input.Phone, Code = input.Code });
 
         // 获取登录租户和用户
-        var (tenant, user) = await GetLoginUserAndTenant(input.Host, phone: input.Phone);
+        var (_, user) = await GetLoginUserAndTenant(input.TenantId, phone: input.Phone);
 
-        return await CreateToken(user, tenant.AppId);
+        return await CreateToken(user);
     }
 
     /// <summary>
     /// 生成Token令牌 🔖
     /// </summary>
-    /// <param name="user"></param>
-    /// <param name="appId"></param>
+    /// <param name="user"></param>\
     /// <returns></returns>
     [NonAction]
-    internal virtual async Task<LoginOutput> CreateToken(SysUser user, long appId)
+    internal virtual async Task<LoginOutput> CreateToken(SysUser user)
     {
         // 单用户登录
         await _sysOnlineUserService.SingleLogin(user.Id);
@@ -250,7 +226,6 @@ public class SysAuthService : IDynamicApiController, ITransient
         var tokenExpire = await _sysConfigService.GetTokenExpire();
         var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
         {
-            { ClaimConst.AppId, appId },
             { ClaimConst.UserId, user.Id },
             { ClaimConst.TenantId, user.TenantId },
             { ClaimConst.Account, user.Account },
@@ -309,7 +284,7 @@ public class SysAuthService : IDynamicApiController, ITransient
         var roleIds = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysUserRole>>().AsQueryable()
             .Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync();
         // 获取水印文字(若系统水印为空则全局为空)
-        var watermarkText = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysWebWatermark);
+        var watermarkText = (await _sysUserRep.Context.Queryable<SysTenant>().FirstAsync(u => u.Id == user.TenantId))?.Watermark;
         if (!string.IsNullOrWhiteSpace(watermarkText))
             watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true)}-{DateTime.Now}";
         return new LoginUserOutput
@@ -373,6 +348,41 @@ public class SysAuthService : IDynamicApiController, ITransient
         return new { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds };
     }
 
+    /// <summary>
+    /// 用户注册 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [UnitOfWork]
+    [AllowAnonymous]
+    [HttpPost, ApiDescriptionSettings(Description = "用户注册", DisableInherite = true)]
+    public async Task UserRegistration(UserRegistrationInput input)
+    {
+        // 校验验证码
+        if (!_captcha.Validate(input.CodeId.ToString(), input.Code)) throw Oops.Oh(ErrorCodeEnum.D0008);
+        _captcha.Generate(input.CodeId.ToString());
+        
+        // 判断租户是否有效且启用注册功能
+        var tenant = await _sysUserRep.Context.Queryable<SysTenant>().FirstAsync(u => u.Id == input.TenantId && u.Status == StatusEnum.Enable);
+        if (tenant?.EnableReg != YesNoEnum.Y) throw Oops.Oh(ErrorCodeEnum.D1034);
+        
+        // 查找注册方案
+        var wayId = input.WayId <= 0 ? tenant.RegWayId : input.WayId;
+        var regWay = await _sysUserRep.Context.Queryable<SysUserRegWay>().FirstAsync(u => u.Id == wayId) ?? throw Oops.Oh(ErrorCodeEnum.D1035);
+
+        var addUserInput = new AddUserInput
+        {
+            AccountType = regWay.AccountType,
+            NickName = "注册用户-" + input.Account,
+            OrgId = regWay.OrgId,
+            PosId = regWay.PosId,
+            TenantId = input.TenantId,
+            RoleIdList = new List<long> { regWay.RoleId },
+        };
+        addUserInput.Copy(input);
+        await App.GetService<SysUserService>().RegisterUser(addUserInput);
+    }
+
     /// <summary>
     /// Swagger登录检查 🔖
     /// </summary>
@@ -395,24 +405,41 @@ public class SysAuthService : IDynamicApiController, ITransient
     [ApiDescriptionSettings(Description = "Swagger登录提交", DisableInherite = true)]
     public async Task<int> SwaggerSubmitUrl([FromForm] SpecificationAuth auth)
     {
+        // 尝试从发起请求页的地址栏中获取租户id,为空则使用默认租户
+        var tenantIdStr = Regex.Match(App.HttpContext.Request.Headers.Referer.ToString() ?? "", @"(?<=t=)(\d+)").Value;
+        var tenantId = string.IsNullOrWhiteSpace(tenantIdStr)
+            ? SqlSugarConst.DefaultTenantId
+            : long.Parse(tenantIdStr);
         try
         {
-            _sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}", false);
+            // 关闭验证码验证
+            await _sysUserRep.Context
+                .Updateable(new SysTenant { Captcha = YesNoEnum.N })
+                .UpdateColumns(u => u.Captcha)
+                .Where(u => u.Id == tenantId)
+                .ExecuteCommandAsync();
 
             await Login(new LoginInput
             {
                 Account = auth.UserName,
                 Password = CryptogramUtil.SM2Encrypt(auth.Password),
-                Host = SqlSugarConst.DefaultTenantHost
+                TenantId = tenantId
             });
 
-            _sysCacheService.Remove($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}");
-
             return 200;
         }
         catch (Exception)
         {
             return 401;
         }
+        finally
+        {
+            // 开启验证码验证
+            await _sysUserRep.Context
+                .Updateable(new SysTenant { Captcha = YesNoEnum.N })
+                .UpdateColumns(u => u.Captcha)
+                .Where(u => u.Id == tenantId)
+                .ExecuteCommandAsync();
+        }
     }
 }

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Auth/SysLdapService.cs

@@ -15,10 +15,12 @@ namespace Admin.NET.Core;
 public class SysLdapService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysLdap> _sysLdapRep;
+    private readonly UserManager _userManager;
 
-    public SysLdapService(SqlSugarRepository<SysLdap> sysLdapRep)
+    public SysLdapService(SqlSugarRepository<SysLdap> sysLdapRep, UserManager userManager)
     {
         _sysLdapRep = sysLdapRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -30,6 +32,7 @@ public class SysLdapService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysLdap>> Page(SysLdapInput input)
     {
         return await _sysLdapRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Host.Contains(input.Keyword.Trim()))
             .WhereIF(!string.IsNullOrWhiteSpace(input.Host), u => u.Host.Contains(input.Host.Trim()))
             .OrderBy(u => u.CreateTime, OrderByType.Desc)

+ 0 - 8
Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs

@@ -475,15 +475,12 @@ public class SysCodeGenService : IDynamicApiController, ITransient
         await DeleteMenuTree(title, pid == 0 ? MenuTypeEnum.Dir : MenuTypeEnum.Menu);
 
         var parentMenuPath = "";
-        var appId = _userManager.AppId;
-        var appMenuList = new List<SysAppMenu>();
         var lowerClassName = className[..1].ToLower() + className[1..];
         if (pid == 0)
         {
             // 新增目录,并记录Id
             var dirMenu = new SysMenu { Pid = 0, Title = title, Type = MenuTypeEnum.Dir, Icon = "robot", Path = "/" + className.ToLower(), Component = "Layout" };
             pid = (await _db.Insertable(dirMenu).ExecuteReturnEntityAsync()).Id;
-            appMenuList.Add(new SysAppMenu { AppId = appId, MenuId = pid });
         }
         else
         {
@@ -494,7 +491,6 @@ public class SysCodeGenService : IDynamicApiController, ITransient
         // 新增菜单,并记录Id
         var rootMenu = new SysMenu { Pid = pid, Title = title, Type = MenuTypeEnum.Menu, Icon = menuIcon, Path = $"{parentMenuPath}/{className.ToLower()}", Component = $"/{pagePath}/{lowerClassName}/index" };
         pid = (await _db.Insertable(rootMenu).ExecuteReturnEntityAsync()).Id;
-        appMenuList.Add(new SysAppMenu { AppId = appId, MenuId = pid });
 
         var orderNo = 100;
         var menuList = new List<SysMenu>
@@ -518,10 +514,6 @@ public class SysCodeGenService : IDynamicApiController, ITransient
             menuList.Add(new SysMenu { Title = $"上传{column.ColumnComment}", Permission = $"{lowerClassName}:upload{column.PropertyName}", Pid = pid, Type = MenuTypeEnum.Btn, OrderNo = orderNo += 10 });
 
         await _db.Insertable(menuList).ExecuteCommandAsync();
-
-        // 新增应用菜单关联
-        appMenuList.AddRange(menuList.Select(u => new SysAppMenu { AppId = appId, MenuId = u.Id }));
-        await _db.Insertable(appMenuList).ExecuteCommandAsync();
     }
 
     /// <summary>

+ 21 - 11
Admin.NET/Admin.NET.Core/Service/Config/Dto/InfoInput.cs

@@ -14,62 +14,72 @@ public class InfoSaveInput
     /// <summary>
     /// 系统图标(Data URI scheme base64 编码)
     /// </summary>
-    public string SysLogoBase64 { get; set; }
+    public string LogoBase64 { get; set; }
 
     /// <summary>
     /// 系统图标文件名
     /// </summary>
-    public string SysLogoFileName { get; set; }
+    public string LogoFileName { get; set; }
 
     /// <summary>
     /// 系统主标题
     /// </summary>
     [Required(ErrorMessage = "系统主标题不能为空")]
-    public string SysTitle { get; set; }
+    public string Title { get; set; }
 
     /// <summary>
     /// 系统副标题
     /// </summary>
     [Required(ErrorMessage = "系统副标题不能为空")]
-    public string SysViceTitle { get; set; }
+    public string ViceTitle { get; set; }
 
     /// <summary>
     /// 系统描述
     /// </summary>
     [Required(ErrorMessage = "系统描述不能为空")]
-    public string SysViceDesc { get; set; }
+    public string ViceDesc { get; set; }
 
     /// <summary>
     /// 水印内容
     /// </summary>
     [Required(ErrorMessage = "水印内容不能为空")]
-    public string SysWatermark { get; set; }
+    public string Watermark { get; set; }
 
     /// <summary>
     /// 版权说明
     /// </summary>
     [Required(ErrorMessage = "版权说明不能为空")]
-    public string SysCopyright { get; set; }
+    public string Copyright { get; set; }
 
     /// <summary>
     /// ICP备案号
     /// </summary>
     [Required(ErrorMessage = "ICP备案号不能为空")]
-    public string SysIcp { get; set; }
+    public string Icp { get; set; }
 
     /// <summary>
     /// ICP地址
     /// </summary>
     [Required(ErrorMessage = "ICP地址不能为空")]
-    public string SysIcpUrl { get; set; }
+    public string IcpUrl { get; set; }
+    
+    /// <summary>
+    /// 启用注册功能
+    /// </summary>
+    public YesNoEnum EnableReg { get; set; }
 
     /// <summary>
     /// 登录二次验证
     /// </summary>
-    public bool? SysSecondVer { get; set; }
+    public YesNoEnum SecondVer { get; set; }
 
     /// <summary>
     /// 图形验证码
     /// </summary>
-    public bool? SysCaptcha { get; set; }
+    public YesNoEnum Captcha { get; set; }
+    
+    /// <summary>
+    /// 默认注册方案Id
+    /// </summary>
+    public virtual long RegWayId { get; set; }
 }

+ 31 - 69
Admin.NET/Admin.NET.Core/Service/Config/SysConfigService.cs

@@ -4,6 +4,9 @@
 //
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
+using Microsoft.AspNetCore.Mvc.Rendering;
+using NewLife.Reflection;
+
 namespace Admin.NET.Core.Service;
 
 /// <summary>
@@ -221,12 +224,12 @@ public class SysConfigService : IDynamicApiController, ITransient
     [DisplayName("批量更新参数配置值")]
     public async Task BatchUpdateConfig(List<BatchConfigInput> input)
     {
-        foreach (var Config in input)
+        foreach (var config in input)
         {
-            var info = await _sysConfigRep.GetFirstAsync(c => c.Code == Config.Code);
+            var info = await _sysConfigRep.GetFirstAsync(c => c.Code == config.Code);
             if (info == null) continue;
 
-            await _sysConfigRep.AsUpdateable().SetColumns(u => u.Value == Config.Value).Where(u => u.Code == Config.Code).ExecuteCommandAsync();
+            await _sysConfigRep.AsUpdateable().SetColumns(u => u.Value == config.Value).Where(u => u.Code == config.Code).ExecuteCommandAsync();
             Remove(info);
         }
     }
@@ -240,31 +243,29 @@ public class SysConfigService : IDynamicApiController, ITransient
     [DisplayName("获取系统信息")]
     public async Task<dynamic> GetSysInfo()
     {
-        // var sysLogo = await GetConfigValue<string>(ConfigConst.SysWebLogo);
-        // var sysTitle = await GetConfigValue<string>(ConfigConst.SysWebTitle);
-        // var sysViceTitle = await GetConfigValue<string>(ConfigConst.SysWebViceTitle);
-        // var sysViceDesc = await GetConfigValue<string>(ConfigConst.SysWebViceDesc);
-        // var sysWatermark = await GetConfigValue<string>(ConfigConst.SysWebWatermark);
-        // var sysCopyright = await GetConfigValue<string>(ConfigConst.SysWebCopyright);
-        // var sysIcp = await GetConfigValue<string>(ConfigConst.SysWebIcp);
-        var app = await App.GetRequiredService<SysAppService>().GetCurrentAppInfo();
-
-        var sysIcpUrl = await GetConfigValue<string>(ConfigConst.SysWebIcpUrl);
-        var sysSecondVer = await GetConfigValue<bool>(ConfigConst.SysSecondVer);
-        var sysCaptcha = await GetConfigValue<bool>(ConfigConst.SysCaptcha);
+        var tenant = await App.GetService<SysTenantService>().GetCurrentTenant();
+        tenant ??= await _sysConfigRep.Context.Queryable<SysTenant>().FirstAsync(u => u.Id == SqlSugarConst.DefaultTenantId);
+        _ = tenant ?? throw Oops.Oh(ErrorCodeEnum.D1002);
 
+        var wayList = await _sysConfigRep.Context.Queryable<SysUserRegWay>().ClearFilter()
+            .Where(u => u.TenantId == tenant.Id)
+            .Select(u => new { Label = u.Name, Value = u.Id })
+            .ToListAsync();
         return new
         {
-            SysLogo = app.Logo,
-            SysTitle = app.Title,
-            SysViceTitle = app.ViceTitle,
-            SysViceDesc = app.ViceDesc,
-            SysWatermark = app.Watermark,
-            SysCopyright = app.Copyright,
-            SysIcp = app.Icp,
-            SysIcpUrl = sysIcpUrl,
-            SysSecondVer = sysSecondVer,
-            SysCaptcha = sysCaptcha
+            tenant.Logo,
+            tenant.Title,
+            tenant.ViceTitle,
+            tenant.ViceDesc,
+            tenant.Watermark,
+            tenant.Copyright,
+            tenant.Icp,
+            tenant.IcpUrl,
+            tenant.RegWayId,
+            tenant.EnableReg,
+            tenant.SecondVer,
+            tenant.Captcha,
+            WayList = wayList
         };
     }
 
@@ -276,51 +277,12 @@ public class SysConfigService : IDynamicApiController, ITransient
     [DisplayName("保存系统信息")]
     public async Task SaveSysInfo(InfoSaveInput input)
     {
-        // logo 不为空才保存
-        var app = await App.GetRequiredService<SysAppService>().GetCurrentAppInfo();
-        if (!string.IsNullOrEmpty(input.SysLogoBase64))
-        {
-            // 旧图标文件相对路径
-            var oldSysLogoRelativeFilePath = app.Logo ?? "";
-            var oldSysLogoAbsoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, oldSysLogoRelativeFilePath.TrimStart('/'));
-
-            var groups = Regex.Match(input.SysLogoBase64, @"data:image/(?<type>.+?);base64,(?<data>.+)").Groups;
-            //var type = groups["type"].Value;
-            var base64Data = groups["data"].Value;
-            var binData = Convert.FromBase64String(base64Data);
-            // 根据文件名取扩展名
-            var ext = string.IsNullOrWhiteSpace(input.SysLogoFileName) ? ".png" : Path.GetExtension(input.SysLogoFileName);
-            // 本地图标保存路径
-            var path = "upload";
-            var fileName = $"{app.ViceTitle}-logo{ext}".ToLower();
-            var absoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, path, fileName);
-
-            // 删除已存在文件
-            if (File.Exists(oldSysLogoAbsoluteFilePath)) File.Delete(oldSysLogoAbsoluteFilePath);
-
-            // 创建文件夹
-            var absoluteFileDir = Path.GetDirectoryName(absoluteFilePath);
-            if (!Directory.Exists(absoluteFileDir)) Directory.CreateDirectory(absoluteFileDir);
-
-            // 保存图标文件
-            await File.WriteAllBytesAsync(absoluteFilePath, binData);
-
-            // 保存图标配置
-            app.Logo = $"/{path}/{fileName}";
-        }
-
-        app.Title = input.SysTitle;
-        app.ViceTitle = input.SysViceTitle;
-        app.ViceDesc = input.SysViceDesc;
-        app.Watermark = input.SysWatermark;
-        app.Copyright = input.SysCopyright;
-        app.Icp = input.SysIcp;
-
-        await _sysConfigRep.Context.Updateable(app).ExecuteCommandAsync();
+        var tenant = await App.GetService<SysTenantService>().GetCurrentTenant() ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        if (!string.IsNullOrEmpty(input.LogoBase64)) App.GetService<SysTenantService>().SetLogoUrl(tenant, input.LogoBase64, input.LogoFileName);
 
-        await UpdateConfigValue(ConfigConst.SysWebIcpUrl, input.SysIcpUrl);
-        await UpdateConfigValue(ConfigConst.SysSecondVer, (input.SysSecondVer ?? false).ToString());
-        await UpdateConfigValue(ConfigConst.SysCaptcha, (input.SysCaptcha ?? true).ToString());
+        tenant.Copy(input);
+        tenant.RegWayId = input.EnableReg == YesNoEnum.Y ? input.RegWayId : null;
+        await _sysConfigRep.Context.Updateable(tenant).ExecuteCommandAsync();
     }
 
     private void Remove(SysConfig config)

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/Dict/Dto/DictDataInput.cs

@@ -21,7 +21,7 @@ public class PageDictDataInput : BasePageInput
     /// 字典文本
     /// </summary>
     public string Label { get; set; }
-
+    
     /// <summary>
     /// 租户Id
     /// </summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/Dict/Dto/DictTypeInput.cs

@@ -21,7 +21,7 @@ public class PageDictTypeInput : BasePageInput
     /// 编码
     /// </summary>
     public string Code { get; set; }
-
+    
     /// <summary>
     /// 租户Id
     /// </summary>

+ 4 - 4
Admin.NET/Admin.NET.Core/Service/Dict/SysDictDataService.cs

@@ -38,7 +38,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
             .Where(u => u.DictTypeId == input.DictTypeId)
             .WhereIF(!_userManager.SuperAdmin, u => ids.Contains(u.TenantId.Value))
             .WhereIF(!string.IsNullOrEmpty(input.Label?.Trim()), u => u.Value.Contains(input.Label))
-            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId ==  input.TenantId)
             .OrderBy(u => new { u.OrderNo, Code = u.Value })
             .ToPagedListAsync(input.Page, input.PageSize);
     }
@@ -148,7 +148,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
     [NonAction]
     public async Task<List<SysDictData>> GetDictDataListByDictTypeId(long dictTypeId)
     {
-        var dictType = await App.GetService<SysDictTypeService>().GetDetail(new DictTypeInput { Id = dictTypeId });
+        var dictType = await App.GetService<SysDictTypeService>().GetDetail(new DictTypeInput { Id= dictTypeId });
         var dictDataList = _sysCacheService.Get<List<SysDictData>>($"{CacheConst.KeyDict}{dictTypeId}");
 
         if (dictDataList == null)
@@ -199,7 +199,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
             .OrderBy((u, a) => new { a.OrderNo, Code = a.Value })
             .Select((u, a) => a).ToListAsync();
     }
-
+    
     /// <summary>
     /// 获取租户Id列表
     /// </summary>
@@ -214,7 +214,7 @@ public class SysDictDataService : IDynamicApiController, ITransient
     [NonAction]
     public ISugarQueryable<SysDictData> GetSysDictDataQueryable()
     {
-        var ids = GetTenantIdList();
+        var ids = GetTenantIdList(); 
         return _sysDictDataRep.AsQueryable().ClearFilter().WhereIF(!_userManager.SuperAdmin, u => ids.Contains(u.TenantId.Value));
     }
 

+ 5 - 5
Admin.NET/Admin.NET.Core/Service/Dict/SysDictTypeService.cs

@@ -37,7 +37,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
     {
         return await _sysDictTypeRep.AsQueryable()
             .WhereIF(!_userManager.SuperAdmin, u => !SqlFunc.EndsWith(SqlFunc.ToLower(u.Code), nameof(Enum).ToLower()))
-            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId ==  input.TenantId)
             .WhereIF(!string.IsNullOrEmpty(input.Code?.Trim()), u => u.Code.Contains(input.Code))
             .WhereIF(!string.IsNullOrEmpty(input.Name?.Trim()), u => u.Name.Contains(input.Name))
             .OrderBy(u => new { u.OrderNo, u.Code })
@@ -158,13 +158,13 @@ public class SysDictTypeService : IDynamicApiController, ITransient
     public async Task<dynamic> GetAllDictList()
     {
         var ds = await GetSysDictDataQueryable()
-            .InnerJoin<SysDictData>((u, a) => u.Id == a.DictTypeId)
-            .Where((u, a) => u.IsDelete == false && a.Status == StatusEnum.Enable)
+            .InnerJoin<SysDictData>((u, a) => u.Id == a.DictTypeId).ClearFilter()
+            .Where((u, a) => u.IsDelete == false && u.Status == StatusEnum.Enable && a.IsDelete == false && a.Status == StatusEnum.Enable)
             .Select((u, a) => new { TypeCode = u.Code, a.Label, a.Value, a.Name, a.TagType, a.StyleSetting, a.ClassSetting, a.ExtData, a.Remark, a.OrderNo, a.Status })
             .ToListAsync();
         return ds.OrderBy(u => u.OrderNo).GroupBy(u => u.TypeCode).ToDictionary(u => u.Key, u => u);
     }
-
+    
     /// <summary>
     /// 获取SysDictData表查询实例
     /// </summary>
@@ -175,7 +175,7 @@ public class SysDictTypeService : IDynamicApiController, ITransient
         var ids = GetTenantIdList();
         return _sysDictTypeRep.AsQueryable().ClearFilter().WhereIF(!_userManager.SuperAdmin, u => ids.Contains(u.TenantId.Value));
     }
-
+    
     /// <summary>
     /// 获取租户Id列表
     /// </summary>

+ 2 - 4
Admin.NET/Admin.NET.Core/Service/Enum/SysEnumService.cs

@@ -32,14 +32,12 @@ public class SysEnumService : IDynamicApiController, ITransient
             .OrderBy(u => u.Name).ThenBy(u => u.FullName)
             .ToList();
 
-        // 如果存在同名枚举类,则依次增加 "_序号" 
+        // 如果存在同名枚举类,则依次增加 "_序号" 
         var list = enumTypeList.Select(GetEnumDescription).ToList();
-        var appEnumList = list.Where(u => !u.TypeFullName.StartsWith(typeof(AccountTypeEnum).Namespace!));
         foreach (var enumType in list.GroupBy(u => u.TypeName).Where(g => g.Count() > 1))
         {
             int i = 1;
-            // 过滤框架中的枚举
-            foreach (var item in appEnumList.Where(u => u.TypeName == enumType.Key)) item.TypeName = $"{i++}_{item.TypeName}";
+            foreach (var item in list.Where(u => u.TypeName == enumType.Key).Skip(1)) item.TypeName = $"{item.TypeName}_{i++}";
         }
         return list;
     }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/File/Dto/FileInput.cs

@@ -30,6 +30,11 @@ public class PageFileInput : BasePageInput
     /// 结束时间
     /// </summary>
     public DateTime? EndTime { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class FileInput : BaseIdInput

+ 1 - 0
Admin.NET/Admin.NET.Core/Service/File/SysFileService.cs

@@ -50,6 +50,7 @@ public class SysFileService : IDynamicApiController, ITransient
         var privateList = _sysFileRep.AsQueryable().Where(u => u.IsPublic == false);
         // 合并公开和私有附件并分页
         return await _sysFileRep.Context.UnionAll(publicList, privateList)
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.FileName), u => u.FileName.Contains(input.FileName.Trim()))
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()) && !string.IsNullOrWhiteSpace(input.EndTime.ToString()),
                 u => u.CreateTime >= input.StartTime && u.CreateTime <= input.EndTime)

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Log/Dto/LogInput.cs

@@ -57,6 +57,11 @@ public class PageLogInput : BasePageInput
     /// IP地址
     /// </summary>
     public string? RemoteIp { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class LogInput

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Log/SysLogDiffService.cs

@@ -13,10 +13,12 @@ namespace Admin.NET.Core.Service;
 public class SysLogDiffService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysLogDiff> _sysLogDiffRep;
+    private readonly UserManager _userManager;
 
-    public SysLogDiffService(SqlSugarRepository<SysLogDiff> sysLogDiffRep)
+    public SysLogDiffService(UserManager userManager, SqlSugarRepository<SysLogDiff> sysLogDiffRep)
     {
         _sysLogDiffRep = sysLogDiffRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -28,6 +30,7 @@ public class SysLogDiffService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysLogDiff>> Page(PageLogInput input)
     {
         return await _sysLogDiffRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
             .OrderBy(u => u.CreateTime, OrderByType.Desc)

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Log/SysLogExService.cs

@@ -13,10 +13,12 @@ namespace Admin.NET.Core.Service;
 public class SysLogExService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysLogEx> _sysLogExRep;
+    private readonly UserManager _userManager;
 
-    public SysLogExService(SqlSugarRepository<SysLogEx> sysLogExRep)
+    public SysLogExService(UserManager userManager, SqlSugarRepository<SysLogEx> sysLogExRep)
     {
         _sysLogExRep = sysLogExRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -28,6 +30,7 @@ public class SysLogExService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysLogEx>> Page(PageExLogInput input)
     {
         return await _sysLogExRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Log/SysLogOpService.cs

@@ -13,10 +13,12 @@ namespace Admin.NET.Core.Service;
 public class SysLogOpService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysLogOp> _sysLogOpRep;
+    private readonly UserManager _userManager;
 
-    public SysLogOpService(SqlSugarRepository<SysLogOp> sysLogOpRep)
+    public SysLogOpService(UserManager userManager, SqlSugarRepository<SysLogOp> sysLogOpRep)
     {
         _sysLogOpRep = sysLogOpRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -28,6 +30,7 @@ public class SysLogOpService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysLogOp>> Page(PageOpLogInput input)
     {
         return await _sysLogOpRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Log/SysLogVisService.cs

@@ -13,10 +13,12 @@ namespace Admin.NET.Core.Service;
 public class SysLogVisService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysLogVis> _sysLogVisRep;
+    private readonly UserManager _userManager;
 
-    public SysLogVisService(SqlSugarRepository<SysLogVis> sysLogVisRep)
+    public SysLogVisService(UserManager userManager, SqlSugarRepository<SysLogVis> sysLogVisRep)
     {
         _sysLogVisRep = sysLogVisRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -28,6 +30,7 @@ public class SysLogVisService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysLogVis>> Page(PageVisLogInput input)
     {
         return await _sysLogVisRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.CreateTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.CreateTime <= input.EndTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account == input.Account)

+ 8 - 8
Admin.NET/Admin.NET.Core/Service/Menu/Dto/MenuInput.cs

@@ -17,16 +17,11 @@ public class MenuInput
     /// 菜单类型(1目录 2菜单 3按钮)
     /// </summary>
     public MenuTypeEnum? Type { get; set; }
-
-    /// <summary>
-    /// 获取所有菜单
-    /// </summary>
-    public bool All { get; set; }
-
+    
     /// <summary>
-    /// 应用Id
+    /// 租户Id
     /// </summary>
-    public long AppId { get; set; }
+    public virtual long TenantId { get; set; }
 }
 
 public class AddMenuInput : SysMenu
@@ -36,6 +31,11 @@ public class AddMenuInput : SysMenu
     /// </summary>
     [Required(ErrorMessage = "菜单名称不能为空")]
     public override string Title { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class UpdateMenuInput : AddMenuInput

+ 72 - 87
Admin.NET/Admin.NET.Core/Service/Menu/SysMenuService.cs

@@ -4,6 +4,8 @@
 //
 // 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
 
+using OfficeOpenXml.FormulaParsing.Excel.Functions.Text;
+
 namespace Admin.NET.Core.Service;
 
 /// <summary>
@@ -12,28 +14,29 @@ namespace Admin.NET.Core.Service;
 [ApiDescriptionSettings(Order = 450)]
 public class SysMenuService : IDynamicApiController, ITransient
 {
-    private readonly UserManager _userManager;
+    private readonly SqlSugarRepository<SysTenantMenu> _sysTenantMenuRep;
     private readonly SqlSugarRepository<SysMenu> _sysMenuRep;
-    private readonly SqlSugarRepository<SysAppMenu> _sysAppMenuRep;
     private readonly SysRoleMenuService _sysRoleMenuService;
     private readonly SysUserRoleService _sysUserRoleService;
     private readonly SysUserMenuService _sysUserMenuService;
     private readonly SysCacheService _sysCacheService;
+    private readonly UserManager _userManager;
 
-    public SysMenuService(UserManager userManager,
-        SqlSugarRepository<SysAppMenu> sysAppMenuRep,
+    public SysMenuService(
+        SqlSugarRepository<SysTenantMenu> sysTenantMenuRep,
         SqlSugarRepository<SysMenu> sysMenuRep,
         SysRoleMenuService sysRoleMenuService,
         SysUserRoleService sysUserRoleService,
         SysUserMenuService sysUserMenuService,
-        SysCacheService sysCacheService)
+        SysCacheService sysCacheService,
+        UserManager userManager)
     {
         _userManager = userManager;
         _sysMenuRep = sysMenuRep;
-        _sysAppMenuRep = sysAppMenuRep;
         _sysRoleMenuService = sysRoleMenuService;
         _sysUserRoleService = sysUserRoleService;
         _sysUserMenuService = sysUserMenuService;
+        _sysTenantMenuRep = sysTenantMenuRep;
         _sysCacheService = sysCacheService;
     }
 
@@ -44,39 +47,24 @@ public class SysMenuService : IDynamicApiController, ITransient
     [DisplayName("获取登录菜单树")]
     public async Task<List<MenuOutput>> GetLoginMenuTree()
     {
-        if (_userManager.SuperAdmin)
+        var (query, _) = GetSugarQueryableAndTenantId(_userManager.TenantId);
+        if (_userManager.SuperAdmin || _userManager.SysAdmin)
         {
-            var menuList = await _sysMenuRep.AsQueryable()
-                .InnerJoin<SysAppMenu>((u, am) => am.AppId == _userManager.AppId && u.Id == am.MenuId)
-                .Where(u => u.Type != MenuTypeEnum.Btn && u.Status == StatusEnum.Enable)
-                .OrderBy(u => new { u.OrderNo, u.Id }).Distinct().ToTreeAsync(u => u.Children, u => u.Pid, 0);
+            // 超管用户且是默认租户,则获取全部默认菜单
+            if (_userManager.SuperAdmin && _userManager.TenantId == SqlSugarConst.DefaultTenantId)
+                query = _sysMenuRep.AsQueryable().ClearFilter().InnerJoinIF<SysTenantMenu>(false, (u, t) => true);
+            var menuList = await query.Where(u => u.Type != MenuTypeEnum.Btn && u.Status == StatusEnum.Enable)
+                .OrderBy(u => new { u.OrderNo, u.Id })
+                .ToTreeAsync(u => u.Children, u => u.Pid, 0);
             return menuList.Adapt<List<MenuOutput>>();
         }
+
         var menuIdList = await GetMenuIdList();
-        var menuTree = await _sysMenuRep.AsQueryable()
-            .InnerJoin<SysAppMenu>((u, am) => am.AppId == _userManager.AppId && u.Id == am.MenuId)
-            .Where(u => u.Status == StatusEnum.Enable)
-            .OrderBy(u => new { u.OrderNo, u.Id }).Distinct().ToTreeAsync(u => u.Children, u => u.Pid, 0, menuIdList.Select(d => (object)d).ToArray());
-        DeleteBtnFromMenuTree(menuTree);
+        var menuTree = await query.Where(u => u.Type != MenuTypeEnum.Btn && u.Status == StatusEnum.Enable)
+            .OrderBy(u => new { u.OrderNo, u.Id }).ToTreeAsync(u => u.Children, u => u.Pid, 0, menuIdList.Select(d => (object)d).ToArray());
         return menuTree.Adapt<List<MenuOutput>>();
     }
 
-    /// <summary>
-    /// 删除登录菜单树里面的按钮
-    /// </summary>
-    private static void DeleteBtnFromMenuTree(List<SysMenu> menuList)
-    {
-        if (menuList == null) return;
-        for (var i = menuList.Count - 1; i >= 0; i--)
-        {
-            var menu = menuList[i];
-            if (menu.Type == MenuTypeEnum.Btn)
-                menuList.Remove(menu);
-            else if (menu.Children.Count > 0)
-                DeleteBtnFromMenuTree(menu.Children);
-        }
-    }
-
     /// <summary>
     /// 获取菜单列表 🔖
     /// </summary>
@@ -84,15 +72,9 @@ public class SysMenuService : IDynamicApiController, ITransient
     [DisplayName("获取菜单列表")]
     public async Task<List<SysMenu>> GetList([FromQuery] MenuInput input)
     {
-        var menuIdList = _userManager.SuperAdmin ? new List<long>() : await GetMenuIdList();
-
-        // 仅超级管理员可以获取全部菜单
-        var joinApp = _userManager.SuperAdmin == false || (_userManager.SuperAdmin && !input.All);
-        // 超级管理员可根据传参获取指定应用的菜单
-        var appId = _userManager.SuperAdmin && input.AppId > 0 ? input.AppId : _userManager.AppId;
-        var query = _sysMenuRep.AsQueryable()
-            .InnerJoinIF<SysAppMenu>(joinApp, (u, am) => am.AppId == appId && u.Id == am.MenuId);
-
+        var menuIdList = _userManager.SuperAdmin || _userManager.SysAdmin ? new List<long>() : await GetMenuIdList();
+        var (query, _) = GetSugarQueryableAndTenantId(input.TenantId);
+        
         // 有筛选条件时返回list列表(防止构造不出树)
         if (!string.IsNullOrWhiteSpace(input.Title) || input.Type is > 0)
         {
@@ -102,7 +84,7 @@ public class SysMenuService : IDynamicApiController, ITransient
                 .OrderBy(u => new { u.OrderNo, u.Id }).Distinct().ToListAsync();
         }
 
-        return _userManager.SuperAdmin ?
+        return _userManager.SuperAdmin || _userManager.SysAdmin ?
             await query.OrderBy(u => new { u.OrderNo, u.Id }).Distinct().ToTreeAsync(u => u.Children, u => u.Pid, 0) :
             await query.OrderBy(u => new { u.OrderNo, u.Id }).Distinct().ToTreeAsync(u => u.Children, u => u.Pid, 0, menuIdList.Select(d => (object)d).ToArray()); // 角色菜单授权时
     }
@@ -116,31 +98,24 @@ public class SysMenuService : IDynamicApiController, ITransient
     [DisplayName("增加菜单")]
     public async Task AddMenu(AddMenuInput input)
     {
+        var (query, tenantId) = GetSugarQueryableAndTenantId(input.TenantId);
+        
         var isExist = input.Type != MenuTypeEnum.Btn
-            ? await _sysMenuRep.IsAnyAsync(u => u.Title == input.Title && u.Pid == input.Pid)
-            : await _sysMenuRep.IsAnyAsync(u => u.Permission == input.Permission);
+            ? await query.AnyAsync(u => u.Title == input.Title && u.Pid == input.Pid)
+            : await query.AnyAsync(u => u.Permission == input.Permission);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D4000);
 
-        if (!string.IsNullOrWhiteSpace(input.Name))
-        {
-            if (await _sysMenuRep.IsAnyAsync(u => u.Name == input.Name))
-                throw Oops.Oh(ErrorCodeEnum.D4009);
-        }
+        if (!string.IsNullOrWhiteSpace(input.Name) && await query.AnyAsync(u => u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D4009);
 
-        if (input.Pid != 0)
-        {
-            if (await _sysMenuRep.IsAnyAsync(u => u.Id == input.Pid && u.Type == MenuTypeEnum.Btn))
-                throw Oops.Oh(ErrorCodeEnum.D4010);
-        }
+        if (input.Pid != 0 && await query.AnyAsync(u => u.Id == input.Pid && u.Type == MenuTypeEnum.Btn)) throw Oops.Oh(ErrorCodeEnum.D4010);
 
         // 校验菜单参数
         var sysMenu = input.Adapt<SysMenu>();
         CheckMenuParam(sysMenu);
 
+        // 保存租户菜单权限
         await _sysMenuRep.InsertAsync(sysMenu);
-
-        // 保存应用菜单关联
-        await _sysAppMenuRep.InsertAsync(new SysAppMenu { AppId = _userManager.AppId, MenuId = sysMenu.Id });
+        await _sysTenantMenuRep.InsertAsync(new SysTenantMenu { TenantId = tenantId, MenuId = sysMenu.Id });
 
         // 清除缓存
         DeleteMenuCache();
@@ -155,26 +130,19 @@ public class SysMenuService : IDynamicApiController, ITransient
     [DisplayName("更新菜单")]
     public async Task UpdateMenu(UpdateMenuInput input)
     {
-        if (input.Id == input.Pid)
-            throw Oops.Oh(ErrorCodeEnum.D4008);
+        if (!_userManager.SuperAdmin && new SysMenuSeedData().HasData().Any(u => u.Id == input.Id)) throw Oops.Oh(ErrorCodeEnum.D4012);
+
+        if (input.Id == input.Pid) throw Oops.Oh(ErrorCodeEnum.D4008);
+        var (query, _) = GetSugarQueryableAndTenantId(input.TenantId);
 
         var isExist = input.Type != MenuTypeEnum.Btn
-            ? await _sysMenuRep.IsAnyAsync(u => u.Title == input.Title && u.Type == input.Type && u.Pid == input.Pid && u.Id != input.Id)
-            : await _sysMenuRep.IsAnyAsync(u => u.Permission == input.Permission && u.Id != input.Id);
-        if (isExist)
-            throw Oops.Oh(ErrorCodeEnum.D4000);
+            ? await query.AnyAsync(u => u.Title == input.Title && u.Type == input.Type && u.Pid == input.Pid && u.Id != input.Id)
+            : await query.AnyAsync(u => u.Permission == input.Permission && u.Id != input.Id);
+        if (isExist) throw Oops.Oh(ErrorCodeEnum.D4000);
 
-        if (!string.IsNullOrWhiteSpace(input.Name))
-        {
-            if (await _sysMenuRep.IsAnyAsync(u => u.Id != input.Id && u.Name == input.Name))
-                throw Oops.Oh(ErrorCodeEnum.D4009);
-        }
+        if (!string.IsNullOrWhiteSpace(input.Name) && await query.AnyAsync(u => u.Id != input.Id && u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D4009);
 
-        if (input.Pid != 0)
-        {
-            if (await _sysMenuRep.IsAnyAsync(u => u.Id == input.Pid && u.Type == MenuTypeEnum.Btn))
-                throw Oops.Oh(ErrorCodeEnum.D4010);
-        }
+        if (input.Pid != 0 && await query.AnyAsync(u => u.Id == input.Pid && u.Type == MenuTypeEnum.Btn)) throw Oops.Oh(ErrorCodeEnum.D4010);
 
         // 校验菜单参数
         var sysMenu = input.Adapt<SysMenu>();
@@ -196,10 +164,15 @@ public class SysMenuService : IDynamicApiController, ITransient
     [DisplayName("删除菜单")]
     public async Task DeleteMenu(DeleteMenuInput input)
     {
-        var menuTreeList = await _sysMenuRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id, true);
+        if (!_userManager.SuperAdmin && new SysMenuSeedData().HasData().Any(u => u.Id == input.Id)) throw Oops.Oh(ErrorCodeEnum.D4013);
+
+        var menuTreeList = await _sysMenuRep.AsQueryable().ToChildListAsync(u => u.Pid, input.Id);
         var menuIdList = menuTreeList.Select(u => u.Id).ToList();
 
         await _sysMenuRep.DeleteAsync(u => menuIdList.Contains(u.Id));
+        
+        // 级联删除租户菜单数据
+        await _sysTenantMenuRep.AsDeleteable().Where(u => menuIdList.Contains(u.MenuId)).ExecuteCommandAsync();
 
         // 级联删除角色菜单数据
         await _sysRoleMenuService.DeleteRoleMenuByMenuIdList(menuIdList);
@@ -207,9 +180,6 @@ public class SysMenuService : IDynamicApiController, ITransient
         // 级联删除用户收藏菜单
         await _sysUserMenuService.DeleteMenuList(menuIdList);
 
-        // 删除应用菜单关联
-        await _sysAppMenuRep.AsDeleteable().Where(u => menuIdList.Contains(u.MenuId)).ExecuteCommandAsync();
-
         // 清除缓存
         DeleteMenuCache();
     }
@@ -253,14 +223,14 @@ public class SysMenuService : IDynamicApiController, ITransient
         var userId = _userManager.UserId;
         var permissions = _sysCacheService.Get<List<string>>(CacheConst.KeyUserButton + userId);
         if (permissions != null) return permissions;
-
-        var menuIdList = _userManager.SuperAdmin ? new() : await GetMenuIdList();
-        permissions = menuIdList.Count > 0 || _userManager.SuperAdmin
-            ? await _sysMenuRep.AsQueryable()
-                .Where(u => u.Type == MenuTypeEnum.Btn)
-                .WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
-                .Select(u => u.Permission).ToListAsync()
-            : new();
+        
+        var menuIdList = _userManager.SuperAdmin || _userManager.SysAdmin ? new() : await GetMenuIdList();
+        
+        permissions = await _sysMenuRep.AsQueryable().Where(u => u.Type == MenuTypeEnum.Btn)
+            .WhereIF(menuIdList.Count > 0, u => menuIdList.Contains(u.Id))
+            .InnerJoinIF<SysTenantMenu>(!_userManager.SuperAdmin, (u, t) => t.TenantId == _userManager.TenantId && u.Id == t.MenuId)
+            .Select(u => u.Permission).ToListAsync();
+        
         _sysCacheService.Set(CacheConst.KeyUserButton + userId, permissions, TimeSpan.FromDays(7));
 
         return permissions;
@@ -283,11 +253,25 @@ public class SysMenuService : IDynamicApiController, ITransient
 
         return permissions;
     }
+    
+    /// <summary>
+    /// 根据租户id获取构建菜单联表查询实例
+    /// </summary>
+    /// <returns></returns>
+    [NonAction]
+    public (ISugarQueryable<SysMenu, SysTenantMenu> query, long tenantId) GetSugarQueryableAndTenantId(long tenantId)
+    {
+        if (!_userManager.SuperAdmin) tenantId = _userManager.TenantId;
+        var query = _sysMenuRep.AsQueryable().ClearFilter()
+            .InnerJoinIF<SysTenantMenu>(tenantId > 0, (u, t) => t.TenantId == tenantId && u.Id == t.MenuId);
+        return (query, tenantId);
+    }
 
     /// <summary>
     /// 清除菜单和按钮缓存
     /// </summary>
-    private void DeleteMenuCache()
+    [NonAction]
+    public void DeleteMenuCache()
     {
         // _sysCacheService.RemoveByPrefixKey(CacheConst.KeyUserMenu);
         _sysCacheService.RemoveByPrefixKey(CacheConst.KeyUserButton);
@@ -297,7 +281,8 @@ public class SysMenuService : IDynamicApiController, ITransient
     /// 获取当前用户菜单Id集合
     /// </summary>
     /// <returns></returns>
-    private async Task<List<long>> GetMenuIdList()
+    [NonAction]
+    public async Task<List<long>> GetMenuIdList()
     {
         var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
         return await _sysRoleMenuService.GetRoleMenuIdList(roleIdList);

+ 5 - 4
Admin.NET/Admin.NET.Core/Service/Message/SysEmailService.cs

@@ -15,13 +15,13 @@ namespace Admin.NET.Core.Service;
 [ApiDescriptionSettings(Order = 370)]
 public class SysEmailService : IDynamicApiController, ITransient
 {
+    private readonly SqlSugarRepository<SysTenant> _sysTenantRep;
     private readonly EmailOptions _emailOptions;
-    private readonly SysConfigService _sysConfigService;
 
-    public SysEmailService(IOptions<EmailOptions> emailOptions, SysConfigService sysConfigService)
+    public SysEmailService(IOptions<EmailOptions> emailOptions, SqlSugarRepository<SysTenant> sysTenantRep)
     {
         _emailOptions = emailOptions.Value;
-        _sysConfigService = sysConfigService;
+        _sysTenantRep = sysTenantRep;
     }
 
     /// <summary>
@@ -34,7 +34,8 @@ public class SysEmailService : IDynamicApiController, ITransient
     [DisplayName("发送邮件")]
     public async Task SendEmail([Required] string content, string title = "", string toEmail = "")
     {
-        var webTitle = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysWebTitle);
+        long.TryParse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? SqlSugarConst.DefaultTenantId.ToString(), out var tenantId);
+        var webTitle = (await _sysTenantRep.GetFirstAsync(u => u.Id == tenantId))?.Title;
         title = string.IsNullOrWhiteSpace(title) ? $"{webTitle} 系统邮件" : title;
         var message = new MimeMessage();
 

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/OAuth/SysOAuthService.cs

@@ -113,7 +113,7 @@ public class SysOAuthService : IDynamicApiController, ITransient
         }
 
         // 构建Token令牌
-        var token = await App.GetRequiredService<SysAuthService>().CreateToken(wechatUser.SysUser, SqlSugarConst.DefaultAppId);
+        var token = await App.GetRequiredService<SysAuthService>().CreateToken(wechatUser.SysUser);
 
         return new RedirectResult($"{redirectUrl}/#/login?token={token.AccessToken}");
     }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/OnlineUser/Dto/OnlineUserInput.cs

@@ -17,4 +17,9 @@ public class PageOnlineUserInput : BasePageInput
     /// 真实姓名
     /// </summary>
     public string RealName { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }

+ 5 - 1
Admin.NET/Admin.NET.Core/Service/OnlineUser/SysOnlineUserService.cs

@@ -14,14 +14,17 @@ namespace Admin.NET.Core.Service;
 [ApiDescriptionSettings(Order = 300)]
 public class SysOnlineUserService : IDynamicApiController, ITransient
 {
+    private readonly UserManager _userManager;
     private readonly SysConfigService _sysConfigService;
     private readonly IHubContext<OnlineUserHub, IOnlineUserHub> _onlineUserHubContext;
     private readonly SqlSugarRepository<SysOnlineUser> _sysOnlineUerRep;
 
     public SysOnlineUserService(SysConfigService sysConfigService,
         IHubContext<OnlineUserHub, IOnlineUserHub> onlineUserHubContext,
-        SqlSugarRepository<SysOnlineUser> sysOnlineUerRep)
+        SqlSugarRepository<SysOnlineUser> sysOnlineUerRep,
+        UserManager userManager)
     {
+        _userManager = userManager;
         _sysConfigService = sysConfigService;
         _onlineUserHubContext = onlineUserHubContext;
         _sysOnlineUerRep = sysOnlineUerRep;
@@ -35,6 +38,7 @@ public class SysOnlineUserService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysOnlineUser>> Page(PageOnlineUserInput input)
     {
         return await _sysOnlineUerRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.UserName), u => u.UserName.Contains(input.UserName))
             .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
             .ToPagedListAsync(input.Page, input.PageSize);

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Org/Dto/OrgInput.cs

@@ -22,6 +22,11 @@ public class OrgInput : BaseIdInput
     /// 机构类型
     /// </summary>
     public string Type { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddOrgInput : SysOrg

+ 11 - 6
Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs

@@ -44,12 +44,14 @@ public class SysOrgService : IDynamicApiController, ITransient
         // 获取拥有的机构Id集合
         var userOrgIdList = await GetUserOrgIdList();
 
-        var iSugarQueryable = _sysOrgRep.AsQueryable().OrderBy(u => new { u.OrderNo, u.Id });
+        var queryable = _sysOrgRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
+            .OrderBy(u => new { u.OrderNo, u.Id });
 
         // 带条件筛选时返回列表数据
         if (!string.IsNullOrWhiteSpace(input.Name) || !string.IsNullOrWhiteSpace(input.Code) || !string.IsNullOrWhiteSpace(input.Type))
         {
-            return await iSugarQueryable.WhereIF(userOrgIdList.Count > 0, u => userOrgIdList.Contains(u.Id))
+            return await queryable.WhereIF(userOrgIdList.Count > 0, u => userOrgIdList.Contains(u.Id))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code == input.Code)
                 .WhereIF(!string.IsNullOrWhiteSpace(input.Type), u => u.Type == input.Type)
@@ -59,11 +61,11 @@ public class SysOrgService : IDynamicApiController, ITransient
         List<SysOrg> orgTree;
         if (_userManager.SuperAdmin)
         {
-            orgTree = await iSugarQueryable.ToTreeAsync(u => u.Children, u => u.Pid, input.Id);
+            orgTree = await queryable.ToTreeAsync(u => u.Children, u => u.Pid, input.Id);
         }
         else
         {
-            orgTree = await iSugarQueryable.ToTreeAsync(u => u.Children, u => u.Pid, input.Id, userOrgIdList.Select(d => (object)d).ToArray());
+            orgTree = await queryable.ToTreeAsync(u => u.Children, u => u.Pid, input.Id, userOrgIdList.Select(d => (object)d).ToArray());
             // 递归禁用没权限的机构(防止用户修改或创建无权的机构和用户)
             HandlerOrgTree(orgTree, userOrgIdList);
         }
@@ -236,8 +238,11 @@ public class SysOrgService : IDynamicApiController, ITransient
         // 若子机构有用户则禁止删除
         var cOrgHasEmp = await _sysOrgRep.ChangeRepository<SqlSugarRepository<SysUser>>()
             .IsAnyAsync(u => childOrgIdList.Contains(u.OrgId));
-        if (cOrgHasEmp)
-            throw Oops.Oh(ErrorCodeEnum.D2007);
+        if (cOrgHasEmp) throw Oops.Oh(ErrorCodeEnum.D2007);
+        
+        // 若有绑定注册方案则禁止删除
+        var hasUserRegWay = await _sysOrgRep.Context.Queryable<SysUserRegWay>().AnyAsync(u => u.OrgId == input.Id);
+        if (hasUserRegWay) throw Oops.Oh(ErrorCodeEnum.D2010);
 
         // 删除与此机构、父机构有关的用户机构缓存
         DeleteAllUserOrgCache(sysOrg.Id, sysOrg.Pid);

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Plugin/Dto/PluginInput.cs

@@ -17,6 +17,11 @@ public class PagePluginInput : BasePageInput
     /// 编码
     /// </summary>
     public string Code { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddPluginInput : SysPlugin

+ 5 - 1
Admin.NET/Admin.NET.Core/Service/Plugin/SysPluginService.cs

@@ -14,11 +14,14 @@ public class SysPluginService : IDynamicApiController, ITransient
 {
     private readonly IDynamicApiRuntimeChangeProvider _provider;
     private readonly SqlSugarRepository<SysPlugin> _sysPluginRep;
+    private readonly UserManager _userManager;
 
     public SysPluginService(IDynamicApiRuntimeChangeProvider provider,
-        SqlSugarRepository<SysPlugin> sysPluginRep)
+        SqlSugarRepository<SysPlugin> sysPluginRep,
+        UserManager userManager)
     {
         _provider = provider;
+        _userManager = userManager;
         _sysPluginRep = sysPluginRep;
     }
 
@@ -31,6 +34,7 @@ public class SysPluginService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysPlugin>> Page(PagePluginInput input)
     {
         return await _sysPluginRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
             .OrderBy(u => new { u.OrderNo, u.Id })
             .ToPagedListAsync(input.Page, input.PageSize);

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Pos/Dto/PosInput.cs

@@ -17,6 +17,11 @@ public class PosInput
     /// 编码
     /// </summary>
     public string Code { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddPosInput : SysPos

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Pos/SysPosService.cs

@@ -34,6 +34,7 @@ public class SysPosService : IDynamicApiController, ITransient
     public async Task<List<SysPos>> GetList([FromQuery] PosInput input)
     {
         return await _sysPosRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
             .WhereIF(!string.IsNullOrWhiteSpace(input.Code), u => u.Code.Contains(input.Code))
             .OrderBy(u => new { u.OrderNo, u.Id })
@@ -99,6 +100,10 @@ public class SysPosService : IDynamicApiController, ITransient
         // 若附属职位有用户则禁止删除
         var hasExtPosEmp = await _sysUserExtOrgService.HasUserPos(input.Id);
         if (hasExtPosEmp) throw Oops.Oh(ErrorCodeEnum.D6001);
+        
+        // 若有绑定注册方案则禁止删除
+        var hasUserRegWay = await _sysPosRep.Context.Queryable<SysUserRegWay>().AnyAsync(u => u.PosId == input.Id);
+        if (hasUserRegWay) throw Oops.Oh(ErrorCodeEnum.D6004);
 
         await _sysPosRep.DeleteAsync(u => u.Id == input.Id);
     }

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Print/Dto/PrintInput.cs

@@ -17,6 +17,11 @@ public class PagePrintInput : BasePageInput
     /// 编码
     /// </summary>
     public string Code { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddPrintInput : SysPrint

+ 4 - 1
Admin.NET/Admin.NET.Core/Service/Print/SysPrintService.cs

@@ -13,10 +13,12 @@ namespace Admin.NET.Core.Service;
 public class SysPrintService : IDynamicApiController, ITransient
 {
     private readonly SqlSugarRepository<SysPrint> _sysPrintRep;
+    private readonly UserManager _userManager;
 
-    public SysPrintService(SqlSugarRepository<SysPrint> sysPrintRep)
+    public SysPrintService(SqlSugarRepository<SysPrint> sysPrintRep, UserManager userManager)
     {
         _sysPrintRep = sysPrintRep;
+        _userManager = userManager;
     }
 
     /// <summary>
@@ -28,6 +30,7 @@ public class SysPrintService : IDynamicApiController, ITransient
     public async Task<SqlSugarPagedList<SysPrint>> Page(PagePrintInput input)
     {
         return await _sysPrintRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
             .OrderBy(u => new { u.OrderNo, u.Id })
             .ToPagedListAsync(input.Page, input.PageSize);

+ 0 - 3
Admin.NET/Admin.NET.Core/Service/Region/SysRegionService.cs

@@ -18,9 +18,6 @@ public class SysRegionService : IDynamicApiController, ITransient
     private readonly SqlSugarRepository<SysRegion> _sysRegionRep;
     private readonly SysConfigService _sysConfigService;
 
-    // Url地址-国家统计局行政区域2023年
-    private readonly string _url = "http://www.stats.gov.cn/sj/tjbz/tjyqhdmhcxhfdm/2023/index.html";
-
     public SysRegionService(SqlSugarRepository<SysRegion> sysRegionRep, SysConfigService sysConfigService)
     {
         _sysRegionRep = sysRegionRep;

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleInput.cs

@@ -16,6 +16,11 @@ public class RoleInput : BaseIdInput
 
 public class PageRoleInput : BasePageInput
 {
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
+    
     /// <summary>
     /// 名称
     /// </summary>

+ 1 - 1
Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleMenuInput.cs

@@ -7,7 +7,7 @@
 namespace Admin.NET.Core.Service;
 
 /// <summary>
-/// 授权角色菜单
+/// 系统角色菜单
 /// </summary>
 public class RoleMenuInput : BaseIdInput
 {

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Role/Dto/RoleOutput.cs

@@ -25,4 +25,9 @@ public class RoleOutput
     /// 编码
     /// </summary>
     public string Code { get; set; }
+
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long tenantId { get; set; }
 }

+ 6 - 4
Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs

@@ -45,6 +45,7 @@ public class SysRoleService : IDynamicApiController, ITransient
         // 当前用户已拥有的角色集合
         var roleIdList = _userManager.SuperAdmin ? new List<long>() : await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId);
         return await _sysRoleRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!_userManager.SuperAdmin, u => u.TenantId == _userManager.TenantId) // 若非超管,则只能操作本租户的角色
             .WhereIF(!_userManager.SuperAdmin && !_userManager.SysAdmin, u => u.CreateUserId == _userManager.UserId || roleIdList.Contains(u.Id)) // 若非超管且非系统管理员,则只能操作自己创建的角色|自己拥有的角色
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name))
@@ -134,14 +135,15 @@ public class SysRoleService : IDynamicApiController, ITransient
     [DisplayName("删除角色")]
     public async Task DeleteRole(DeleteRoleInput input)
     {
-        // 禁止删除系统管理员角色
-        var sysRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
-        if (sysRole.Code == CommonConst.SysAdminRole) throw Oops.Oh(ErrorCodeEnum.D1019);
-
         // 若角色有用户则禁止删除
         var userIds = await _sysUserRoleService.GetUserIdList(input.Id);
         if (userIds != null && userIds.Count > 0) throw Oops.Oh(ErrorCodeEnum.D1025);
+        
+        // 若有绑定注册方案则禁止删除
+        var hasUserRegWay = await _sysRoleRep.Context.Queryable<SysUserRegWay>().AnyAsync(u => u.RoleId == input.Id);
+        if (hasUserRegWay) throw Oops.Oh(ErrorCodeEnum.D1033);
 
+        var sysRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
         await _sysRoleRep.DeleteAsync(sysRole);
 
         // 级联删除角色机构数据

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/Schedule/Dto/ScheduleInput.cs

@@ -19,6 +19,11 @@ public class ListScheduleInput
     public DateTime? StartTime { get; set; }
 
     public DateTime? EndTime { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }
 
 public class AddScheduleInput : SysSchedule

+ 1 - 0
Admin.NET/Admin.NET.Core/Service/Schedule/SysScheduleService.cs

@@ -31,6 +31,7 @@ public class SysScheduleService : IDynamicApiController, ITransient
     {
         return await _sysSchedule.AsQueryable()
             .Where(u => u.UserId == _userManager.UserId)
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.StartTime.ToString()), u => u.ScheduleTime >= input.StartTime)
             .WhereIF(!string.IsNullOrWhiteSpace(input.EndTime.ToString()), u => u.ScheduleTime <= input.EndTime)
             .OrderBy(u => u.StartTime, OrderByType.Asc)

+ 67 - 7
Admin.NET/Admin.NET.Core/Service/Tenant/Dto/TenantInput.cs

@@ -29,12 +29,6 @@ public class PageTenantInput : BasePageInput
 
 public class AddTenantInput : TenantOutput
 {
-    /// <summary>
-    /// 应用Id
-    /// </summary>
-    [Required(ErrorMessage = "应用不能为空")]
-    public new long? AppId { get; set; }
-
     /// <summary>
     /// 租户名称
     /// </summary>
@@ -51,7 +45,62 @@ public class AddTenantInput : TenantOutput
     /// 租户域名
     /// </summary>
     [Required(ErrorMessage = "域名不能为空"), MinLength(5, ErrorMessage = "域名不能少于5个字符")]
-    public new string Host { get; set; }
+    public override string Host { get; set; }
+    
+    /// <summary>
+    /// 系统主标题
+    /// </summary>
+    [Required(ErrorMessage = "系统主标题不能为空")]
+    public override string Title { get; set; }
+
+    /// <summary>
+    /// 系统副标题
+    /// </summary>
+    [Required(ErrorMessage = "系统副标题不能为空")]
+    public override string ViceTitle { get; set; }
+
+    /// <summary>
+    /// 系统描述
+    /// </summary>
+    [Required(ErrorMessage = "系统描述不能为空")]
+    public override string ViceDesc { get; set; }
+
+    /// <summary>
+    /// 水印内容
+    /// </summary>
+    [Required(ErrorMessage = "水印内容不能为空")]
+    public override string Watermark { get; set; }
+
+    /// <summary>
+    /// 版权说明
+    /// </summary>
+    [Required(ErrorMessage = "版权说明不能为空")]
+    public override string Copyright { get; set; }
+
+    /// <summary>
+    /// ICP备案号
+    /// </summary>
+    [Required(ErrorMessage = "ICP备案号不能为空")]
+    public override string Icp { get; set; }
+
+    /// <summary>
+    /// ICP地址
+    /// </summary>
+    [Required(ErrorMessage = "ICP地址不能为空")]
+    public override string IcpUrl { get; set; }
+    
+    /// <summary>
+    /// Logo图片Base64码
+    /// </summary>
+    [CommonValidation(
+        "string.IsNullOrWhiteSpace(Logo) && string.IsNullOrWhiteSpace(LogoBase64)", "图标不能为空"
+    )]
+    public virtual string LogoBase64 { get; set; }
+    
+    /// <summary>
+    /// Logo文件名
+    /// </summary>
+    public virtual string LogoFileName { get; set; }
 }
 
 public class UpdateTenantInput : AddTenantInput
@@ -62,6 +111,17 @@ public class DeleteTenantInput : BaseIdInput
 {
 }
 
+/// <summary>
+/// 租户菜单
+/// </summary>
+public class TenantMenuInput : BaseIdInput
+{
+    /// <summary>
+    /// 菜单Id集合
+    /// </summary>
+    public List<long> MenuIdList { get; set; }
+}
+
 public class TenantUserInput
 {
     /// <summary>

+ 2 - 7
Admin.NET/Admin.NET.Core/Service/Tenant/Dto/TenantOutput.cs

@@ -13,11 +13,6 @@ public class TenantOutput : SysTenant
     /// </summary>
     public virtual string Name { get; set; }
 
-    /// <summary>
-    /// 关联应用名称
-    /// </summary>
-    public virtual string AppName { get; set; }
-
     /// <summary>
     /// 管理员账号
     /// </summary>
@@ -26,10 +21,10 @@ public class TenantOutput : SysTenant
     /// <summary>
     /// 电子邮箱
     /// </summary>
-    public string Email { get; set; }
+    public virtual string Email { get; set; }
 
     /// <summary>
     /// 电话
     /// </summary>
-    public string Phone { get; set; }
+    public virtual string Phone { get; set; }
 }

+ 256 - 56
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -18,12 +18,12 @@ public class SysTenantService : IDynamicApiController, ITransient
     private readonly SqlSugarRepository<SysPos> _sysPosRep;
     private readonly SqlSugarRepository<SysUser> _sysUserRep;
     private readonly SqlSugarRepository<SysUserExtOrg> _sysUserExtOrgRep;
+    private readonly SqlSugarRepository<SysTenantMenu> _sysTenantMenuRep;
     private readonly SqlSugarRepository<SysRoleMenu> _sysRoleMenuRep;
     private readonly SqlSugarRepository<SysUserRole> _userRoleRep;
-    private readonly SysUserRoleService _sysUserRoleService;
-    private readonly SysRoleMenuService _sysRoleMenuService;
     private readonly SysConfigService _sysConfigService;
     private readonly SysCacheService _sysCacheService;
+    private readonly UploadOptions _uploadOptions;
 
     public SysTenantService(SqlSugarRepository<SysTenant> sysTenantRep,
         SqlSugarRepository<SysOrg> sysOrgRep,
@@ -31,10 +31,10 @@ public class SysTenantService : IDynamicApiController, ITransient
         SqlSugarRepository<SysPos> sysPosRep,
         SqlSugarRepository<SysUser> sysUserRep,
         SqlSugarRepository<SysUserExtOrg> sysUserExtOrgRep,
+        SqlSugarRepository<SysTenantMenu> sysTenantMenuRep,
         SqlSugarRepository<SysRoleMenu> sysRoleMenuRep,
         SqlSugarRepository<SysUserRole> userRoleRep,
-        SysUserRoleService sysUserRoleService,
-        SysRoleMenuService sysRoleMenuService,
+        IOptions<UploadOptions> uploadOptions,
         SysConfigService sysConfigService,
         SysCacheService sysCacheService)
     {
@@ -43,11 +43,11 @@ public class SysTenantService : IDynamicApiController, ITransient
         _sysRoleRep = sysRoleRep;
         _sysPosRep = sysPosRep;
         _sysUserRep = sysUserRep;
+        _sysTenantMenuRep = sysTenantMenuRep;
         _sysUserExtOrgRep = sysUserExtOrgRep;
         _sysRoleMenuRep = sysRoleMenuRep;
         _userRoleRep = userRoleRep;
-        _sysUserRoleService = sysUserRoleService;
-        _sysRoleMenuService = sysRoleMenuService;
+        _uploadOptions = uploadOptions.Value;
         _sysConfigService = sysConfigService;
         _sysCacheService = sysCacheService;
     }
@@ -63,19 +63,15 @@ public class SysTenantService : IDynamicApiController, ITransient
         return await _sysTenantRep.AsQueryable()
             .LeftJoin<SysUser>((u, a) => u.UserId == a.Id)
             .LeftJoin<SysOrg>((u, a, b) => u.OrgId == b.Id)
-            .LeftJoin<SysApp>((u, a, b, c) => u.AppId == c.Id)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Phone), (u, a) => a.Phone.Contains(input.Phone.Trim()))
             .WhereIF(!string.IsNullOrWhiteSpace(input.Name), (u, a, b) => b.Name.Contains(input.Name.Trim()))
-            .Where(u => u.Id.ToString() != SqlSugarConst.MainConfigId) // 排除默认主库/主租户
             .OrderBy(u => new { u.OrderNo, u.Id })
-            .Select((u, a, b, c) => new TenantOutput
+            .Select((u, a, b) => new TenantOutput
             {
                 Id = u.Id,
                 OrgId = b.Id,
                 Name = b.Name,
                 UserId = a.Id,
-                AppId = u.AppId,
-                AppName = c.Name,
                 AdminAccount = a.Account,
                 Phone = a.Phone,
                 Host = u.Host,
@@ -91,9 +87,43 @@ public class SysTenantService : IDynamicApiController, ITransient
                 CreateUserName = u.CreateUserName,
                 UpdateTime = u.UpdateTime,
                 UpdateUserName = u.UpdateUserName,
-            })
+            }, true)
             .ToPagedListAsync(input.Page, input.PageSize);
     }
+    
+    /// <summary>
+    /// 获取租户列表
+    /// </summary>
+    /// <returns></returns>
+    [AllowAnonymous]
+    [DisplayName("获取租户列表"), HttpGet]
+    public async Task<dynamic> GetList()
+    {
+        return await _sysTenantRep.AsQueryable()
+           .LeftJoin<SysOrg>((u, a) => u.OrgId == a.Id).ClearFilter()
+           .Where(u => u.Status == StatusEnum.Enable && u.IsDelete == false)
+            .Select((u, a) => new
+            {
+                Label = $"{u.Title}-{a.Name}",
+                Value = u.Id,
+                Host = u.Host.ToLower()
+            }).ToListAsync();
+    }
+    
+    /// <summary>
+    /// 获取当前租户
+    /// </summary>
+    /// <returns></returns>
+    [NonAction]
+    public async Task<SysTenant> GetCurrentTenant()
+    {
+        var tenantId = long.Parse(App.User?.FindFirst(ClaimConst.TenantId)?.Value ?? "0");
+        var host = App.HttpContext.Request.Host.Host.ToLower();
+        return await _sysTenantRep.AsQueryable()
+            .WhereIF(tenantId > 0, u => u.Id == tenantId)
+            .WhereIF(!(tenantId > 0), u => SqlFunc.ToLower(u.Host).Equals(host))
+            .FirstAsync();
+    }
 
     /// <summary>
     /// 获取库隔离的租户列表
@@ -118,7 +148,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         var isExist = await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1300);
 
-        input.Host = input.Host.ToLower();
+        input.Host = input.Host?.ToLower();
         isExist = await _sysTenantRep.IsAnyAsync(u => u.Host == input.Host);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1303);
 
@@ -145,14 +175,60 @@ public class SysTenantService : IDynamicApiController, ITransient
             default:
                 throw Oops.Oh(ErrorCodeEnum.D3004);
         }
-
+        if (input.EnableReg == YesNoEnum.N) input.RegWayId = null;
         var tenant = input.Adapt<TenantOutput>();
+        
+        // 设置logo
+        SetLogoUrl(tenant, input.LogoBase64, input.LogoFileName);
+        
         await _sysTenantRep.InsertAsync(tenant);
         await InitNewTenant(tenant);
 
         await CacheTenant();
     }
 
+    /// <summary>
+    /// 设置logo
+    /// </summary>
+    /// <param name="tenant"></param>
+    /// <param name="logoBase64"></param>
+    /// <param name="logoFileName"></param>
+    [NonAction]
+    public void SetLogoUrl(SysTenant tenant, string logoBase64, string logoFileName)
+    {
+        // 旧图标文件相对路径
+        var oldSysLogoRelativeFilePath = tenant.Logo ?? "";
+        var oldSysLogoAbsoluteFilePath = Path.Combine(App.WebHostEnvironment.WebRootPath, oldSysLogoRelativeFilePath.TrimStart('/'));
+
+        var groups = Regex.Match(logoBase64, @"data:image/(?<type>.+?);base64,(?<data>.+)").Groups;
+        
+        //var type = groups["type"].Value;
+        var base64Data = groups["data"].Value;
+        var binData = Convert.FromBase64String(base64Data);
+        
+        // 根据文件名取扩展名
+        var ext = string.IsNullOrWhiteSpace(logoFileName) ? ".png" : Path.GetExtension(logoFileName);
+        
+        // 本地图标保存路径
+        var fileName = $"{tenant.ViceTitle}-logo{ext}".ToLower();
+        var path = _uploadOptions.Path.Replace("/{yyyy}/{MM}/{dd}", "");
+        path = path.StartsWith("/") || Regex.IsMatch(path, "^[A-Z|a-z]:") ? path : Path.Combine(App.WebHostEnvironment.WebRootPath, path);
+        var absoluteFilePath = Path.Combine(path, fileName);
+
+        // 删除已存在文件
+        if (File.Exists(oldSysLogoAbsoluteFilePath)) File.Delete(oldSysLogoAbsoluteFilePath);
+
+        // 创建文件夹
+        var absoluteFileDir = Path.GetDirectoryName(absoluteFilePath);
+        if (!Directory.Exists(absoluteFileDir)) Directory.CreateDirectory(absoluteFileDir);
+
+        // 保存图标文件
+        File.WriteAllBytesAsync(absoluteFilePath, binData);
+
+        // 保存图标配置
+        tenant.Logo = $"/upload/{fileName}";
+    }
+
     /// <summary>
     /// 设置租户状态 🔖
     /// </summary>
@@ -183,51 +259,72 @@ public class SysTenantService : IDynamicApiController, ITransient
         var newOrg = new SysOrg { TenantId = tenantId, Pid = 0, Name = tenantName, Code = tenantName, Remark = tenantName, };
         await _sysOrgRep.InsertAsync(newOrg);
 
-        // 初始化角色
-        var newRole = new SysRole { TenantId = tenantId, Name = "租管-" + tenantName, Code = CommonConst.SysAdminRole, DataScope = DataScopeEnum.All, Remark = tenantName };
-        await _sysRoleRep.InsertAsync(newRole);
-
         // 初始化职位
-        var newPos = new SysPos { TenantId = tenantId, Name = "管-" + tenantName, Code = tenantName, Remark = tenantName };
+        var newPos = new SysPos { TenantId = tenantId, Name = "管理员-" + tenantName, Code = tenantName, Remark = tenantName };
         await _sysPosRep.InsertAsync(newPos);
 
-        // 初始化系统账号
+        // 初始化租户管理员账号
         var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
         var newUser = new SysUser
         {
             TenantId = tenantId,
             Account = tenant.AdminAccount,
             Password = CryptogramUtil.Encrypt(password),
-            NickName = "租管",
+            NickName = "系统管理员",
             Email = tenant.Email,
             Phone = tenant.Phone,
             AccountType = AccountTypeEnum.SysAdmin,
             OrgId = newOrg.Id,
             PosId = newPos.Id,
             Birthday = DateTime.Parse("2000-01-01"),
-            RealName = "租管",
-            Remark = "租管" + tenantName,
+            RealName = "系统管理员",
+            Remark = "系统管理员" + tenantName,
         };
         await _sysUserRep.InsertAsync(newUser);
 
-        // 关联用户及角色
-        var newUserRole = new SysUserRole { RoleId = newRole.Id, UserId = newUser.Id };
-        await _userRoleRep.InsertAsync(newUserRole);
-
         // 关联租户组织机构和管理员用户
         await _sysTenantRep.UpdateAsync(u => new SysTenant { UserId = newUser.Id, OrgId = newOrg.Id }, u => u.Id == tenantId);
 
         // 默认租户管理员角色菜单集合
-        var menuIdList = new List<long> { 1300000000111,1300000000121, // 工作台
-            1310000000111,1310000000112,1310000000113,1310000000114,1310000000115,1310000000116,1310000000117,1310000000118,1310000000119,1310000000120,1310000000121, // 账号
-            1310000000131,1310000000132,1310000000133,1310000000134,1310000000135,1310000000136,1310000000137,1310000000138, 1310000000322, // 角色
-            1310000000141,1310000000142,1310000000143,1310000000144,1310000000145, // 机构
-            1310000000151,1310000000152,1310000000153,1310000000154,1310000000155,1310000000156, // 职位
-            1310000000161,1310000000162,1310000000163,1310000000164,1310000000165, // 个人中心
-            1310000000171,1310000000172,1310000000173,1310000000174,1310000000175,1310000000176, // 通知公告
-            1310000000801  // 关于项目
-        };
-        await _sysRoleMenuService.GrantRoleMenu(new RoleMenuInput() { Id = newRole.Id, MenuIdList = menuIdList });
+        var menuList = GetTenantDefaultMenuList().ToList();
+        await GrantMenu(new TenantMenuInput { Id = tenantId, MenuIdList = menuList.Select(u => u.MenuId).ToList() });
+    }
+
+    /// <summary>
+    /// 获取租户默认菜单
+    /// </summary>
+    /// <param name="ignoreHome">如果某租户需要定制主页,可以忽略</param>
+    /// <returns></returns>
+    [NonAction]
+    public IEnumerable<SysTenantMenu> GetTenantDefaultMenuList(bool ignoreHome = false)
+    {
+        var id = 1300000000000;
+
+        var menuList = new List<SysMenu>();
+        var allMenuList = new SysMenuSeedData().HasData().ToList();
+
+        var dashboardMenu = allMenuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "工作台");
+        menuList.AddRange(allMenuList.ToChildList(u => u.Id, u => u.Pid, dashboardMenu.Id));
+        if (ignoreHome) menuList = menuList.Where(u => !(u.Type == MenuTypeEnum.Menu && u.Name == "home")).ToList();
+
+        var systemMenu = allMenuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "系统管理");
+        menuList.Add(systemMenu);
+        menuList.AddRange(allMenuList.ToChildList(u => u.Id, u => u.Pid, u => u.Pid == systemMenu.Id && new[]{ "账号管理", "角色管理", "机构管理", "职位管理", "个人中心", "通知公告" }.Contains(u.Title)));
+
+        var platformMenu = allMenuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "平台管理");
+        menuList.Add(platformMenu);
+        menuList.AddRange(allMenuList.ToChildList(u => u.Id, u => u.Pid, u => u.Pid == platformMenu.Id && new[]{ "菜单管理", "字典管理", "系统配置"}.Contains(u.Title)));
+        var dictMenu = menuList.First(u => u.Type == MenuTypeEnum.Menu && u.Title == "字典管理");
+        menuList = menuList.Where(u => u.Pid != dictMenu.Id || !new[]{"增加", "编辑", "删除"}.Contains(u.Title)).ToList();
+
+        var logMenu = allMenuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "日志管理");
+        menuList.Add(logMenu);
+        menuList.AddRange(allMenuList.ToChildList(u => u.Id, u => u.Pid, u => u.Pid == logMenu.Id && new[]{ "访问日志", "操作日志" }.Contains(u.Title)));
+
+        menuList.Add(allMenuList.First(u => u.Type == MenuTypeEnum.Dir && u.Title == "帮助文档"));
+        menuList.Add(allMenuList.First(u => u.Type == MenuTypeEnum.Menu && u.Title == "关于项目"));
+
+        return menuList.Select(u => new SysTenantMenu { Id=id+=100, TenantId=SqlSugarConst.DefaultTenantId, MenuId=u.Id });
     }
 
     /// <summary>
@@ -235,6 +332,7 @@ public class SysTenantService : IDynamicApiController, ITransient
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
+    [UnitOfWork]
     [ApiDescriptionSettings(Name = "Delete"), HttpPost]
     [DisplayName("删除租户")]
     public async Task DeleteTenant(DeleteTenantInput input)
@@ -251,6 +349,12 @@ public class SysTenantService : IDynamicApiController, ITransient
         await CacheTenant(input.Id);
 
         // 删除与租户相关的表数据
+        await _sysTenantMenuRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
+        var menuIds = await _sysTenantRep.Context.Queryable<SysMenu>().Select(u => u.Id).ToListAsync();
+        await _sysTenantRep.Context.Deleteable<SysRoleMenu>().Where(u => menuIds.Contains(u.Id)).ExecuteCommandAsync();
+        await _sysTenantRep.Context.Deleteable<SysUserMenu>().Where(u => menuIds.Contains(u.Id)).ExecuteCommandAsync();
+        await _sysTenantRep.Context.Deleteable<SysMenu>().Where(u => menuIds.Contains(u.Id)).ExecuteCommandAsync();
+        
         var users = await _sysUserRep.AsQueryable().ClearFilter().Where(u => u.TenantId == input.Id).ToListAsync();
         var userIds = users.Select(u => u.Id).ToList();
         await _sysUserRep.AsDeleteable().Where(u => userIds.Contains(u.Id)).ExecuteCommandAsync();
@@ -282,7 +386,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         var isExist = await _sysOrgRep.IsAnyAsync(u => u.Name == input.Name && u.Id != input.OrgId);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1300);
 
-        input.Host = input.Host.ToLower();
+        input.Host = input.Host?.ToLower();
         isExist = await _sysTenantRep.IsAnyAsync(u => u.Host == input.Host && u.Id != input.Id);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1303);
 
@@ -310,8 +414,12 @@ public class SysTenantService : IDynamicApiController, ITransient
         if (!string.IsNullOrWhiteSpace(input.SlaveConnections) && !JSON.IsValid(input.SlaveConnections))
             throw Oops.Oh(ErrorCodeEnum.D1302);
 
-        input.AppId = null;
-        await _sysTenantRep.AsUpdateable(input.Adapt<TenantOutput>()).IgnoreColumns(true).ExecuteCommandAsync();
+        // 设置logo
+        var tenant = input.Adapt<SysTenant>();
+        if (!string.IsNullOrWhiteSpace(input.LogoBase64)) SetLogoUrl(tenant, input.LogoBase64, input.LogoFileName);
+
+        // 更新租户信息
+        await _sysTenantRep.AsUpdateable(tenant).IgnoreColumns(true).ExecuteCommandAsync();
 
         // 更新系统机构
         await _sysOrgRep.UpdateAsync(u => new SysOrg() { Name = input.Name }, u => u.Id == input.OrgId);
@@ -323,33 +431,46 @@ public class SysTenantService : IDynamicApiController, ITransient
     }
 
     /// <summary>
-    /// 授权租户管理员角色菜单 🔖
+    /// 授权租户菜单 🔖
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
     [UnitOfWork]
-    [DisplayName("授权租户管理员角色菜单")]
-    public async Task GrantMenu(RoleMenuInput input)
+    [DisplayName("授权租户菜单")]
+    public async Task GrantMenu(TenantMenuInput input)
     {
-        // 获取租户管理员角色【sys_admin】
-        var adminRole = await _sysRoleRep.AsQueryable().ClearFilter()
-            .FirstAsync(u => u.Code == CommonConst.SysAdminRole && u.TenantId == input.Id && u.IsDelete == false);
-        if (adminRole == null) return;
-
-        input.Id = adminRole.Id; // 重置租户管理员角色Id
-        await _sysRoleMenuService.GrantRoleMenu(input);
+        // 获取需要授权的菜单列表
+        var menuList = await _sysTenantRep.Context.Queryable<SysMenu>().ClearFilter()
+            .Where(u => input.MenuIdList.Contains(u.Id))
+            .InnerJoin<SysTenantMenu>((u, t) => t.TenantId == input.Id && u.Id == t.MenuId)
+            .ToListAsync();
+
+        // 检查是否存在重复菜单
+        if (menuList.Where(u => u.Type != MenuTypeEnum.Btn).GroupBy(u => new { u.Pid, u.Title }).Any(u => u.Count() > 1) ||
+            menuList.Where(u => u.Type == MenuTypeEnum.Btn).GroupBy(u => u.Permission).Any(u => u.Count() > 1))
+            throw Oops.Oh(ErrorCodeEnum.D1304);
+        
+        // 检查路由是否重复
+        if (menuList.Where(u => !string.IsNullOrWhiteSpace(u.Name)).GroupBy(u => u.Name).Any(u => u.Count() > 1)) 
+            throw Oops.Oh(ErrorCodeEnum.D4009);
+        
+        await _sysTenantMenuRep.AsDeleteable().Where(u => u.TenantId == input.Id).ExecuteCommandAsync();
+        var sysTenantMenuList = input.MenuIdList.Select(menuId => new SysTenantMenu { TenantId = input.Id, MenuId = menuId }).ToList();
+        await _sysTenantMenuRep.InsertRangeAsync(sysTenantMenuList);
+        
+        // 清除菜单权限缓存
+        App.GetService<SysMenuService>().DeleteMenuCache();
     }
 
     /// <summary>
-    /// 获取租户管理员角色拥有菜单Id集合 🔖
+    /// 获取租户菜单Id集合 🔖
     /// </summary>
     /// <param name="input"></param>
     /// <returns></returns>
-    [DisplayName("获取租户管理员角色拥有菜单Id集合")]
-    public async Task<List<long>> GetOwnMenuList([FromQuery] TenantUserInput input)
+    [DisplayName("获取租户菜单Id集合")]
+    public async Task<List<long>> GetTenantMenuList([FromQuery] BaseIdInput input)
     {
-        var roleIds = await _sysUserRoleService.GetUserRoleIdList(input.UserId);
-        return await _sysRoleMenuService.GetRoleMenuIdList(new List<long> { roleIds[0] });
+        return await _sysTenantMenuRep.AsQueryable().Where(u => u.TenantId == input.Id).Select(u => u.MenuId).ToListAsync();
     }
 
     /// <summary>
@@ -362,9 +483,88 @@ public class SysTenantService : IDynamicApiController, ITransient
     {
         var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
         var encryptPassword = CryptogramUtil.Encrypt(password);
-        await _sysUserRep.UpdateAsync(u => new SysUser() { Password = encryptPassword }, u => u.Id == input.UserId);
+        await _sysUserRep.UpdateAsync(u => new SysUser { Password = encryptPassword }, u => u.Id == input.UserId);
         return password;
     }
+    
+    /// <summary>
+    /// 切换租户 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [UnitOfWork]
+    [DisplayName("切换租户")]
+    public async Task<LoginOutput> ChangeTenant(BaseIdInput input)
+    {
+        var userManager = App.GetService<UserManager>();
+
+        _ = await _sysTenantRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        var user = await _sysUserRep.GetFirstAsync(u => u.Id == userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        user.TenantId = input.Id;
+
+        return await GetAccessTokenInNotSingleLogin(user);
+    }
+    
+    /// <summary>
+    /// 进入租管端 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("进入租管端")]
+    public async Task<LoginOutput> GoTenant(BaseIdInput input)
+    {
+        var tenant = await _sysTenantRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        var user = await _sysUserRep.GetFirstAsync(u => u.Id == tenant.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        return await GetAccessTokenInNotSingleLogin(user);
+    }
+    
+    /// <summary>
+    /// 同步授权菜单(用于版本更新后,同步授权数据) 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [UnitOfWork]
+    [DisplayName("同步授权菜单")]
+    public async Task SyncGrantMenu(BaseIdInput input)
+    {
+        var menuIdList = input.Id == SqlSugarConst.DefaultTenantId
+            ? new SysMenuSeedData().HasData().Select(u => u.Id).ToList()
+            : await _sysRoleRep.AsQueryable().ClearFilter()
+              .InnerJoin<SysTenant>((u , t) => t.Id == input.Id && u.TenantId == t.Id)
+              .InnerJoin<SysRoleMenu>((u, t, rm) => u.Id == rm.RoleId)
+              .Select((u, t, rm) => rm.MenuId)
+              .Distinct()
+              .ToListAsync() ?? throw Oops.Oh(ErrorCodeEnum.D1019);
+        var adminRole = await _sysRoleRep.AsQueryable().ClearFilter().FirstAsync(u => u.TenantId == input.Id && u.Code == "sys_admin");
+        if (adminRole != null)
+        {
+            await _sysRoleRep.Context.Deleteable<SysUserRole>().Where(u => u.RoleId == adminRole.Id).ExecuteCommandAsync();
+            await App.GetService<SysRoleService>().DeleteRole(new DeleteRoleInput { Id = adminRole.Id });
+        }
+        await GrantMenu(new TenantMenuInput { Id = input.Id, MenuIdList = menuIdList });
+    }
+    
+    /// <summary>
+    /// 在非单用户登录模式下获取登录令牌
+    /// </summary>
+    /// <param name="user"></param>
+    /// <returns></returns>
+    [NonAction]
+    public async Task<LoginOutput> GetAccessTokenInNotSingleLogin(SysUser user)
+    {
+        // 使用非单用户模式登录
+        var singleLogin = _sysCacheService.Get<bool>($"{CacheConst.KeyConfig}{ConfigConst.SysSingleLogin}");
+        try
+        {
+            _sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysSingleLogin}", false);
+            return await App.GetService<SysAuthService>().CreateToken(user);
+        }
+        finally
+        {
+            // 恢复单用户登录参数
+            if (singleLogin) _sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysSingleLogin}", true);
+        }
+    }
 
     /// <summary>
     /// 缓存所有租户

+ 5 - 0
Admin.NET/Admin.NET.Core/Service/User/Dto/UserInput.cs

@@ -18,6 +18,11 @@ public class UserInput : BaseStatusInput
 /// </summary>
 public class PageUserInput : BasePageInput
 {
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
+    
     /// <summary>
     /// 账号
     /// </summary>

+ 73 - 0
Admin.NET/Admin.NET.Core/Service/User/Dto/UserRegWayInput.cs

@@ -0,0 +1,73 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 注册方案分页查询输入参数
+/// </summary>
+public class PageUserRegWayInput : BasePageInput
+{
+    /// <summary>
+    /// 方案名称
+    /// </summary>
+    public string? Name { get; set; }
+    
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
+}
+
+/// <summary>
+/// 注册方案增加输入参数
+/// </summary>
+public class AddUserRegWayInput : SysUserRegWay
+{
+    /// <summary>
+    /// 方案名称
+    /// </summary>
+    [Required(ErrorMessage = "方案名称不能为空")]
+    [MaxLength(32, ErrorMessage = "方案名称字符长度不能超过32")]
+    public override string Name { get; set; }
+    
+    /// <summary>
+    /// 账号类型
+    /// </summary>
+    [Dict(nameof(AccountTypeEnum), AllowNullValue=true)]
+    [Required(ErrorMessage = "账号类型不能为空")]
+    public override AccountTypeEnum AccountType { get; set; }
+    
+    /// <summary>
+    /// 角色
+    /// </summary>
+    [Required(ErrorMessage = "角色不能为空")]
+    public override long RoleId { get; set; }
+    
+    /// <summary>
+    /// 机构
+    /// </summary>
+    [Required(ErrorMessage = "机构不能为空")]
+    public override long OrgId { get; set; }
+    
+    /// <summary>
+    /// 职位
+    /// </summary>
+    [Required(ErrorMessage = "职位不能为空")]
+    public override long PosId { get; set; }
+}
+
+/// <summary>
+/// 注册方案更新输入参数
+/// </summary>
+public class UpdateUserRegWayInput : AddUserRegWayInput
+{
+    /// <summary>
+    /// 主键Id
+    /// </summary>    
+    [Required(ErrorMessage = "主键Id不能为空")]
+    public override long Id { get; set; }
+}

+ 28 - 0
Admin.NET/Admin.NET.Core/Service/User/Dto/UserRegWayOutput.cs

@@ -0,0 +1,28 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 注册方案输出参数
+/// </summary>
+public class UserRegWayOutput : SysUserRegWay
+{
+    /// <summary>
+    /// 角色名称
+    /// </summary>
+    public string RoleName { get; set; }   
+    
+    /// <summary>
+    /// 机构名称
+    /// </summary>
+    public string OrgName { get; set; }
+    
+    /// <summary>
+    /// 职位名称
+    /// </summary>
+    public string PosName { get; set; }
+}

+ 118 - 0
Admin.NET/Admin.NET.Core/Service/User/SysUserRegWayService.cs

@@ -0,0 +1,118 @@
+// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。
+//
+// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。
+//
+// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!
+
+namespace Admin.NET.Core.Service;
+
+/// <summary>
+/// 系统用户服务 🧩
+/// </summary>
+[ApiDescriptionSettings(Order = 490)]
+public class SysUserRegWayService : IDynamicApiController, ITransient
+{
+    private readonly SqlSugarRepository<SysUserRegWay> _sysUserRegWayRep;
+    private readonly UserManager _userManager;
+
+    public SysUserRegWayService(SqlSugarRepository<SysUserRegWay> sysUserRegWayRep, UserManager userManager)
+    {
+        _sysUserRegWayRep = sysUserRegWayRep;
+        _userManager = userManager;
+    }
+    
+    /// <summary>
+    /// 查询注册方案列表 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("查询注册方案列表")]
+    [ApiDescriptionSettings(Name = "List"), HttpPost]
+    public async Task<List<UserRegWayOutput>> List(PageUserRegWayInput input)
+    {
+        input.Keyword = input.Keyword?.Trim();
+        var query = _sysUserRegWayRep.AsQueryable()
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Keyword), u => u.Name.Contains(input.Keyword))
+            .WhereIF(!string.IsNullOrWhiteSpace(input.Name), u => u.Name.Contains(input.Name.Trim()))
+            .LeftJoin<SysRole>((u, a) => u.RoleId == a.Id)
+            .LeftJoin<SysOrg>((u, a, b) => u.OrgId == b.Id)
+            .LeftJoin<SysPos>((u, a, b, c) => u.PosId == c.Id)
+            .Select((u, a, b, c) => new UserRegWayOutput
+            {
+                RoleName = a.Name,
+                OrgName = b.Name,
+                PosName = c.Name,
+            }, true);
+        return await query.OrderBuilder(input).ToListAsync();
+    }
+
+    /// <summary>
+    /// 增加注册方案 ➕
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("增加注册方案")]
+    [ApiDescriptionSettings(Name = "Add"), HttpPost]
+    public async Task<long> Add(AddUserRegWayInput input)
+    {
+        var entity = input.Adapt<SysUserRegWay>();
+        if (await _sysUserRegWayRep.IsAnyAsync(u => u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D2101);
+        
+        await CheckData(input);
+        return await _sysUserRegWayRep.InsertAsync(entity) ? entity.Id : 0;
+    }
+
+    /// <summary>
+    /// 更新注册方案 ✏️
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [DisplayName("更新注册方案")]
+    [ApiDescriptionSettings(Name = "Update"), HttpPost]
+    public async Task Update(UpdateUserRegWayInput input)
+    {
+        if (await _sysUserRegWayRep.IsAnyAsync(u => u.Id != input.Id && u.Name == input.Name)) throw Oops.Oh(ErrorCodeEnum.D2101);
+
+        await CheckData(input);
+        await _sysUserRegWayRep.AsUpdateable(input).ExecuteCommandAsync();
+    }
+
+    /// <summary>
+    /// 检查数据
+    /// </summary>
+    /// <param name="input"></param>
+    [NonAction]
+    public async Task CheckData(AddUserRegWayInput input)
+    {
+        // 检查外键数据是否存在
+        if (!await _sysUserRegWayRep.Context.Queryable<SysRole>().AnyAsync(u => u.Id == input.RoleId)) throw Oops.Oh(ErrorCodeEnum.D1036);
+        if (!await _sysUserRegWayRep.Context.Queryable<SysOrg>().AnyAsync(u => u.Id == input.OrgId)) throw Oops.Oh(ErrorCodeEnum.D2011);
+        if (!await _sysUserRegWayRep.Context.Queryable<SysPos>().AnyAsync(u => u.Id == input.PosId)) throw Oops.Oh(ErrorCodeEnum.D6003);
+        
+        // 禁止注册超级管理员和系统管理员
+        if (input.AccountType is AccountTypeEnum.SysAdmin or AccountTypeEnum.SuperAdmin) throw Oops.Oh(ErrorCodeEnum.D1037);
+    }
+
+    /// <summary>
+    /// 删除注册方案 ❌
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [UnitOfWork]
+    [DisplayName("删除注册方案")]
+    [ApiDescriptionSettings(Name = "Delete"), HttpPost]
+    public async Task Delete(BaseIdInput input)
+    {
+        var entity = await _sysUserRegWayRep.GetFirstAsync(u => u.Id == input.Id) ?? throw Oops.Oh(ErrorCodeEnum.D1002);
+        
+        // 关闭相关租户注册功能
+        await _sysUserRegWayRep.Context.Updateable(new SysTenant{ EnableReg = YesNoEnum.N, RegWayId = null })
+            .UpdateColumns(u => new { u.EnableReg, u.RegWayId })
+            .Where(u => u.RegWayId == input.Id)
+            .ExecuteCommandAsync();
+        
+        // 删除方案
+        await _sysUserRegWayRep.DeleteAsync(entity);
+    }
+}

+ 39 - 5
Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs

@@ -75,6 +75,8 @@ public class SysUserService : IDynamicApiController, ITransient
             .LeftJoin<SysPos>((u, a, b) => u.PosId == b.Id)
             .Where(u => u.AccountType != AccountTypeEnum.SuperAdmin)
             .WhereIF(orgList != null, u => orgList.Contains(u.OrgId))
+            .WhereIF(!_userManager.SuperAdmin, u => u.AccountType != AccountTypeEnum.SysAdmin)
+            .WhereIF(_userManager.SuperAdmin && input.TenantId > 0, u => u.TenantId == input.TenantId)
             .WhereIF(!string.IsNullOrWhiteSpace(input.Account), u => u.Account.Contains(input.Account))
             .WhereIF(!string.IsNullOrWhiteSpace(input.RealName), u => u.RealName.Contains(input.RealName))
             .WhereIF(!string.IsNullOrWhiteSpace(input.PosName), (u, a, b) => b.Name.Contains(input.PosName))
@@ -100,9 +102,7 @@ public class SysUserService : IDynamicApiController, ITransient
     [DisplayName("增加用户")]
     public virtual async Task<long> AddUser(AddUserInput input)
     {
-        // 是否租户隔离登录验证
-        var isTenantHostLogin = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysTenantHostLogin);
-        var query = _sysUserRep.AsQueryable().ClearFilter().WhereIF(isTenantHostLogin, u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
+        var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
 
         if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
         if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
@@ -125,6 +125,41 @@ public class SysUserService : IDynamicApiController, ITransient
 
         return newUser.Id;
     }
+    
+    /// <summary>
+    /// 增加用户 🔖
+    /// </summary>
+    /// <param name="input"></param>
+    /// <returns></returns>
+    [NonAction]
+    public virtual async Task<long> RegisterUser(AddUserInput input)
+    {
+        var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.TenantId == input.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
+
+        if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
+        if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);
+
+        if (string.IsNullOrWhiteSpace(input.Password))
+        {
+            var password = await _sysConfigService.GetConfigValue<string>(ConfigConst.SysPassword);
+            input.Password = CryptogramUtil.Encrypt(password);
+        }
+
+        var user = input.Adapt<SysUser>();
+        var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
+
+        input.Id = newUser.Id;
+        await UpdateRoleAndExtOrg(input);
+
+        // 增加域账号
+        if (!string.IsNullOrWhiteSpace(input.DomainAccount))
+            await _sysUserLdapService.AddUserLdap(newUser.TenantId!.Value, newUser.Id, newUser.Account, input.DomainAccount);
+
+        // 执行订阅事件
+        _sysUserEventHandler.OnEvent(this, SysUserEventTypeEnum.Register, input);
+
+        return newUser.Id;
+    }
 
     /// <summary>
     /// 更新用户 🔖
@@ -137,9 +172,8 @@ public class SysUserService : IDynamicApiController, ITransient
     public virtual async Task UpdateUser(UpdateUserInput input)
     {
         // 是否租户隔离登录验证
-        var isTenantHostLogin = await _sysConfigService.GetConfigValue<bool>(ConfigConst.SysTenantHostLogin);
         var query = _sysUserRep.AsQueryable().ClearFilter().Where(u => u.Id != input.Id)
-            .WhereIF(isTenantHostLogin, u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
+            .Where(u => u.TenantId == _userManager.TenantId || u.AccountType == AccountTypeEnum.SuperAdmin);
 
         if (await query.AnyAsync(u => u.Account == input.Account)) throw Oops.Oh(ErrorCodeEnum.D1003);
         if (!string.IsNullOrWhiteSpace(input.Phone) && await query.AnyAsync(u => u.Phone == input.Phone)) throw Oops.Oh(ErrorCodeEnum.D1032);

+ 6 - 6
Admin.NET/Admin.NET.Core/Service/User/UserManager.cs

@@ -12,12 +12,7 @@ namespace Admin.NET.Core;
 public class UserManager : IScoped
 {
     private readonly IHttpContextAccessor _httpContextAccessor;
-
-    /// <summary>
-    /// 应用ID
-    /// </summary>
-    public long AppId => (_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AppId)?.Value).ToLong();
-
+    
     /// <summary>
     /// 用户ID
     /// </summary>
@@ -37,6 +32,11 @@ public class UserManager : IScoped
     /// 真实姓名
     /// </summary>
     public string RealName => _httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.RealName)?.Value;
+    
+    /// <summary>
+    /// 是否超级管理员
+    /// </summary>
+    public AccountTypeEnum? AccountType => int.TryParse(_httpContextAccessor.HttpContext?.User.FindFirst(ClaimConst.AccountType)?.Value, out var val) ? (AccountTypeEnum?)val : null;
 
     /// <summary>
     /// 是否超级管理员

+ 5 - 5
Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs

@@ -52,8 +52,8 @@ public static class SqlSugarFilter
         var maxDataScope = SetDataScopeFilter(db);
         if (maxDataScope == 0 || maxDataScope == (int)DataScopeEnum.Self) return;
 
-        var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
-        if (string.IsNullOrWhiteSpace(userId)) return;
+        var userId = App.GetService<UserManager>()?.UserId;
+        if (userId == null) return;
 
         // 配置用户机构集合缓存
         var cacheKey = $"db:{db.CurrentConnectionConfig.ConfigId}:orgList:{userId}";
@@ -108,8 +108,8 @@ public static class SqlSugarFilter
     {
         var maxDataScope = (int)DataScopeEnum.All;
 
-        var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value;
-        if (string.IsNullOrWhiteSpace(userId)) return maxDataScope;
+        var userId = App.GetService<UserManager>().UserId;
+        if (userId <= 0) return maxDataScope;
 
         // 获取用户最大数据范围---仅本人数据
         maxDataScope = App.GetRequiredService<SysCacheService>().Get<int>(CacheConst.KeyRoleMaxDataScope + userId);
@@ -146,7 +146,7 @@ public static class SqlSugarFilter
 
                 //var lambda = DynamicExpressionParser.ParseLambda(new[] {
                 //    Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId);
-                var lambda = entityType.GetConditionExpression<OwnerUserAttribute>(new List<long> { long.Parse(userId) });
+                var lambda = entityType.GetConditionExpression<OwnerUserAttribute>(new List<long> { userId });
 
                 db.QueryFilter.AddTableFilter(entityType, lambda);
                 dataScopeFilter.TryAdd(entityType, lambda);

+ 4 - 4
Admin.NET/Admin.NET.Core/Utils/CommonUtil.cs

@@ -21,8 +21,9 @@ public static class CommonUtil
     /// 根据字符串获取固定整型哈希值
     /// </summary>
     /// <param name="str"></param>
+    /// <param name="startNumber"></param>
     /// <returns></returns>
-    public static int GetFixedHashCode(string str)
+    public static long GetFixedHashCode(string str, long startNumber=0)
     {
         if (string.IsNullOrWhiteSpace(str)) return 0;
         unchecked
@@ -32,11 +33,10 @@ public static class CommonUtil
             for (int i = 0; i < str.Length; i += 2)
             {
                 hash1 = ((hash1 << 5) + hash1) ^ str[i];
-                if (i == str.Length - 1)
-                    break;
+                if (i == str.Length - 1) break;
                 hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
             }
-            return Math.Abs(hash1 + (hash2 * 1566083941));
+            return startNumber + Math.Abs(hash1 + (hash2 * 1566083941));
         }
     }
 

+ 6 - 0
Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewSys/Dto/GoViewLoginInput.cs

@@ -22,4 +22,10 @@ public class GoViewLoginInput
     /// </summary>
     [Required(ErrorMessage = "密码不能为空")]
     public string Password { get; set; }
+
+    /// <summary>
+    /// 租户
+    /// </summary>
+    [Required(ErrorMessage = "租户不能为空")]
+    public long? TenantId { get; set; }
 }

+ 6 - 2
Admin.NET/Plugins/Admin.NET.Plugin.GoView/Service/GoViewSys/GoViewSysService.cs

@@ -30,11 +30,14 @@ public class GoViewSysService : IDynamicApiController
     /// GoView 登录 🔖
     /// </summary>
     /// <returns></returns>
+    [UnitOfWork]
     [AllowAnonymous]
     [DisplayName("GoView 登录")]
     public async Task<GoViewLoginOutput> Login(GoViewLoginInput input)
     {
-        _sysCacheService.Set($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}", false);
+        // 关闭验证码验证
+        var tenant = await _sysUserRep.Context.Queryable<SysTenant>().FirstAsync(u => u.Id == input.TenantId) ?? throw Oops.Oh(ErrorCodeEnum.Z1003);
+        if (tenant.Captcha == YesNoEnum.Y) await _sysUserRep.Context.Updateable(new SysTenant{ Captcha = YesNoEnum.N }).UpdateColumns(u => u.Captcha).ExecuteCommandAsync();
 
         input.Password = CryptogramUtil.SM2Encrypt(input.Password);
         var loginResult = await _sysAuthService.Login(new LoginInput()
@@ -43,7 +46,8 @@ public class GoViewSysService : IDynamicApiController
             Password = input.Password,
         });
 
-        _sysCacheService.Remove($"{CacheConst.KeyConfig}{ConfigConst.SysCaptcha}");
+        // 启用验证码
+        if (tenant.Captcha == YesNoEnum.Y) await _sysUserRep.Context.Updateable(new SysTenant{ Captcha = YesNoEnum.Y }).UpdateColumns(u => u.Captcha).ExecuteCommandAsync();
 
         var sysUser = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Account.Equals(input.Username));
         return new GoViewLoginOutput()

+ 1 - 7
Web/.env

@@ -2,7 +2,7 @@
 VITE_PORT = 8888
 
 # open 运行 npm run dev 时自动打开浏览器
-VITE_OPEN = false
+VITE_OPEN = true
 
 # 打包是否开启 cdn(源文件 utils/build.ts),可自行修改
 VITE_OPEN_CDN = false
@@ -10,11 +10,5 @@ VITE_OPEN_CDN = false
 # public path 配置线上环境路径(打包)、本地通过 http-server 访问时,请置空即可
 VITE_PUBLIC_PATH =
 
-# 登陆界面默认用户
-VITE_DEFAULT_USER = superadmin
-
-# 登陆界面默认密码
-VITE_DEFAULT_USER_PASSWORD = 123456
-
 # 国密SM公钥
 VITE_SM_PUBLIC_KEY = "0484C7466D950E120E5ECE5DD85D0C90EAA85081A3A2BD7C57AE6DC822EFCCBD66620C67B0103FC8DD280E36C3B282977B722AAEC3C56518EDCEBAFB72C5A05312"

+ 7 - 1
Web/.env.development

@@ -2,4 +2,10 @@
 ENV = development
 
 # 本地环境接口地址
-VITE_API_URL = http://localhost:5005
+VITE_API_URL = http://localhost:5005
+
+# 登陆界面默认用户
+VITE_DEFAULT_USER = superadmin
+
+# 登陆界面默认密码
+VITE_DEFAULT_USER_PASSWORD = 123456

+ 7 - 1
Web/.env.production

@@ -2,4 +2,10 @@
 ENV = production
 
 # 线上环境接口地址
-VITE_API_URL =
+VITE_API_URL =
+
+# 登陆界面默认用户
+VITE_DEFAULT_USER = 
+
+# 登陆界面默认密码
+VITE_DEFAULT_USER_PASSWORD = 

+ 14 - 12
Web/src/App.vue

@@ -118,29 +118,31 @@ const loadSysInfo = () => {
 
 			const data = res.data.result;
 			// 系统logo
-			themeConfig.value.logoUrl = data.sysLogo;
+			themeConfig.value.logoUrl = data.logo;
 			// 主标题
-			themeConfig.value.globalTitle = data.sysTitle;
+			themeConfig.value.globalTitle = data.title;
 			// 副标题
-			themeConfig.value.globalViceTitle = data.sysViceTitle;
+			themeConfig.value.globalViceTitle = data.viceTitle;
 			// 系统说明
-			themeConfig.value.globalViceTitleMsg = data.sysViceDesc;
+			themeConfig.value.globalViceTitleMsg = data.viceDesc;
 			// Icp备案信息
-			themeConfig.value.icp = data.sysIcp;
-			themeConfig.value.icpUrl = data.sysIcpUrl;
+			themeConfig.value.icp = data.icp;
+			themeConfig.value.icpUrl = data.icpUrl;
 			// 水印
-			themeConfig.value.isWatermark = data.sysWatermark != null;
-			themeConfig.value.watermarkText = data.sysWatermark;
+			themeConfig.value.isWatermark = data.watermark != null;
+			themeConfig.value.watermarkText = data.watermark;
 			// 版权说明
-			themeConfig.value.copyright = data.sysCopyright;
+			themeConfig.value.copyright = data.copyright;
 			// 登录验证
-			themeConfig.value.secondVer = data.sysSecondVer;
-			themeConfig.value.captcha = data.sysCaptcha;
+			themeConfig.value.secondVer = data.secondVer == 1;
+			themeConfig.value.captcha = data.captcha == 1;
+			// 注册功能
+			themeConfig.value.registration = data.enableReg == 1;
 			// 更新配置加载状态
 			themeConfig.value.isLoaded = true;
 
 			// 更新 favicon
-			updateFavicon(data.sysLogo);
+			updateFavicon(data.logo);
 
 			// 保存配置
 			Local.remove('themeConfig');

+ 1 - 1
Web/src/api-services/api.ts

@@ -11,7 +11,6 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */export * from './apis/apijsonapi';
-export * from './apis/sys-app-api';
 export * from './apis/sys-auth-api';
 export * from './apis/sys-cache-api';
 export * from './apis/sys-code-gen-api';
@@ -50,6 +49,7 @@ export * from './apis/sys-sms-api';
 export * from './apis/sys-tenant-api';
 export * from './apis/sys-user-api';
 export * from './apis/sys-user-menu-api';
+export * from './apis/sys-user-reg-way-api';
 export * from './apis/sys-wechat-api';
 export * from './apis/sys-wechat-pay-api';
 export * from './apis/sys-wechat-user-api';

+ 0 - 720
Web/src/api-services/apis/sys-app-api.ts

@@ -1,720 +0,0 @@
-/* tslint:disable */
-/* eslint-disable */
-/**
- * Admin.NET 通用权限开发平台
- * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
- *
- * OpenAPI spec version: 1.0.0
- * 
- *
- * NOTE: This class is auto generated by the swagger code generator program.
- * https://github.com/swagger-api/swagger-codegen.git
- * Do not edit the class manually.
- */
-import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
-import { Configuration } from '../configuration';
-// Some imports not used depending on template conditions
-// @ts-ignore
-import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
-import { AddSysAppInput } from '../models';
-import { AdminResultInt64 } from '../models';
-import { AdminResultListInt64 } from '../models';
-import { AdminResultLoginOutput } from '../models';
-import { AdminResultObject } from '../models';
-import { AdminResultSqlSugarPagedListSysAppOutput } from '../models';
-import { BaseIdInput } from '../models';
-import { BasePageInput } from '../models';
-import { ChangeAppInput } from '../models';
-import { UpdateAppMenuInput } from '../models';
-import { UpdateSysAppInput } from '../models';
-/**
- * SysAppApi - axios parameter creator
- * @export
- */
-export const SysAppApiAxiosParamCreator = function (configuration?: Configuration) {
-    return {
-        /**
-         * 
-         * @summary 增加应用 🔖
-         * @param {AddSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppAddPost: async (body?: AddSysAppInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/add`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 获取切换应用数据 🔖
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppChangeAppGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/changeApp`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 切换应用 🔖
-         * @param {ChangeAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppChangeAppPost: async (body?: ChangeAppInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/changeApp`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 删除应用 🔖
-         * @param {BaseIdInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppDeletePost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/delete`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 获取授权菜单 🔖
-         * @param {number} [id] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppGrantMenuGet: async (id?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/grantMenu`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            if (id !== undefined) {
-                localVarQueryParameter['id'] = id;
-            }
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 授权菜单 🔖
-         * @param {UpdateAppMenuInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppGrantMenuPost: async (body?: UpdateAppMenuInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/grantMenu`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 分页查询应用 🔖
-         * @param {BasePageInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppPagePost: async (body?: BasePageInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/page`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-        /**
-         * 
-         * @summary 更新应用 🔖
-         * @param {UpdateSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        apiSysAppUpdatePost: async (body?: UpdateSysAppInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysApp/update`;
-            // use dummy base URL string because the URL constructor only accepts absolute URLs.
-            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
-            let baseOptions;
-            if (configuration) {
-                baseOptions = configuration.baseOptions;
-            }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
-            const localVarHeaderParameter = {} as any;
-            const localVarQueryParameter = {} as any;
-
-            // authentication Bearer required
-            // http bearer authentication required
-            if (configuration && configuration.accessToken) {
-                const accessToken = typeof configuration.accessToken === 'function'
-                    ? await configuration.accessToken()
-                    : await configuration.accessToken;
-                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
-            }
-
-            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
-
-            const query = new URLSearchParams(localVarUrlObj.search);
-            for (const key in localVarQueryParameter) {
-                query.set(key, localVarQueryParameter[key]);
-            }
-            for (const key in options.params) {
-                query.set(key, options.params[key]);
-            }
-            localVarUrlObj.search = (new URLSearchParams(query)).toString();
-            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
-            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
-            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
-            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
-
-            return {
-                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
-                options: localVarRequestOptions,
-            };
-        },
-    }
-};
-
-/**
- * SysAppApi - functional programming interface
- * @export
- */
-export const SysAppApiFp = function(configuration?: Configuration) {
-    return {
-        /**
-         * 
-         * @summary 增加应用 🔖
-         * @param {AddSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppAddPost(body?: AddSysAppInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultInt64>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppAddPost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 获取切换应用数据 🔖
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppChangeAppGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppChangeAppGet(options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 切换应用 🔖
-         * @param {ChangeAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppChangeAppPost(body?: ChangeAppInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultLoginOutput>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppChangeAppPost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 删除应用 🔖
-         * @param {BaseIdInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppDeletePost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 获取授权菜单 🔖
-         * @param {number} [id] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppGrantMenuGet(id?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListInt64>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppGrantMenuGet(id, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 授权菜单 🔖
-         * @param {UpdateAppMenuInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppGrantMenuPost(body?: UpdateAppMenuInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppGrantMenuPost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 分页查询应用 🔖
-         * @param {BasePageInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppPagePost(body?: BasePageInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultSqlSugarPagedListSysAppOutput>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppPagePost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-        /**
-         * 
-         * @summary 更新应用 🔖
-         * @param {UpdateSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppUpdatePost(body?: UpdateSysAppInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
-            const localVarAxiosArgs = await SysAppApiAxiosParamCreator(configuration).apiSysAppUpdatePost(body, options);
-            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
-                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
-                return axios.request(axiosRequestArgs);
-            };
-        },
-    }
-};
-
-/**
- * SysAppApi - factory interface
- * @export
- */
-export const SysAppApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
-    return {
-        /**
-         * 
-         * @summary 增加应用 🔖
-         * @param {AddSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppAddPost(body?: AddSysAppInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt64>> {
-            return SysAppApiFp(configuration).apiSysAppAddPost(body, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 获取切换应用数据 🔖
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppChangeAppGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysAppApiFp(configuration).apiSysAppChangeAppGet(options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 切换应用 🔖
-         * @param {ChangeAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppChangeAppPost(body?: ChangeAppInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultLoginOutput>> {
-            return SysAppApiFp(configuration).apiSysAppChangeAppPost(body, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 删除应用 🔖
-         * @param {BaseIdInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysAppApiFp(configuration).apiSysAppDeletePost(body, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 获取授权菜单 🔖
-         * @param {number} [id] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppGrantMenuGet(id?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListInt64>> {
-            return SysAppApiFp(configuration).apiSysAppGrantMenuGet(id, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 授权菜单 🔖
-         * @param {UpdateAppMenuInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppGrantMenuPost(body?: UpdateAppMenuInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysAppApiFp(configuration).apiSysAppGrantMenuPost(body, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 分页查询应用 🔖
-         * @param {BasePageInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppPagePost(body?: BasePageInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultSqlSugarPagedListSysAppOutput>> {
-            return SysAppApiFp(configuration).apiSysAppPagePost(body, options).then((request) => request(axios, basePath));
-        },
-        /**
-         * 
-         * @summary 更新应用 🔖
-         * @param {UpdateSysAppInput} [body] 
-         * @param {*} [options] Override http request option.
-         * @throws {RequiredError}
-         */
-        async apiSysAppUpdatePost(body?: UpdateSysAppInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
-            return SysAppApiFp(configuration).apiSysAppUpdatePost(body, options).then((request) => request(axios, basePath));
-        },
-    };
-};
-
-/**
- * SysAppApi - object-oriented interface
- * @export
- * @class SysAppApi
- * @extends {BaseAPI}
- */
-export class SysAppApi extends BaseAPI {
-    /**
-     * 
-     * @summary 增加应用 🔖
-     * @param {AddSysAppInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppAddPost(body?: AddSysAppInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt64>> {
-        return SysAppApiFp(this.configuration).apiSysAppAddPost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 获取切换应用数据 🔖
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppChangeAppGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysAppApiFp(this.configuration).apiSysAppChangeAppGet(options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 切换应用 🔖
-     * @param {ChangeAppInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppChangeAppPost(body?: ChangeAppInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultLoginOutput>> {
-        return SysAppApiFp(this.configuration).apiSysAppChangeAppPost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 删除应用 🔖
-     * @param {BaseIdInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysAppApiFp(this.configuration).apiSysAppDeletePost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 获取授权菜单 🔖
-     * @param {number} [id] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppGrantMenuGet(id?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListInt64>> {
-        return SysAppApiFp(this.configuration).apiSysAppGrantMenuGet(id, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 授权菜单 🔖
-     * @param {UpdateAppMenuInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppGrantMenuPost(body?: UpdateAppMenuInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysAppApiFp(this.configuration).apiSysAppGrantMenuPost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 分页查询应用 🔖
-     * @param {BasePageInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppPagePost(body?: BasePageInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultSqlSugarPagedListSysAppOutput>> {
-        return SysAppApiFp(this.configuration).apiSysAppPagePost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-    /**
-     * 
-     * @summary 更新应用 🔖
-     * @param {UpdateSysAppInput} [body] 
-     * @param {*} [options] Override http request option.
-     * @throws {RequiredError}
-     * @memberof SysAppApi
-     */
-    public async apiSysAppUpdatePost(body?: UpdateSysAppInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
-        return SysAppApiFp(this.configuration).apiSysAppUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
-    }
-}

+ 84 - 0
Web/src/api-services/apis/sys-auth-api.ts

@@ -23,6 +23,7 @@ import { AdminResultObject } from '../models';
 import { AdminResultString } from '../models';
 import { LoginInput } from '../models';
 import { LoginPhoneInput } from '../models';
+import { UserRegistrationInput } from '../models';
 /**
  * SysAuthApi - axios parameter creator
  * @export
@@ -457,6 +458,54 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
             let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
             localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
 
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 用户注册
+         * @summary 用户注册 🔖
+         * @param {UserRegistrationInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysAuthUserRegistrationPost: async (body?: UserRegistrationInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysAuth/userRegistration`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
             return {
                 url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
                 options: localVarRequestOptions,
@@ -594,6 +643,20 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 用户注册
+         * @summary 用户注册 🔖
+         * @param {UserRegistrationInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysAuthUserRegistrationPost(body?: UserRegistrationInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).apiSysAuthUserRegistrationPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
     }
 };
 
@@ -690,6 +753,16 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         async apiSysAuthUserInfoGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultLoginUserOutput>> {
             return SysAuthApiFp(configuration).apiSysAuthUserInfoGet(options).then((request) => request(axios, basePath));
         },
+        /**
+         * 用户注册
+         * @summary 用户注册 🔖
+         * @param {UserRegistrationInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysAuthUserRegistrationPost(body?: UserRegistrationInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysAuthApiFp(configuration).apiSysAuthUserRegistrationPost(body, options).then((request) => request(axios, basePath));
+        },
     };
 };
 
@@ -796,4 +869,15 @@ export class SysAuthApi extends BaseAPI {
     public async apiSysAuthUserInfoGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultLoginUserOutput>> {
         return SysAuthApiFp(this.configuration).apiSysAuthUserInfoGet(options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 用户注册
+     * @summary 用户注册 🔖
+     * @param {UserRegistrationInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async apiSysAuthUserRegistrationPost(body?: UserRegistrationInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysAuthApiFp(this.configuration).apiSysAuthUserRegistrationPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
 }

+ 13 - 21
Web/src/api-services/apis/sys-menu-api.ts

@@ -130,12 +130,11 @@ export const SysMenuApiAxiosParamCreator = function (configuration?: Configurati
          * @summary 获取菜单列表 🔖
          * @param {string} [title] 标题
          * @param {MenuTypeEnum} [type] 菜单类型(1目录 2菜单 3按钮)
-         * @param {boolean} [all] 获取所有菜单
-         * @param {number} [appId] 应用Id
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysMenuListGet: async (title?: string, type?: MenuTypeEnum, all?: boolean, appId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysMenuListGet: async (title?: string, type?: MenuTypeEnum, tenantId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             const localVarPath = `/api/sysMenu/list`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@@ -164,12 +163,8 @@ export const SysMenuApiAxiosParamCreator = function (configuration?: Configurati
                 localVarQueryParameter['Type'] = type;
             }
 
-            if (all !== undefined) {
-                localVarQueryParameter['All'] = all;
-            }
-
-            if (appId !== undefined) {
-                localVarQueryParameter['AppId'] = appId;
+            if (tenantId !== undefined) {
+                localVarQueryParameter['TenantId'] = tenantId;
             }
 
             const query = new URLSearchParams(localVarUrlObj.search);
@@ -364,13 +359,12 @@ export const SysMenuApiFp = function(configuration?: Configuration) {
          * @summary 获取菜单列表 🔖
          * @param {string} [title] 标题
          * @param {MenuTypeEnum} [type] 菜单类型(1目录 2菜单 3按钮)
-         * @param {boolean} [all] 获取所有菜单
-         * @param {number} [appId] 应用Id
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, all?: boolean, appId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysMenu>>> {
-            const localVarAxiosArgs = await SysMenuApiAxiosParamCreator(configuration).apiSysMenuListGet(title, type, all, appId, options);
+        async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, tenantId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysMenu>>> {
+            const localVarAxiosArgs = await SysMenuApiAxiosParamCreator(configuration).apiSysMenuListGet(title, type, tenantId, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -450,13 +444,12 @@ export const SysMenuApiFactory = function (configuration?: Configuration, basePa
          * @summary 获取菜单列表 🔖
          * @param {string} [title] 标题
          * @param {MenuTypeEnum} [type] 菜单类型(1目录 2菜单 3按钮)
-         * @param {boolean} [all] 获取所有菜单
-         * @param {number} [appId] 应用Id
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, all?: boolean, appId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysMenu>> {
-            return SysMenuApiFp(configuration).apiSysMenuListGet(title, type, all, appId, options).then((request) => request(axios, basePath));
+        async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, tenantId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysMenu>> {
+            return SysMenuApiFp(configuration).apiSysMenuListGet(title, type, tenantId, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -523,14 +516,13 @@ export class SysMenuApi extends BaseAPI {
      * @summary 获取菜单列表 🔖
      * @param {string} [title] 标题
      * @param {MenuTypeEnum} [type] 菜单类型(1目录 2菜单 3按钮)
-     * @param {boolean} [all] 获取所有菜单
-     * @param {number} [appId] 应用Id
+     * @param {number} [tenantId] 租户Id
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysMenuApi
      */
-    public async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, all?: boolean, appId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysMenu>> {
-        return SysMenuApiFp(this.configuration).apiSysMenuListGet(title, type, all, appId, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysMenuListGet(title?: string, type?: MenuTypeEnum, tenantId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysMenu>> {
+        return SysMenuApiFp(this.configuration).apiSysMenuListGet(title, type, tenantId, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 15 - 7
Web/src/api-services/apis/sys-org-api.ts

@@ -130,10 +130,11 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
          * @param {string} [name] 名称
          * @param {string} [code] 编码
          * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysOrgListGet: async (id: number, name?: string, code?: string, type?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysOrgListGet: async (id: number, name?: string, code?: string, type?: string, tenantId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             // verify required parameter 'id' is not null or undefined
             if (id === null || id === undefined) {
                 throw new RequiredError('id','Required parameter id was null or undefined when calling apiSysOrgListGet.');
@@ -170,6 +171,10 @@ export const SysOrgApiAxiosParamCreator = function (configuration?: Configuratio
                 localVarQueryParameter['Type'] = type;
             }
 
+            if (tenantId !== undefined) {
+                localVarQueryParameter['TenantId'] = tenantId;
+            }
+
             if (id !== undefined) {
                 localVarQueryParameter['Id'] = id;
             }
@@ -282,11 +287,12 @@ export const SysOrgApiFp = function(configuration?: Configuration) {
          * @param {string} [name] 名称
          * @param {string} [code] 编码
          * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysOrg>>> {
-            const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).apiSysOrgListGet(id, name, code, type, options);
+        async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysOrg>>> {
+            const localVarAxiosArgs = await SysOrgApiAxiosParamCreator(configuration).apiSysOrgListGet(id, name, code, type, tenantId, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -342,11 +348,12 @@ export const SysOrgApiFactory = function (configuration?: Configuration, basePat
          * @param {string} [name] 名称
          * @param {string} [code] 编码
          * @param {string} [type] 机构类型
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysOrg>> {
-            return SysOrgApiFp(configuration).apiSysOrgListGet(id, name, code, type, options).then((request) => request(axios, basePath));
+        async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysOrg>> {
+            return SysOrgApiFp(configuration).apiSysOrgListGet(id, name, code, type, tenantId, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -397,12 +404,13 @@ export class SysOrgApi extends BaseAPI {
      * @param {string} [name] 名称
      * @param {string} [code] 编码
      * @param {string} [type] 机构类型
+     * @param {number} [tenantId] 租户Id
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysOrgApi
      */
-    public async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysOrg>> {
-        return SysOrgApiFp(this.configuration).apiSysOrgListGet(id, name, code, type, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysOrgListGet(id: number, name?: string, code?: string, type?: string, tenantId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysOrg>> {
+        return SysOrgApiFp(this.configuration).apiSysOrgListGet(id, name, code, type, tenantId, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 15 - 7
Web/src/api-services/apis/sys-pos-api.ts

@@ -127,10 +127,11 @@ export const SysPosApiAxiosParamCreator = function (configuration?: Configuratio
          * @summary 获取职位列表 🔖
          * @param {string} [name] 名称
          * @param {string} [code] 编码
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysPosListGet: async (name?: string, code?: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+        apiSysPosListGet: async (name?: string, code?: string, tenantId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
             const localVarPath = `/api/sysPos/list`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
@@ -159,6 +160,10 @@ export const SysPosApiAxiosParamCreator = function (configuration?: Configuratio
                 localVarQueryParameter['Code'] = code;
             }
 
+            if (tenantId !== undefined) {
+                localVarQueryParameter['TenantId'] = tenantId;
+            }
+
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -265,11 +270,12 @@ export const SysPosApiFp = function(configuration?: Configuration) {
          * @summary 获取职位列表 🔖
          * @param {string} [name] 名称
          * @param {string} [code] 编码
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysPosListGet(name?: string, code?: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysPos>>> {
-            const localVarAxiosArgs = await SysPosApiAxiosParamCreator(configuration).apiSysPosListGet(name, code, options);
+        async apiSysPosListGet(name?: string, code?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysPos>>> {
+            const localVarAxiosArgs = await SysPosApiAxiosParamCreator(configuration).apiSysPosListGet(name, code, tenantId, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -323,11 +329,12 @@ export const SysPosApiFactory = function (configuration?: Configuration, basePat
          * @summary 获取职位列表 🔖
          * @param {string} [name] 名称
          * @param {string} [code] 编码
+         * @param {number} [tenantId] 租户Id
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysPosListGet(name?: string, code?: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysPos>> {
-            return SysPosApiFp(configuration).apiSysPosListGet(name, code, options).then((request) => request(axios, basePath));
+        async apiSysPosListGet(name?: string, code?: string, tenantId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysPos>> {
+            return SysPosApiFp(configuration).apiSysPosListGet(name, code, tenantId, options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -376,12 +383,13 @@ export class SysPosApi extends BaseAPI {
      * @summary 获取职位列表 🔖
      * @param {string} [name] 名称
      * @param {string} [code] 编码
+     * @param {number} [tenantId] 租户Id
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysPosApi
      */
-    public async apiSysPosListGet(name?: string, code?: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysPos>> {
-        return SysPosApiFp(this.configuration).apiSysPosListGet(name, code, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysPosListGet(name?: string, code?: string, tenantId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysPos>> {
+        return SysPosApiFp(this.configuration).apiSysPosListGet(name, code, tenantId, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 

+ 364 - 33
Web/src/api-services/apis/sys-tenant-api.ts

@@ -20,13 +20,16 @@ import { AddTenantInput } from '../models';
 import { AdminResultInt32 } from '../models';
 import { AdminResultListInt64 } from '../models';
 import { AdminResultListSysUser } from '../models';
+import { AdminResultLoginOutput } from '../models';
+import { AdminResultObject } from '../models';
 import { AdminResultSqlSugarPagedListTenantOutput } from '../models';
 import { AdminResultString } from '../models';
+import { BaseIdInput } from '../models';
 import { DeleteTenantInput } from '../models';
 import { PageTenantInput } from '../models';
-import { RoleMenuInput } from '../models';
 import { TenantIdInput } from '../models';
 import { TenantInput } from '../models';
+import { TenantMenuInput } from '../models';
 import { TenantUserInput } from '../models';
 import { UpdateTenantInput } from '../models';
 /**
@@ -83,6 +86,54 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 切换租户 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysTenantChangeTenantPost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysTenant/changeTenant`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 创建租户数据库 🔖
@@ -181,13 +232,13 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 授权租户管理员角色菜单 🔖
-         * @param {RoleMenuInput} [body] 
+         * @summary 进入租管端 🔖
+         * @param {BaseIdInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysTenantGrantMenuPost: async (body?: RoleMenuInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysTenant/grantMenu`;
+        apiSysTenantGoTenantPost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysTenant/goTenant`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -229,20 +280,20 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
         },
         /**
          * 
-         * @summary 获取租户管理员角色拥有菜单Id集合 🔖
-         * @param {number} [userId] 用户Id
+         * @summary 授权租户菜单 🔖
+         * @param {TenantMenuInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        apiSysTenantOwnMenuListGet: async (userId?: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/api/sysTenant/ownMenuList`;
+        apiSysTenantGrantMenuPost: async (body?: TenantMenuInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysTenant/grantMenu`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
             if (configuration) {
                 baseOptions = configuration.baseOptions;
             }
-            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
@@ -255,8 +306,51 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
                 localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
             }
 
-            if (userId !== undefined) {
-                localVarQueryParameter['UserId'] = userId;
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 获取租户列表
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysTenantListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysTenant/list`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
             }
 
             const query = new URLSearchParams(localVarUrlObj.search);
@@ -419,6 +513,106 @@ export const SysTenantApiAxiosParamCreator = function (configuration?: Configura
                 options: localVarRequestOptions,
             };
         },
+        /**
+         * 
+         * @summary 同步授权菜单(用于版本更新后,同步授权数据) 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysTenantSyncGrantMenuPost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysTenant/syncGrantMenu`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 获取租户菜单Id集合 🔖
+         * @param {number} id 主键Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysTenantTenantMenuListGet: async (id: number, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'id' is not null or undefined
+            if (id === null || id === undefined) {
+                throw new RequiredError('id','Required parameter id was null or undefined when calling apiSysTenantTenantMenuListGet.');
+            }
+            const localVarPath = `/api/sysTenant/tenantMenuList`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            if (id !== undefined) {
+                localVarQueryParameter['Id'] = id;
+            }
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
         /**
          * 
          * @summary 更新租户 🔖
@@ -538,6 +732,20 @@ export const SysTenantApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 切换租户 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantChangeTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultLoginOutput>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantChangeTenantPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 创建租户数据库 🔖
@@ -568,12 +776,26 @@ export const SysTenantApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 授权租户管理员角色菜单 🔖
-         * @param {RoleMenuInput} [body] 
+         * @summary 进入租管端 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantGoTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultLoginOutput>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantGoTenantPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 授权租户菜单 🔖
+         * @param {TenantMenuInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysTenantGrantMenuPost(body?: RoleMenuInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+        async apiSysTenantGrantMenuPost(body?: TenantMenuInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
             const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantGrantMenuPost(body, options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
@@ -582,13 +804,12 @@ export const SysTenantApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取租户管理员角色拥有菜单Id集合 🔖
-         * @param {number} [userId] 用户Id
+         * @summary 获取租户列表
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysTenantOwnMenuListGet(userId?: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListInt64>>> {
-            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantOwnMenuListGet(userId, options);
+        async apiSysTenantListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantListGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -636,6 +857,34 @@ export const SysTenantApiFp = function(configuration?: Configuration) {
                 return axios.request(axiosRequestArgs);
             };
         },
+        /**
+         * 
+         * @summary 同步授权菜单(用于版本更新后,同步授权数据) 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantSyncGrantMenuPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantSyncGrantMenuPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 获取租户菜单Id集合 🔖
+         * @param {number} id 主键Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantTenantMenuListGet(id: number, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListInt64>>> {
+            const localVarAxiosArgs = await SysTenantApiAxiosParamCreator(configuration).apiSysTenantTenantMenuListGet(id, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
         /**
          * 
          * @summary 更新租户 🔖
@@ -683,6 +932,16 @@ export const SysTenantApiFactory = function (configuration?: Configuration, base
         async apiSysTenantAddPost(body?: AddTenantInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysTenantApiFp(configuration).apiSysTenantAddPost(body, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 切换租户 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantChangeTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultLoginOutput>> {
+            return SysTenantApiFp(configuration).apiSysTenantChangeTenantPost(body, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 创建租户数据库 🔖
@@ -705,23 +964,32 @@ export const SysTenantApiFactory = function (configuration?: Configuration, base
         },
         /**
          * 
-         * @summary 授权租户管理员角色菜单 🔖
-         * @param {RoleMenuInput} [body] 
+         * @summary 进入租管端 🔖
+         * @param {BaseIdInput} [body] 
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysTenantGrantMenuPost(body?: RoleMenuInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+        async apiSysTenantGoTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultLoginOutput>> {
+            return SysTenantApiFp(configuration).apiSysTenantGoTenantPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 授权租户菜单 🔖
+         * @param {TenantMenuInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantGrantMenuPost(body?: TenantMenuInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
             return SysTenantApiFp(configuration).apiSysTenantGrantMenuPost(body, options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取租户管理员角色拥有菜单Id集合 🔖
-         * @param {number} [userId] 用户Id
+         * @summary 获取租户列表
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async apiSysTenantOwnMenuListGet(userId?: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListInt64>> {
-            return SysTenantApiFp(configuration).apiSysTenantOwnMenuListGet(userId, options).then((request) => request(axios, basePath));
+        async apiSysTenantListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
+            return SysTenantApiFp(configuration).apiSysTenantListGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 
@@ -753,6 +1021,26 @@ export const SysTenantApiFactory = function (configuration?: Configuration, base
         async apiSysTenantSetStatusPost(body?: TenantInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt32>> {
             return SysTenantApiFp(configuration).apiSysTenantSetStatusPost(body, options).then((request) => request(axios, basePath));
         },
+        /**
+         * 
+         * @summary 同步授权菜单(用于版本更新后,同步授权数据) 🔖
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantSyncGrantMenuPost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysTenantApiFp(configuration).apiSysTenantSyncGrantMenuPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 获取租户菜单Id集合 🔖
+         * @param {number} id 主键Id
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysTenantTenantMenuListGet(id: number, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListInt64>> {
+            return SysTenantApiFp(configuration).apiSysTenantTenantMenuListGet(id, options).then((request) => request(axios, basePath));
+        },
         /**
          * 
          * @summary 更新租户 🔖
@@ -794,6 +1082,17 @@ export class SysTenantApi extends BaseAPI {
     public async apiSysTenantAddPost(body?: AddTenantInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysTenantApiFp(this.configuration).apiSysTenantAddPost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 切换租户 🔖
+     * @param {BaseIdInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysTenantApi
+     */
+    public async apiSysTenantChangeTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultLoginOutput>> {
+        return SysTenantApiFp(this.configuration).apiSysTenantChangeTenantPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 创建租户数据库 🔖
@@ -818,25 +1117,35 @@ export class SysTenantApi extends BaseAPI {
     }
     /**
      * 
-     * @summary 授权租户管理员角色菜单 🔖
-     * @param {RoleMenuInput} [body] 
+     * @summary 进入租管端 🔖
+     * @param {BaseIdInput} [body] 
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysTenantApi
      */
-    public async apiSysTenantGrantMenuPost(body?: RoleMenuInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+    public async apiSysTenantGoTenantPost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultLoginOutput>> {
+        return SysTenantApiFp(this.configuration).apiSysTenantGoTenantPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 授权租户菜单 🔖
+     * @param {TenantMenuInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysTenantApi
+     */
+    public async apiSysTenantGrantMenuPost(body?: TenantMenuInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
         return SysTenantApiFp(this.configuration).apiSysTenantGrantMenuPost(body, options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取租户管理员角色拥有菜单Id集合 🔖
-     * @param {number} [userId] 用户Id
+     * @summary 获取租户列表
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysTenantApi
      */
-    public async apiSysTenantOwnMenuListGet(userId?: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListInt64>> {
-        return SysTenantApiFp(this.configuration).apiSysTenantOwnMenuListGet(userId, options).then((request) => request(this.axios, this.basePath));
+    public async apiSysTenantListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
+        return SysTenantApiFp(this.configuration).apiSysTenantListGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
@@ -871,6 +1180,28 @@ export class SysTenantApi extends BaseAPI {
     public async apiSysTenantSetStatusPost(body?: TenantInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt32>> {
         return SysTenantApiFp(this.configuration).apiSysTenantSetStatusPost(body, options).then((request) => request(this.axios, this.basePath));
     }
+    /**
+     * 
+     * @summary 同步授权菜单(用于版本更新后,同步授权数据) 🔖
+     * @param {BaseIdInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysTenantApi
+     */
+    public async apiSysTenantSyncGrantMenuPost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysTenantApiFp(this.configuration).apiSysTenantSyncGrantMenuPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 获取租户菜单Id集合 🔖
+     * @param {number} id 主键Id
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysTenantApi
+     */
+    public async apiSysTenantTenantMenuListGet(id: number, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListInt64>> {
+        return SysTenantApiFp(this.configuration).apiSysTenantTenantMenuListGet(id, options).then((request) => request(this.axios, this.basePath));
+    }
     /**
      * 
      * @summary 更新租户 🔖

+ 391 - 0
Web/src/api-services/apis/sys-user-reg-way-api.ts

@@ -0,0 +1,391 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET 通用权限开发平台
+ * 让 .NET 开发更简单、更通用、更流行。整合最新技术,模块插件式开发,前后端分离,开箱即用。<br/><u><b><font color='FF0000'> 👮不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任!</font></b></u>
+ *
+ * OpenAPI spec version: 1.0.0
+ * 
+ *
+ * NOTE: This class is auto generated by the swagger code generator program.
+ * https://github.com/swagger-api/swagger-codegen.git
+ * Do not edit the class manually.
+ */
+import globalAxios, { AxiosResponse, AxiosInstance, AxiosRequestConfig } from 'axios';
+import { Configuration } from '../configuration';
+// Some imports not used depending on template conditions
+// @ts-ignore
+import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base';
+import { AddUserRegWayInput } from '../models';
+import { AdminResultInt64 } from '../models';
+import { AdminResultListUserRegWayOutput } from '../models';
+import { BaseIdInput } from '../models';
+import { PageUserRegWayInput } from '../models';
+import { UpdateUserRegWayInput } from '../models';
+/**
+ * SysUserRegWayApi - axios parameter creator
+ * @export
+ */
+export const SysUserRegWayApiAxiosParamCreator = function (configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary 增加注册方案 ➕
+         * @param {AddUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysUserRegWayAddPost: async (body?: AddUserRegWayInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysUserRegWay/add`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 删除注册方案 ❌
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysUserRegWayDeletePost: async (body?: BaseIdInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysUserRegWay/delete`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 查询注册方案列表 🔖
+         * @param {PageUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysUserRegWayListPost: async (body?: PageUserRegWayInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysUserRegWay/list`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+        /**
+         * 
+         * @summary 更新注册方案 ✏️
+         * @param {UpdateUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        apiSysUserRegWayUpdatePost: async (body?: UpdateUserRegWayInput, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/api/sysUserRegWay/update`;
+            // use dummy base URL string because the URL constructor only accepts absolute URLs.
+            const localVarUrlObj = new URL(localVarPath, 'https://example.com');
+            let baseOptions;
+            if (configuration) {
+                baseOptions = configuration.baseOptions;
+            }
+            const localVarRequestOptions :AxiosRequestConfig = { method: 'POST', ...baseOptions, ...options};
+            const localVarHeaderParameter = {} as any;
+            const localVarQueryParameter = {} as any;
+
+            // authentication Bearer required
+            // http bearer authentication required
+            if (configuration && configuration.accessToken) {
+                const accessToken = typeof configuration.accessToken === 'function'
+                    ? await configuration.accessToken()
+                    : await configuration.accessToken;
+                localVarHeaderParameter["Authorization"] = "Bearer " + accessToken;
+            }
+
+            localVarHeaderParameter['Content-Type'] = 'application/json-patch+json';
+
+            const query = new URLSearchParams(localVarUrlObj.search);
+            for (const key in localVarQueryParameter) {
+                query.set(key, localVarQueryParameter[key]);
+            }
+            for (const key in options.params) {
+                query.set(key, options.params[key]);
+            }
+            localVarUrlObj.search = (new URLSearchParams(query)).toString();
+            let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {};
+            localVarRequestOptions.headers = {...localVarHeaderParameter, ...headersFromBaseOptions, ...options.headers};
+            const needsSerialization = (typeof body !== "string") || localVarRequestOptions.headers['Content-Type'] === 'application/json';
+            localVarRequestOptions.data =  needsSerialization ? JSON.stringify(body !== undefined ? body : {}) : (body || "");
+
+            return {
+                url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash,
+                options: localVarRequestOptions,
+            };
+        },
+    }
+};
+
+/**
+ * SysUserRegWayApi - functional programming interface
+ * @export
+ */
+export const SysUserRegWayApiFp = function(configuration?: Configuration) {
+    return {
+        /**
+         * 
+         * @summary 增加注册方案 ➕
+         * @param {AddUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayAddPost(body?: AddUserRegWayInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultInt64>>> {
+            const localVarAxiosArgs = await SysUserRegWayApiAxiosParamCreator(configuration).apiSysUserRegWayAddPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 删除注册方案 ❌
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysUserRegWayApiAxiosParamCreator(configuration).apiSysUserRegWayDeletePost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 查询注册方案列表 🔖
+         * @param {PageUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayListPost(body?: PageUserRegWayInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListUserRegWayOutput>>> {
+            const localVarAxiosArgs = await SysUserRegWayApiAxiosParamCreator(configuration).apiSysUserRegWayListPost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
+         * @summary 更新注册方案 ✏️
+         * @param {UpdateUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayUpdatePost(body?: UpdateUserRegWayInput, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<void>>> {
+            const localVarAxiosArgs = await SysUserRegWayApiAxiosParamCreator(configuration).apiSysUserRegWayUpdatePost(body, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+    }
+};
+
+/**
+ * SysUserRegWayApi - factory interface
+ * @export
+ */
+export const SysUserRegWayApiFactory = function (configuration?: Configuration, basePath?: string, axios?: AxiosInstance) {
+    return {
+        /**
+         * 
+         * @summary 增加注册方案 ➕
+         * @param {AddUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayAddPost(body?: AddUserRegWayInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultInt64>> {
+            return SysUserRegWayApiFp(configuration).apiSysUserRegWayAddPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 删除注册方案 ❌
+         * @param {BaseIdInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysUserRegWayApiFp(configuration).apiSysUserRegWayDeletePost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 查询注册方案列表 🔖
+         * @param {PageUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayListPost(body?: PageUserRegWayInput, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListUserRegWayOutput>> {
+            return SysUserRegWayApiFp(configuration).apiSysUserRegWayListPost(body, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
+         * @summary 更新注册方案 ✏️
+         * @param {UpdateUserRegWayInput} [body] 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async apiSysUserRegWayUpdatePost(body?: UpdateUserRegWayInput, options?: AxiosRequestConfig): Promise<AxiosResponse<void>> {
+            return SysUserRegWayApiFp(configuration).apiSysUserRegWayUpdatePost(body, options).then((request) => request(axios, basePath));
+        },
+    };
+};
+
+/**
+ * SysUserRegWayApi - object-oriented interface
+ * @export
+ * @class SysUserRegWayApi
+ * @extends {BaseAPI}
+ */
+export class SysUserRegWayApi extends BaseAPI {
+    /**
+     * 
+     * @summary 增加注册方案 ➕
+     * @param {AddUserRegWayInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysUserRegWayApi
+     */
+    public async apiSysUserRegWayAddPost(body?: AddUserRegWayInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultInt64>> {
+        return SysUserRegWayApiFp(this.configuration).apiSysUserRegWayAddPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 删除注册方案 ❌
+     * @param {BaseIdInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysUserRegWayApi
+     */
+    public async apiSysUserRegWayDeletePost(body?: BaseIdInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysUserRegWayApiFp(this.configuration).apiSysUserRegWayDeletePost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 查询注册方案列表 🔖
+     * @param {PageUserRegWayInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysUserRegWayApi
+     */
+    public async apiSysUserRegWayListPost(body?: PageUserRegWayInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListUserRegWayOutput>> {
+        return SysUserRegWayApiFp(this.configuration).apiSysUserRegWayListPost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
+     * @summary 更新注册方案 ✏️
+     * @param {UpdateUserRegWayInput} [body] 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysUserRegWayApi
+     */
+    public async apiSysUserRegWayUpdatePost(body?: UpdateUserRegWayInput, options?: AxiosRequestConfig) : Promise<AxiosResponse<void>> {
+        return SysUserRegWayApiFp(this.configuration).apiSysUserRegWayUpdatePost(body, options).then((request) => request(this.axios, this.basePath));
+    }
+}

+ 6 - 0
Web/src/api-services/models/add-menu-input.ts

@@ -176,4 +176,10 @@ export interface AddMenuInput {
      * @memberof AddMenuInput
      */
     title: string;
+    /**
+     * 租户Id
+     * @type {number}
+     * @memberof AddMenuInput
+     */
+    tenantId?: number;
 }

+ 87 - 8
Web/src/api-services/models/add-tenant-input.ts

@@ -14,6 +14,7 @@
 import { DbType } from './db-type';
 import { StatusEnum } from './status-enum';
 import { TenantTypeEnum } from './tenant-type-enum';
+import { YesNoEnum } from './yes-no-enum';
 /**
  * 
  * @export
@@ -73,9 +74,9 @@ export interface AddTenantInput {
      * @type {number}
      * @memberof AddTenantInput
      */
-    appId: number;
+    appId?: number | null;
     /**
-     * 用户Id
+     * 租管用户Id
      * @type {number}
      * @memberof AddTenantInput
      */
@@ -116,6 +117,36 @@ export interface AddTenantInput {
      * @memberof AddTenantInput
      */
     slaveConnections?: string | null;
+    /**
+     * 
+     * @type {YesNoEnum}
+     * @memberof AddTenantInput
+     */
+    enableReg?: YesNoEnum;
+    /**
+     * 默认注册方案Id
+     * @type {number}
+     * @memberof AddTenantInput
+     */
+    regWayId?: number | null;
+    /**
+     * 
+     * @type {YesNoEnum}
+     * @memberof AddTenantInput
+     */
+    captcha?: YesNoEnum;
+    /**
+     * 
+     * @type {YesNoEnum}
+     * @memberof AddTenantInput
+     */
+    secondVer?: YesNoEnum;
+    /**
+     * 图标
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    logo: string;
     /**
      * 排序
      * @type {number}
@@ -134,12 +165,6 @@ export interface AddTenantInput {
      * @memberof AddTenantInput
      */
     status?: StatusEnum;
-    /**
-     * 关联应用名称
-     * @type {string}
-     * @memberof AddTenantInput
-     */
-    appName?: string | null;
     /**
      * 电子邮箱
      * @type {string}
@@ -170,4 +195,58 @@ export interface AddTenantInput {
      * @memberof AddTenantInput
      */
     host: string;
+    /**
+     * 系统主标题
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    title: string;
+    /**
+     * 系统副标题
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    viceTitle: string;
+    /**
+     * 系统描述
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    viceDesc: string;
+    /**
+     * 水印内容
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    watermark: string;
+    /**
+     * 版权说明
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    copyright: string;
+    /**
+     * ICP备案号
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    icp: string;
+    /**
+     * ICP地址
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    icpUrl: string;
+    /**
+     * Logo图片Base64码
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    logoBase64?: string | null;
+    /**
+     * Logo文件名
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    logoFileName?: string | null;
 }

+ 56 - 67
Web/src/api-services/models/sys-app-output.ts → Web/src/api-services/models/add-user-reg-way-input.ts

@@ -11,118 +11,107 @@
  * https://github.com/swagger-api/swagger-codegen.git
  * Do not edit the class manually.
  */
+import { AccountTypeEnum } from './account-type-enum';
 /**
- * 应用输出参数
+ * 注册方案增加输入参数
  * @export
- * @interface SysAppOutput
+ * @interface AddUserRegWayInput
  */
-export interface SysAppOutput {
+export interface AddUserRegWayInput {
     /**
-     * 主键Id
+     * 雪花Id
      * @type {number}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
     id?: number;
     /**
-     * 名称
-     * @type {string}
-     * @memberof SysAppOutput
+     * 创建时间
+     * @type {Date}
+     * @memberof AddUserRegWayInput
      */
-    name?: string | null;
+    createTime?: Date;
     /**
-     * 图标
-     * @type {string}
-     * @memberof SysAppOutput
+     * 更新时间
+     * @type {Date}
+     * @memberof AddUserRegWayInput
      */
-    logo?: string | null;
+    updateTime?: Date | null;
     /**
-     * 标题
-     * @type {string}
-     * @memberof SysAppOutput
+     * 创建者Id
+     * @type {number}
+     * @memberof AddUserRegWayInput
      */
-    title?: string | null;
+    createUserId?: number | null;
     /**
-     * 副标题
+     * 创建者姓名
      * @type {string}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
-    viceTitle?: string | null;
+    createUserName?: string | null;
     /**
-     * 副描述
-     * @type {string}
-     * @memberof SysAppOutput
+     * 修改者Id
+     * @type {number}
+     * @memberof AddUserRegWayInput
      */
-    viceDesc?: string | null;
+    updateUserId?: number | null;
     /**
-     * 水印
+     * 修改者姓名
      * @type {string}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
-    watermark?: string | null;
+    updateUserName?: string | null;
     /**
-     * 版权信息
-     * @type {string}
-     * @memberof SysAppOutput
+     * 软删除
+     * @type {boolean}
+     * @memberof AddUserRegWayInput
      */
-    copyright?: string | null;
+    isDelete?: boolean;
     /**
-     * ICP备案号
-     * @type {string}
-     * @memberof SysAppOutput
+     * 租户Id
+     * @type {number}
+     * @memberof AddUserRegWayInput
      */
-    icp?: string | null;
+    tenantId?: number | null;
     /**
      * 排序
      * @type {number}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
     orderNo?: number;
     /**
      * 备注
      * @type {string}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
     remark?: string | null;
     /**
-     * 创建时间
-     * @type {Date}
-     * @memberof SysAppOutput
+     * 方案名称
+     * @type {string}
+     * @memberof AddUserRegWayInput
      */
-    createTime?: Date | null;
+    name: string;
     /**
-     * 更新时间
-     * @type {Date}
-     * @memberof SysAppOutput
+     * 
+     * @type {AccountTypeEnum}
+     * @memberof AddUserRegWayInput
      */
-    updateTime?: Date | null;
+    accountType: AccountTypeEnum;
     /**
-     * 创建者Id
+     * 角色
      * @type {number}
-     * @memberof SysAppOutput
-     */
-    createUserId?: number | null;
-    /**
-     * 创建者姓名
-     * @type {string}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
-    createUserName?: string | null;
+    roleId: number;
     /**
-     * 修改者Id
+     * 机构
      * @type {number}
-     * @memberof SysAppOutput
-     */
-    updateUserId?: number | null;
-    /**
-     * 修改者姓名
-     * @type {string}
-     * @memberof SysAppOutput
+     * @memberof AddUserRegWayInput
      */
-    updateUserName?: string | null;
+    orgId: number;
     /**
-     * 软删除
-     * @type {boolean}
-     * @memberof SysAppOutput
+     * 职位
+     * @type {number}
+     * @memberof AddUserRegWayInput
      */
-    isDelete?: boolean;
+    posId: number;
 }

Nem az összes módosított fájl került megjelenítésre, mert túl sok fájl változott