Ver Fonte

1、验证码与默认密码开关与前端匹配 2、调整多库租户模式

zuohuaijun há 3 anos atrás
pai
commit
eaee14a2cd
25 ficheiros alterados com 458 adições e 101 exclusões
  1. 1 1
      Admin.NET/Admin.NET.Application/AppConfig.json
  2. 0 2
      Admin.NET/Admin.NET.Application/Service/TestService.cs
  3. 1 1
      Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj
  4. 48 10
      Admin.NET/Admin.NET.Core/Admin.NET.Core.xml
  5. 21 11
      Admin.NET/Admin.NET.Core/Const/CommonConst.cs
  6. 7 0
      Admin.NET/Admin.NET.Core/Entity/SysTenant.cs
  7. 1 1
      Admin.NET/Admin.NET.Core/Entity/SysUser.cs
  8. 3 3
      Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs
  9. 5 0
      Admin.NET/Admin.NET.Core/Service/Auth/Dto/LoginInput.cs
  10. 36 5
      Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs
  11. 2 2
      Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs
  12. 0 1
      Admin.NET/Admin.NET.Core/Service/Region/Dto/RegionInput.cs
  13. 3 3
      Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs
  14. 20 4
      Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs
  15. 10 3
      Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs
  16. 175 37
      Web/src/api-services/apis/sys-auth-api.ts
  17. 6 0
      Web/src/api-services/models/add-tenant-input.ts
  18. 57 0
      Web/src/api-services/models/admin-result-list-sys-tenant.ts
  19. 1 0
      Web/src/api-services/models/index.ts
  20. 6 0
      Web/src/api-services/models/login-input.ts
  21. 6 0
      Web/src/api-services/models/sys-tenant.ts
  22. 6 0
      Web/src/api-services/models/update-tenant-input.ts
  23. 38 11
      Web/src/views/login/component/account.vue
  24. 1 1
      Web/src/views/login/component/mobile.vue
  25. 4 5
      Web/src/views/login/index.vue

+ 1 - 1
Admin.NET/Admin.NET.Application/AppConfig.json

@@ -16,7 +16,7 @@
                 "ConfigId": "Test",
                 "DbType": "Sqlite",
                 "ConnectionString": "DataSource=./Test.db",
-                "EnableInitDb": true, // 启用库表初始化
+                "EnableInitDb": false, // 启用库表初始化
                 "EnableDiffLog": false // 启用库表差异日志
             }
         ]

+ 0 - 2
Admin.NET/Admin.NET.Application/Service/TestService.cs

@@ -1,6 +1,4 @@
 using Admin.NET.Application.Const;
-using AngleSharp;
-using AngleSharp.Html.Dom;
 using Furion.DatabaseAccessor;
 using Furion.FriendlyException;
 using Furion.Localization;

+ 1 - 1
Admin.NET/Admin.NET.Core/Admin.NET.Core.csproj

@@ -36,7 +36,7 @@
     <PackageReference Include="NETCore.MailKit" Version="2.1.0" />
     <PackageReference Include="NewLife.Redis" Version="5.0.2022.1101" />
     <PackageReference Include="OnceMi.AspNetCore.OSS" Version="1.1.9" />
-    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.19.0" />
+    <PackageReference Include="SKIT.FlurlHttpClient.Wechat.Api" Version="2.20.0" />
     <PackageReference Include="SKIT.FlurlHttpClient.Wechat.TenpayV3" Version="2.13.1" />
     <PackageReference Include="SqlSugarCore" Version="5.1.3.30" />
     <PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.21" />

+ 48 - 10
Admin.NET/Admin.NET.Core/Admin.NET.Core.xml

@@ -167,19 +167,14 @@
             通用常量
             </summary>
         </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysPassword">
-            <summary>
-            默认密码
-            </summary>
-        </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysAdminRoleCode">
+        <member name="F:Admin.NET.Core.CommonConst.SysDemoEnv">
             <summary>
-            系统管理员角色编码
+            演示环境开关
             </summary>
         </member>
-        <member name="F:Admin.NET.Core.CommonConst.SysDemoEnv">
+        <member name="F:Admin.NET.Core.CommonConst.SysPassword">
             <summary>
-            演示环境开关
+            默认密码
             </summary>
         </member>
         <member name="F:Admin.NET.Core.CommonConst.SysCaptcha">
@@ -192,9 +187,24 @@
             开启操作日志
             </summary>
         </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysTokenExpire">
+            <summary>
+            Token过期时间
+            </summary>
+        </member>
         <member name="F:Admin.NET.Core.CommonConst.SysSingleLogin">
             <summary>
-            开启当用户登录
+            单用户登录
+            </summary>
+        </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysTenantDb">
+            <summary>
+            开启多库租户
+            </summary>
+        </member>
+        <member name="F:Admin.NET.Core.CommonConst.SysAdminRole">
+            <summary>
+            系统管理员角色编码
             </summary>
         </member>
         <member name="F:Admin.NET.Core.CommonConst.SysSensitiveDetection">
@@ -1357,6 +1367,11 @@
             数据库连接
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.SysTenant.ConfigId">
+            <summary>
+            数据库标识
+            </summary>
+        </member>
         <member name="P:Admin.NET.Core.SysTenant.Order">
             <summary>
             排序
@@ -3805,6 +3820,11 @@
             验证码
             </summary>
         </member>
+        <member name="P:Admin.NET.Core.Service.LoginInput.TenantId">
+            <summary>
+            租户Id
+            </summary>
+        </member>
         <member name="T:Admin.NET.Core.Service.LoginOutput">
             <summary>
             用户登录结果
@@ -3906,12 +3926,24 @@
             退出系统
             </summary>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysAuthService.GetCaptchaFlag">
+            <summary>
+            是否启用验证码
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysAuthService.GetCaptcha">
             <summary>
             生成图片验证码
             </summary>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysAuthService.GetTenantDbList">
+            <summary>
+            是否启用多库租户
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysAuthService.SwaggerCheckUrl">
             <summary>
             Swagger登录检查
@@ -6080,6 +6112,12 @@
             <param name="input"></param>
             <returns></returns>
         </member>
+        <member name="M:Admin.NET.Core.Service.SysTenantService.GetTenantDbList">
+            <summary>
+            获取库隔离的租户列表
+            </summary>
+            <returns></returns>
+        </member>
         <member name="M:Admin.NET.Core.Service.SysTenantService.AddTenant(Admin.NET.Core.Service.AddTenantInput)">
             <summary>
             增加租户

+ 21 - 11
Admin.NET/Admin.NET.Core/Const/CommonConst.cs

@@ -6,19 +6,14 @@
 public class CommonConst
 {
     /// <summary>
-    /// 默认密码
-    /// </summary>
-    public const string SysPassword = "123456";
-
-    /// <summary>
-    /// 系统管理员角色编码
+    /// 演示环境开关
     /// </summary>
-    public const string SysAdminRoleCode = "sys_admin";
+    public const string SysDemoEnv = "sys_demo";
 
     /// <summary>
-    /// 演示环境开关
+    /// 默认密码
     /// </summary>
-    public const string SysDemoEnv = "sys_demo_env";
+    public const string SysPassword = "sys_password";
 
     /// <summary>
     /// 验证码开关
@@ -28,14 +23,29 @@ public class CommonConst
     /// <summary>
     /// 开启操作日志
     /// </summary>
-    public const string SysOpLog = "sys_op_log";
+    public const string SysOpLog = "sys_oplog";
+
+    /// <summary>
+    /// Token过期时间
+    /// </summary>
+    public const string SysTokenExpire = "sys_token_expire";
 
     /// <summary>
-    /// 开启当用户登录
+    /// 用户登录
     /// </summary>
     public const string SysSingleLogin = "sys_single_login";
 
     /// <summary>
+    /// 开启多库租户
+    /// </summary>
+    public const string SysTenantDb = "sys_tenant_db";
+
+    /// <summary>
+    /// 系统管理员角色编码
+    /// </summary>
+    public const string SysAdminRole = "sys_admin";
+
+    /// <summary>
     /// 开启全局脱敏处理(默认不开启)
     /// </summary>
     public static bool SysSensitiveDetection = false;

+ 7 - 0
Admin.NET/Admin.NET.Core/Entity/SysTenant.cs

@@ -61,6 +61,13 @@ public class SysTenant : EntityBase
     public string Connection { get; set; }
 
     /// <summary>
+    /// 数据库标识
+    /// </summary>
+    [SugarColumn(ColumnDescription = "数据库标识", Length = 64)]
+    [MaxLength(64)]
+    public string ConfigId { get; set; }
+
+    /// <summary>
     /// 排序
     /// </summary>
     [SugarColumn(ColumnDescription = "排序")]

+ 1 - 1
Admin.NET/Admin.NET.Core/Entity/SysUser.cs

@@ -20,7 +20,7 @@ public class SysUser : EntityTenant
     [MaxLength(64)]
     [System.Text.Json.Serialization.JsonIgnore]
     [JsonIgnore]
-    public virtual string Password { get; set; }  = CommonConst.SysPassword;
+    public virtual string Password { get; set; }
 
     /// <summary>
     /// 真实姓名

+ 3 - 3
Admin.NET/Admin.NET.Core/SeedData/SysConfigSeedData.cs

@@ -13,13 +13,13 @@ public class SysConfigSeedData : ISqlSugarEntitySeedData<SysConfig>
     {
         return new[]
         {
-            new SysConfig{ Id=252885263003800, Name="演示环境", Code="sys_demo_env", Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", Order=1, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003800, Name="演示环境", Code="sys_demo", Value="False", SysFlag=YesNoEnum.Y, Remark="演示环境", Order=1, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003801, Name="默认密码", Code="sys_password", Value="123456", SysFlag=YesNoEnum.Y, Remark="默认密码", Order=2, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003802, Name="Token过期时间", Code="sys_token_expire", Value="10080", SysFlag=YesNoEnum.Y, Remark="Token过期时间", Order=3, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=252885263003803, Name="操作日志", Code="sys_op_log", Value="True", SysFlag=YesNoEnum.Y, Remark="开启操作日志", Order=4, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003803, Name="操作日志", Code="sys_oplog", Value="True", SysFlag=YesNoEnum.Y, Remark="开启操作日志", Order=4, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003804, Name="单点登录", Code="sys_single_login", Value="True", SysFlag=YesNoEnum.Y, Remark="开启单点登录", Order=5, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
             new SysConfig{ Id=252885263003805, Name="验证码", Code="sys_captcha", Value="True", SysFlag=YesNoEnum.Y, Remark="开启验证码", Order=6, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
-            new SysConfig{ Id=252885263003806, Name="管理员角色编码", Code="sys_admin_role", Value="True", SysFlag=YesNoEnum.Y, Remark="管理员角色编码", Order=7, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
+            new SysConfig{ Id=252885263003806, Name="多库租户", Code="sys_tenant_db", Value="True", SysFlag=YesNoEnum.Y, Remark="开启多库租户", Order=7, GroupCode="Default", CreateTime=DateTime.Parse("2022-02-10 00:00:00") },
         };
     }
 }

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

@@ -28,4 +28,9 @@ public class LoginInput
     /// 验证码
     /// </summary>
     public string Code { get; set; }
+
+    /// <summary>
+    /// 租户Id
+    /// </summary>
+    public long TenantId { get; set; }
 }

+ 36 - 5
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -15,9 +15,10 @@ public class SysAuthService : IDynamicApiController, ITransient
     private readonly RefreshTokenOptions _refreshTokenOptions;
     private readonly IHttpContextAccessor _httpContextAccessor;
     private readonly IEventPublisher _eventPublisher;
-    private readonly SysUserService _sysUserService;
     private readonly SysMenuService _sysMenuService;
+    private readonly SysTenantService _sysTenantService;
     private readonly SysOnlineUserService _sysOnlineUserService;
+    private readonly SysConfigService _sysConfigService;
     private readonly IMemoryCache _cache;
     private readonly ICaptcha _captcha;
 
@@ -26,9 +27,10 @@ public class SysAuthService : IDynamicApiController, ITransient
         IOptions<RefreshTokenOptions> refreshTokenOptions,
         IHttpContextAccessor httpContextAccessor,
         IEventPublisher eventPublisher,
-        SysUserService sysUserService,
         SysMenuService sysMenuService,
+        SysTenantService sysTenantService,
         SysOnlineUserService sysOnlineUserService,
+        SysConfigService sysConfigService,
         IMemoryCache cache,
         ICaptcha captcha)
     {
@@ -37,9 +39,10 @@ public class SysAuthService : IDynamicApiController, ITransient
         _httpContextAccessor = httpContextAccessor;
         _refreshTokenOptions = refreshTokenOptions.Value;
         _eventPublisher = eventPublisher;
-        _sysUserService = sysUserService;
         _sysMenuService = sysMenuService;
+        _sysTenantService = sysTenantService;
         _sysOnlineUserService = sysOnlineUserService;
+        _sysConfigService = sysConfigService;
         _cache = cache;
         _captcha = captcha;
     }
@@ -55,8 +58,11 @@ public class SysAuthService : IDynamicApiController, ITransient
     [SuppressMonitor]
     public async Task<LoginOutput> Login([Required] LoginInput input)
     {
+        // 判断租户
+
         // 判断验证码
-        if (!_captcha.Validate(input.CodeId.ToString(), input.Code))
+        var captchaEnabled = await GetCaptchaFlag();
+        if (captchaEnabled && !_captcha.Validate(input.CodeId.ToString(), input.Code))
             throw Oops.Oh(ErrorCodeEnum.D0009);
 
         var encryptPasswod = MD5Encryption.Encrypt(input.Password);
@@ -153,7 +159,7 @@ public class SysAuthService : IDynamicApiController, ITransient
     /// </summary>
     /// <param name="accessToken"></param>
     /// <returns></returns>
-    [HttpPost("/getRefreshToken")]
+    [HttpPost("/refreshToken")]
     public string RefreshToken([Required] string accessToken)
     {
         return JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
@@ -185,6 +191,18 @@ public class SysAuthService : IDynamicApiController, ITransient
     }
 
     /// <summary>
+    /// 是否启用验证码
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("/captchaFlag")]
+    [AllowAnonymous]
+    [SuppressMonitor]
+    public async Task<bool> GetCaptchaFlag()
+    {
+        return await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
+    }
+
+    /// <summary>
     /// 生成图片验证码
     /// </summary>
     /// <returns></returns>
@@ -199,6 +217,19 @@ public class SysAuthService : IDynamicApiController, ITransient
     }
 
     /// <summary>
+    /// 是否启用多库租户
+    /// </summary>
+    /// <returns></returns>
+    [HttpGet("/tenantDbList")]
+    [AllowAnonymous]
+    [SuppressMonitor]
+    public async Task<List<SysTenant>> GetTenantDbList()
+    {
+        var tenantDbEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysTenantDb);
+        return tenantDbEnabled ? await _sysTenantService.GetTenantDbList() : new List<SysTenant>();
+    }
+
+    /// <summary>
     /// Swagger登录检查
     /// </summary>
     /// <returns></returns>

+ 2 - 2
Admin.NET/Admin.NET.Core/Service/Org/SysOrgService.cs

@@ -13,8 +13,8 @@ public class SysOrgService : IDynamicApiController, ITransient
     private readonly SysUserRoleService _sysUserRoleService;
     private readonly SysRoleOrgService _sysRoleOrgService;
 
-    public SysOrgService(UserManager userManager, 
-        SqlSugarRepository<SysOrg> sysOrgRep,        
+    public SysOrgService(UserManager userManager,
+        SqlSugarRepository<SysOrg> sysOrgRep,
         SysCacheService sysCacheService,
         SysUserExtOrgService sysUserExtOrgService,
         SysUserRoleService sysUserRoleService,

+ 0 - 1
Admin.NET/Admin.NET.Core/Service/Region/Dto/RegionInput.cs

@@ -20,7 +20,6 @@ public class PageRegionInput : BasePageInput
 
 public class RegionInput : BaseIdInput
 {
-
 }
 
 [NotTable]

+ 3 - 3
Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs

@@ -104,7 +104,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task UpdateRole(UpdateRoleInput input)
     {
         var adminRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (adminRole.Code == CommonConst.SysAdminRoleCode)
+        if (adminRole.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1020);
 
         var isExist = await _sysRoleRep.IsAnyAsync(u => (u.Name == input.Name || u.Code == input.Code) && u.Id != input.Id);
@@ -127,7 +127,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task DeleteRole(DeleteRoleInput input)
     {
         var sysRole = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (sysRole.Code == CommonConst.SysAdminRoleCode)
+        if (sysRole.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1019);
 
         await _sysRoleRep.DeleteAsync(sysRole);
@@ -151,7 +151,7 @@ public class SysRoleService : IDynamicApiController, ITransient
     public async Task GrantRoleMenu(RoleMenuInput input)
     {
         var role = await _sysRoleRep.GetFirstAsync(u => u.Id == input.Id);
-        if (!_userManager.SuperAdmin && role.Code == CommonConst.SysAdminRoleCode)
+        if (!_userManager.SuperAdmin && role.Code == CommonConst.SysAdminRole)
             throw Oops.Oh(ErrorCodeEnum.D1021);
 
         await _sysRoleMenuService.GrantRoleMenu(input);

+ 20 - 4
Admin.NET/Admin.NET.Core/Service/Tenant/SysTenantService.cs

@@ -16,6 +16,7 @@ public class SysTenantService : IDynamicApiController, ITransient
     private readonly SqlSugarRepository<SysUserRole> _userRoleRep;
     private readonly SysUserRoleService _sysUserRoleService;
     private readonly SysRoleMenuService _sysRoleMenuService;
+    private readonly SysConfigService _sysConfigService;
 
     public SysTenantService(SqlSugarRepository<SysTenant> tenantRep,
         SqlSugarRepository<SysOrg> orgRep,
@@ -26,7 +27,8 @@ public class SysTenantService : IDynamicApiController, ITransient
         SqlSugarRepository<SysRoleMenu> sysRoleMenuRep,
         SqlSugarRepository<SysUserRole> userRoleRep,
         SysUserRoleService sysUserRoleService,
-        SysRoleMenuService sysRoleMenuService)
+        SysRoleMenuService sysRoleMenuService,
+        SysConfigService sysConfigService)
     {
         _tenantRep = tenantRep;
         _orgRep = orgRep;
@@ -38,6 +40,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         _userRoleRep = userRoleRep;
         _sysUserRoleService = sysUserRoleService;
         _sysRoleMenuService = sysRoleMenuService;
+        _sysConfigService = sysConfigService;
     }
 
     /// <summary>
@@ -55,6 +58,16 @@ public class SysTenantService : IDynamicApiController, ITransient
     }
 
     /// <summary>
+    /// 获取库隔离的租户列表
+    /// </summary>
+    /// <returns></returns>
+    [NonAction]
+    public async Task<List<SysTenant>> GetTenantDbList()
+    {
+        return await _tenantRep.GetListAsync(u => u.TenantType == TenantTypeEnum.Db);
+    }
+
+    /// <summary>
     /// 增加租户
     /// </summary>
     /// <param name="input"></param>
@@ -94,7 +107,7 @@ public class SysTenantService : IDynamicApiController, ITransient
         var newRole = new SysRole
         {
             TenantId = tenantId,
-            Code = CommonConst.SysAdminRoleCode,
+            Code = CommonConst.SysAdminRole,
             Name = "租户管理员-" + companyName,
             DataScope = DataScopeEnum.All,
             Remark = companyName
@@ -111,11 +124,12 @@ public class SysTenantService : IDynamicApiController, ITransient
         await _posRep.InsertAsync(newPos);
 
         // 初始化租户管理员
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
         var newUser = new SysUser
         {
             TenantId = tenantId,
             Account = admin,
-            Password = MD5Encryption.Encrypt(CommonConst.SysPassword),
+            Password = MD5Encryption.Encrypt(password),
             NickName = newTenant.AdminName,
             Email = newTenant.Email,
             Phone = newTenant.Phone,
@@ -238,8 +252,10 @@ public class SysTenantService : IDynamicApiController, ITransient
     [HttpPost("/sysTenant/resetPwd")]
     public async Task ResetTenantPwd(TenantInput input)
     {
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var tenantAdminUser = await GetTenantAdminUser(input.Id);
-        tenantAdminUser.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        tenantAdminUser.Password = MD5Encryption.Encrypt(password);
         await _userRep.UpdateAsync(tenantAdminUser);
     }
 

+ 10 - 3
Admin.NET/Admin.NET.Core/Service/User/SysUserService.cs

@@ -11,18 +11,21 @@ public class SysUserService : IDynamicApiController, ITransient
     private readonly SysOrgService _sysOrgService;
     private readonly SysUserExtOrgService _sysUserExtOrgService;
     private readonly SysUserRoleService _sysUserRoleService;
+    private readonly SysConfigService _sysConfigService;
 
     public SysUserService(UserManager userManager,
         SqlSugarRepository<SysUser> sysUserRep,
         SysOrgService sysOrgService,
         SysUserExtOrgService sysUserExtOrgService,
-        SysUserRoleService sysUserRoleService)
+        SysUserRoleService sysUserRoleService,
+        SysConfigService sysConfigService)
     {
         _userManager = userManager;
         _sysUserRep = sysUserRep;
         _sysOrgService = sysOrgService;
         _sysUserExtOrgService = sysUserExtOrgService;
         _sysUserRoleService = sysUserRoleService;
+        _sysConfigService = sysConfigService;
     }
 
     /// <summary>
@@ -58,8 +61,10 @@ public class SysUserService : IDynamicApiController, ITransient
         var isExist = await _sysUserRep.IsAnyAsync(u => u.Account == input.Account);
         if (isExist) throw Oops.Oh(ErrorCodeEnum.D1003);
 
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var user = input.Adapt<SysUser>();
-        user.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        user.Password = MD5Encryption.Encrypt(password);
         var newUser = await _sysUserRep.AsInsertable(user).ExecuteReturnEntityAsync();
         input.Id = newUser.Id;
         await UpdateRoleAndExtOrg(input);
@@ -199,8 +204,10 @@ public class SysUserService : IDynamicApiController, ITransient
     [HttpPost("/sysUser/resetPwd")]
     public async Task<int> ResetUserPwd(ResetPwdUserInput input)
     {
+        var password = await _sysConfigService.GetConfigValue<string>(CommonConst.SysPassword);
+
         var user = await _sysUserRep.GetFirstAsync(u => u.Id == input.Id);
-        user.Password = MD5Encryption.Encrypt(CommonConst.SysPassword);
+        user.Password = MD5Encryption.Encrypt(password);
         return await _sysUserRep.AsUpdateable(user).UpdateColumns(u => u.Password).ExecuteCommandAsync();
     }
 

+ 175 - 37
Web/src/api-services/apis/sys-auth-api.ts

@@ -16,6 +16,8 @@ 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 { AdminResultBoolean } from '../models';
+import { AdminResultListSysTenant } from '../models';
 import { AdminResultLoginOutput } from '../models';
 import { AdminResultLoginUserOutput } from '../models';
 import { AdminResultObject } from '../models';
@@ -29,12 +31,12 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        captchaGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            const localVarPath = `/captcha`;
+        captchaFlagGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/captchaFlag`;
             // use dummy base URL string because the URL constructor only accepts absolute URLs.
             const localVarUrlObj = new URL(localVarPath, 'https://example.com');
             let baseOptions;
@@ -65,33 +67,24 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        getRefreshTokenPost: async (accessToken: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
-            // verify required parameter 'accessToken' is not null or undefined
-            if (accessToken === null || accessToken === undefined) {
-                throw new RequiredError('accessToken','Required parameter accessToken was null or undefined when calling getRefreshTokenPost.');
-            }
-            const localVarPath = `/getRefreshToken`;
+        captchaGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/captcha`;
             // 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 localVarRequestOptions :AxiosRequestConfig = { method: 'GET', ...baseOptions, ...options};
             const localVarHeaderParameter = {} as any;
             const localVarQueryParameter = {} as any;
 
             // authentication Bearer required
 
-            if (accessToken !== undefined) {
-                localVarQueryParameter['accessToken'] = accessToken;
-            }
-
             const query = new URLSearchParams(localVarUrlObj.search);
             for (const key in localVarQueryParameter) {
                 query.set(key, localVarQueryParameter[key]);
@@ -191,6 +184,51 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
         },
         /**
          * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        refreshTokenPost: async (accessToken: string, options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            // verify required parameter 'accessToken' is not null or undefined
+            if (accessToken === null || accessToken === undefined) {
+                throw new RequiredError('accessToken','Required parameter accessToken was null or undefined when calling refreshTokenPost.');
+            }
+            const localVarPath = `/refreshToken`;
+            // 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
+
+            if (accessToken !== undefined) {
+                localVarQueryParameter['accessToken'] = 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 Swagger登录检查
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -277,6 +315,42 @@ export const SysAuthApiAxiosParamCreator = function (configuration?: Configurati
         },
         /**
          * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        tenantDbListGet: async (options: AxiosRequestConfig = {}): Promise<RequestArgs> => {
+            const localVarPath = `/tenantDbList`;
+            // 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
+
+            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 {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -322,12 +396,12 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async captchaGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
-            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaGet(options);
+        async captchaFlagGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultBoolean>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaFlagGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -335,13 +409,12 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
-            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).getRefreshTokenPost(accessToken, options);
+        async captchaGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultObject>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).captchaGet(options);
             return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
                 const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
                 return axios.request(axiosRequestArgs);
@@ -376,6 +449,20 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultString>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).refreshTokenPost(accessToken, options);
+            return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => {
+                const axiosRequestArgs :AxiosRequestConfig = {...localVarAxiosArgs.options, url: basePath + localVarAxiosArgs.url};
+                return axios.request(axiosRequestArgs);
+            };
+        },
+        /**
+         * 
          * @summary Swagger登录检查
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -404,6 +491,19 @@ export const SysAuthApiFp = function(configuration?: Configuration) {
         },
         /**
          * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async tenantDbListGet(options?: AxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => Promise<AxiosResponse<AdminResultListSysTenant>>> {
+            const localVarAxiosArgs = await SysAuthApiAxiosParamCreator(configuration).tenantDbListGet(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}
@@ -426,22 +526,21 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
     return {
         /**
          * 
-         * @summary 生成图片验证码
+         * @summary 是否启用验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async captchaGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
-            return SysAuthApiFp(configuration).captchaGet(options).then((request) => request(axios, basePath));
+        async captchaFlagGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultBoolean>> {
+            return SysAuthApiFp(configuration).captchaFlagGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 
-         * @summary 获取刷新Token
-         * @param {string} accessToken 
+         * @summary 生成图片验证码
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
          */
-        async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
-            return SysAuthApiFp(configuration).getRefreshTokenPost(accessToken, options).then((request) => request(axios, basePath));
+        async captchaGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultObject>> {
+            return SysAuthApiFp(configuration).captchaGet(options).then((request) => request(axios, basePath));
         },
         /**
          * 用户名/密码:superadmin/123456
@@ -464,6 +563,16 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         },
         /**
          * 
+         * @summary 获取刷新Token
+         * @param {string} accessToken 
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultString>> {
+            return SysAuthApiFp(configuration).refreshTokenPost(accessToken, options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
          * @summary Swagger登录检查
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -484,6 +593,15 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
         },
         /**
          * 
+         * @summary 是否启用多库租户
+         * @param {*} [options] Override http request option.
+         * @throws {RequiredError}
+         */
+        async tenantDbListGet(options?: AxiosRequestConfig): Promise<AxiosResponse<AdminResultListSysTenant>> {
+            return SysAuthApiFp(configuration).tenantDbListGet(options).then((request) => request(axios, basePath));
+        },
+        /**
+         * 
          * @summary 获取用户信息
          * @param {*} [options] Override http request option.
          * @throws {RequiredError}
@@ -503,24 +621,23 @@ export const SysAuthApiFactory = function (configuration?: Configuration, basePa
 export class SysAuthApi extends BaseAPI {
     /**
      * 
-     * @summary 生成图片验证码
+     * @summary 是否启用验证码
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysAuthApi
      */
-    public async captchaGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
-        return SysAuthApiFp(this.configuration).captchaGet(options).then((request) => request(this.axios, this.basePath));
+    public async captchaFlagGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultBoolean>> {
+        return SysAuthApiFp(this.configuration).captchaFlagGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 
-     * @summary 获取刷新Token
-     * @param {string} accessToken 
+     * @summary 生成图片验证码
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
      * @memberof SysAuthApi
      */
-    public async getRefreshTokenPost(accessToken: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
-        return SysAuthApiFp(this.configuration).getRefreshTokenPost(accessToken, options).then((request) => request(this.axios, this.basePath));
+    public async captchaGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultObject>> {
+        return SysAuthApiFp(this.configuration).captchaGet(options).then((request) => request(this.axios, this.basePath));
     }
     /**
      * 用户名/密码:superadmin/123456
@@ -545,6 +662,17 @@ export class SysAuthApi extends BaseAPI {
     }
     /**
      * 
+     * @summary 获取刷新Token
+     * @param {string} accessToken 
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async refreshTokenPost(accessToken: string, options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultString>> {
+        return SysAuthApiFp(this.configuration).refreshTokenPost(accessToken, options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
      * @summary Swagger登录检查
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}
@@ -567,6 +695,16 @@ export class SysAuthApi extends BaseAPI {
     }
     /**
      * 
+     * @summary 是否启用多库租户
+     * @param {*} [options] Override http request option.
+     * @throws {RequiredError}
+     * @memberof SysAuthApi
+     */
+    public async tenantDbListGet(options?: AxiosRequestConfig) : Promise<AxiosResponse<AdminResultListSysTenant>> {
+        return SysAuthApiFp(this.configuration).tenantDbListGet(options).then((request) => request(this.axios, this.basePath));
+    }
+    /**
+     * 
      * @summary 获取用户信息
      * @param {*} [options] Override http request option.
      * @throws {RequiredError}

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

@@ -92,6 +92,12 @@ export interface AddTenantInput {
      */
     connection?: string | null;
     /**
+     * 数据库标识
+     * @type {string}
+     * @memberof AddTenantInput
+     */
+    configId?: string | null;
+    /**
      * 排序
      * @type {number}
      * @memberof AddTenantInput

+ 57 - 0
Web/src/api-services/models/admin-result-list-sys-tenant.ts

@@ -0,0 +1,57 @@
+/* tslint:disable */
+/* eslint-disable */
+/**
+ * Admin.NET
+ * 让 .NET 开发更简单、更通用、更流行。前后端分离架构(.NET6/Vue3),开箱即用紧随前沿技术。<br/><a href='https://gitee.com/zuohuaijun/Admin.NET/'>https://gitee.com/zuohuaijun/Admin.NET</a>
+ *
+ * OpenAPI spec version: 1.0.0
+ * Contact: 515096995@qq.com
+ *
+ * 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 { SysTenant } from './sys-tenant';
+/**
+ * 全局返回结果
+ * @export
+ * @interface AdminResultListSysTenant
+ */
+export interface AdminResultListSysTenant {
+    /**
+     * 状态码
+     * @type {number}
+     * @memberof AdminResultListSysTenant
+     */
+    code?: number;
+    /**
+     * 类型success、warning、error
+     * @type {string}
+     * @memberof AdminResultListSysTenant
+     */
+    type?: string | null;
+    /**
+     * 错误信息
+     * @type {string}
+     * @memberof AdminResultListSysTenant
+     */
+    message?: string | null;
+    /**
+     * 数据
+     * @type {Array<SysTenant>}
+     * @memberof AdminResultListSysTenant
+     */
+    result?: Array<SysTenant> | null;
+    /**
+     * 附加数据
+     * @type {any}
+     * @memberof AdminResultListSysTenant
+     */
+    extras?: any | null;
+    /**
+     * 时间
+     * @type {Date}
+     * @memberof AdminResultListSysTenant
+     */
+    time?: Date;
+}

+ 1 - 0
Web/src/api-services/models/index.ts

@@ -36,6 +36,7 @@ export * from './admin-result-list-sys-notice';
 export * from './admin-result-list-sys-org';
 export * from './admin-result-list-sys-pos';
 export * from './admin-result-list-sys-region';
+export * from './admin-result-list-sys-tenant';
 export * from './admin-result-list-sys-user-ext-org';
 export * from './admin-result-list-table-column-ouput';
 export * from './admin-result-list-table-output';

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

@@ -41,4 +41,10 @@ export interface LoginInput {
      * @memberof LoginInput
      */
     code?: string | null;
+    /**
+     * 租户Id
+     * @type {number}
+     * @memberof LoginInput
+     */
+    tenantId?: number;
 }

+ 6 - 0
Web/src/api-services/models/sys-tenant.ts

@@ -104,6 +104,12 @@ export interface SysTenant {
      */
     connection?: string | null;
     /**
+     * 数据库标识
+     * @type {string}
+     * @memberof SysTenant
+     */
+    configId?: string | null;
+    /**
      * 排序
      * @type {number}
      * @memberof SysTenant

+ 6 - 0
Web/src/api-services/models/update-tenant-input.ts

@@ -92,6 +92,12 @@ export interface UpdateTenantInput {
      */
     connection?: string | null;
     /**
+     * 数据库标识
+     * @type {string}
+     * @memberof UpdateTenantInput
+     */
+    configId?: string | null;
+    /**
      * 排序
      * @type {number}
      * @memberof UpdateTenantInput

+ 38 - 11
Web/src/views/login/component/account.vue

@@ -1,9 +1,19 @@
 <template>
 	<el-form ref="ruleFormRef" :model="ruleForm" size="large" :rules="rules" class="login-content-form">
+		<el-form-item class="login-animation1" v-show="tenantList.length > 0">
+			<el-select v-model="ruleForm.tenantId" value-key="id" placeholder="租户名称" class="w100">
+				<template #prefix>
+					<el-icon>
+						<ele-OfficeBuilding />
+					</el-icon>
+				</template>
+				<el-option v-for="item in tenantList" :key="item.id" :label="item.name" :value="item.id" />
+			</el-select>
+		</el-form-item>
 		<el-form-item class="login-animation1" prop="account">
 			<el-input type="text" placeholder="请输入账号" v-model="ruleForm.account" clearable autocomplete="off">
 				<template #prefix>
-					<el-icon class="el-input__icon">
+					<el-icon>
 						<ele-User />
 					</el-icon>
 				</template>
@@ -12,7 +22,7 @@
 		<el-form-item class="login-animation2" prop="password">
 			<el-input :type="isShowPassword ? 'text' : 'password'" placeholder="请输入密码" v-model="ruleForm.password" autocomplete="off">
 				<template #prefix>
-					<el-icon class="el-input__icon">
+					<el-icon>
 						<ele-Unlock />
 					</el-icon>
 				</template>
@@ -21,11 +31,11 @@
 				</template>
 			</el-input>
 		</el-form-item>
-		<el-form-item class="login-animation3" prop="captcha">
+		<el-form-item class="login-animation3" prop="captcha" v-show="captchaEnabled">
 			<el-col :span="15">
 				<el-input type="text" maxlength="4" :placeholder="$t('message.account.accountPlaceholder3')" v-model="ruleForm.code" clearable autocomplete="off">
 					<template #prefix>
-						<el-icon class="el-input__icon">
+						<el-icon>
 							<ele-Position />
 						</el-icon>
 					</template>
@@ -75,7 +85,8 @@ import { formatAxis } from '/@/utils/formatTime';
 import { NextLoading } from '/@/utils/loading';
 
 import { getAPI } from '/@/utils/axios-utils';
-import { SysAuthApi } from '/@/api-services/apis/sys-auth-api';
+import { SysAuthApi } from '/@/api-services/api';
+import { SysTenant } from '/@/api-services/models';
 
 // 旋转图片滑块组件
 import DragVerifyImgRotate from '/@/components/dragVerify/dragVerifyImgRotate.vue';
@@ -98,8 +109,9 @@ export default defineComponent({
 			ruleForm: {
 				account: 'superadmin',
 				password: '123456',
-				code: '1234',
+				code: '',
 				codeId: 0,
+				tenantId: 0,
 			},
 			rules: {
 				account: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
@@ -113,8 +125,19 @@ export default defineComponent({
 			isPass: false,
 			verifyImg: verifyImg,
 			captchaImage: '',
+			captchaEnabled: true,
+			tenantList: [] as Array<SysTenant>,
 		});
-		onMounted(() => {
+		onMounted(async () => {
+			// 是否开启多库租户
+			var res = await getAPI(SysAuthApi).tenantDbListGet();
+			state.tenantList = res.data.result ?? [];
+			if (state.tenantList.length > 0) state.ruleForm.tenantId = state.tenantList[0].id ?? 0;
+
+			// 是否开启验证码验证
+			var res1 = await getAPI(SysAuthApi).captchaFlagGet();
+			state.captchaEnabled = res1.data.result ?? true;
+			if (!state.captchaEnabled) return;
 			getCaptcha();
 		});
 		// 获取验证码
@@ -184,15 +207,19 @@ export default defineComponent({
 			ruleFormRef.value.validate((valid: boolean) => {
 				if (!valid) return false;
 
-				state.verifyVisible = true;
-				state.isPass = false;
-				dragRef.value.reset();
+				if (!state.captchaEnabled) {
+					passVerify();
+				} else {
+					state.verifyVisible = true;
+					state.isPass = false;
+					dragRef.value.reset();
+				}
 			});
 		};
 		// 通过旋转验证
 		const passVerify = () => {
 			state.verifyVisible = false;
-			state.isPass = false;
+			state.isPass = true;
 			onSignIn();
 		};
 		return {

+ 1 - 1
Web/src/views/login/component/mobile.vue

@@ -1,6 +1,6 @@
 <template>
 	<el-form size="large" class="login-content-form">
-		<el-form-item class="login-animation1">
+		<el-form-item class="login-animation4">
 			<el-input type="text" :placeholder="$t('message.mobile.placeholder1')" v-model="ruleForm.userName" clearable autocomplete="off">
 				<template #prefix>
 					<i class="iconfont icon-dianhua el-input__icon"></i>

+ 4 - 5
Web/src/views/login/index.vue

@@ -1,12 +1,11 @@
 <template>
 	<div class="login-container">
 		<div class="login-icon-group">
-			<div class="login-icon-group-title">
+			<!-- <div class="login-icon-group-title">
 				<img :src="logoMini" />
-				<!-- <div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div> -->
-			</div>
-			<el-carousel height="550px"
-				style="width: 100%; padding-right: 38%; top:50%; transform: translateY(-50%) translate3d(0, 0, 0);">
+				<div class="login-icon-group-title-text font25">{{ getThemeConfig.globalViceTitle }}</div>
+			</div> -->
+			<el-carousel height="550px" style="width: 100%; padding-right: 38%; top: 50%; transform: translateY(-50%) translate3d(0, 0, 0)">
 				<el-carousel-item>
 					<img :src="loginIconTwo" class="login-icon-group-icon" />
 				</el-carousel-item>