diff --git a/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/Aggregates/DataDictionary.cs b/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/Aggregates/DataDictionary.cs index 11992271..2ad4aa58 100644 --- a/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/Aggregates/DataDictionary.cs +++ b/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/Aggregates/DataDictionary.cs @@ -72,7 +72,7 @@ namespace CompanyName.ProjectName.DataDictionaryManagement.DataDictionaries.Aggr public void SetTenantId(Guid? tenantId) { - TenantId = TenantId; + TenantId = tenantId; } public void SetCode(string code) diff --git a/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/DataDictionaryDataSeedContributor.cs b/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/DataDictionaryDataSeedContributor.cs index 3873bb42..78c81cf0 100644 --- a/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/DataDictionaryDataSeedContributor.cs +++ b/aspnet-core/modules/DataDictionaryManagement/src/CompanyName.ProjectName.DataDictionaryManagement.Domain/DataDictionaries/DataDictionaryDataSeedContributor.cs @@ -4,6 +4,7 @@ using CompanyName.ProjectName.DataDictionaryManagement.DataDictionaries.Aggregat using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.Guids; +using Volo.Abp.MultiTenancy; namespace CompanyName.ProjectName.DataDictionaryManagement.DataDictionaries { @@ -11,27 +12,31 @@ namespace CompanyName.ProjectName.DataDictionaryManagement.DataDictionaries { private readonly IDataDictionaryRepository _dataDictionaryRepository; private readonly IGuidGenerator _guidGenerator; + private readonly ICurrentTenant _currentTenant; public DataDictionaryDataSeedContributor( IDataDictionaryRepository dataDictionaryRepository, - IGuidGenerator guidGenerator) + IGuidGenerator guidGenerator, ICurrentTenant currentTenant) { _dataDictionaryRepository = dataDictionaryRepository; _guidGenerator = guidGenerator; + _currentTenant = currentTenant; } public async Task SeedAsync(DataSeedContext context) { - var gender = await _dataDictionaryRepository.FindByCodeAsync("Gender"); - if (gender == null) + using (_currentTenant.Change(context?.TenantId)) { - var id = DataDictionaryManagementConsts.SeedDataDictionaryId;//_guidGenerator.Create(); - - var entity = new DataDictionary(id, "Gender", "性别", "单元测试"); - entity.AddDetail(_guidGenerator.Create(), "Man", "男", 1, "单元测试"); - entity.AddDetail(_guidGenerator.Create(), "WoMan", "女", 2, "单元测试"); - entity.AddDetail(_guidGenerator.Create(), "None", "未知", 3, "单元测试", false); - await _dataDictionaryRepository.InsertAsync(entity); + var gender = await _dataDictionaryRepository.FindByCodeAsync("Gender"); + if (gender == null) + { + var id = context is {TenantId: null} ? DataDictionaryManagementConsts.SeedDataDictionaryId : _guidGenerator.Create(); + var entity = new DataDictionary(id, "Gender", "性别", "单元测试", context?.TenantId); + entity.AddDetail(_guidGenerator.Create(), "Man", "男", 1, "单元测试"); + entity.AddDetail(_guidGenerator.Create(), "WoMan", "女", 2, "单元测试"); + entity.AddDetail(_guidGenerator.Create(), "None", "未知", 3, "单元测试", false); + await _dataDictionaryRepository.InsertAsync(entity); + } } } } diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs index 6feaaae2..ec023a51 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Extensions/Filters/HiddenAbpDefaultApiFilter.cs @@ -42,14 +42,14 @@ namespace CompanyName.ProjectName.Extensions.Filters private List GetHiddenAbpDefaultApiList() { return new List() { - // "/api/abp/multi-tenancy/tenants", - // "/api/account", - // "/api/feature-management/features", - // "/api/permission-management/permissions", - // "/api/identity/my-profile", - // "/api/identity", - // "/api/multi-tenancy/tenants", - // "/api/setting-management/emailing" + "/api/abp/multi-tenancy/tenants", + "/api/account", + "/api/feature-management/features", + "/api/permission-management/permissions", + "/api/identity/my-profile", + "/api/identity", + "/api/multi-tenancy/tenants", + "/api/setting-management/emailing" }; } } diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs index e747a15c..d006cbf0 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/ProjectNameHttpApiHostModule.cs @@ -36,9 +36,11 @@ using System.Threading.Tasks; using CompanyName.ProjectName.CAP; using CompanyName.ProjectName.Extensions; using CompanyName.ProjectName.Extensions.Customs.Http; +using CompanyName.ProjectName.MultiTenancy; using Savorboard.CAP.InMemoryMessageQueue; using Serilog; using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.AspNetCore.MultiTenancy; namespace CompanyName.ProjectName { @@ -54,7 +56,8 @@ namespace CompanyName.ProjectName typeof(AbpAccountWebModule), typeof(AbpAspNetCoreAuthenticationJwtBearerModule), typeof(AbpBackgroundJobsHangfireModule), - typeof(AbpCapModule) + typeof(AbpCapModule), + typeof(AbpAspNetCoreMultiTenancyModule) )] public class ProjectNameHttpApiHostModule : AbpModule { @@ -96,11 +99,11 @@ namespace CompanyName.ProjectName app.UseRouting(); app.UseCors(DefaultCorsPolicyName); app.UseAuthentication(); - // - // if (MultiTenancyConsts.IsEnabled) - // { - // app.UseMultiTenancy(); - // } + + if (MultiTenancyConsts.IsEnabled) + { + app.UseMultiTenancy(); + } app.UseAuthorization(); diff --git a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json index 64892bee..6fce9433 100644 --- a/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json +++ b/aspnet-core/services/host/CompanyName.ProjectName.HttpApi.Host/Properties/launchSettings.json @@ -20,7 +20,7 @@ "launchBrowser": true, "applicationUrl": "http://localhost:44315", "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Production" + "ASPNETCORE_ENVIRONMENT": "Development" } } } diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/CompanyName.ProjectName.Application.Contracts.csproj b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/CompanyName.ProjectName.Application.Contracts.csproj index c1a365b2..82bf0b16 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/CompanyName.ProjectName.Application.Contracts.csproj +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/CompanyName.ProjectName.Application.Contracts.csproj @@ -35,4 +35,8 @@ + + + + diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/FindTenantByNameInput.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/FindTenantByNameInput.cs new file mode 100644 index 00000000..05bd8aa6 --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/FindTenantByNameInput.cs @@ -0,0 +1,7 @@ +namespace CompanyName.ProjectName.Tenants.Dtos +{ + public class FindTenantByNameInput + { + public string Name { get; set; } + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/PagingTenantInput.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/PagingTenantInput.cs new file mode 100644 index 00000000..d16612cf --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/PagingTenantInput.cs @@ -0,0 +1,9 @@ +using CompanyName.ProjectName.Extensions.Customs; + +namespace CompanyName.ProjectName.Tenants.Dtos +{ + public class PagingTenantInput : PagingBase + { + public string Filter { get; set; } + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateDefaultConnectionStringInput.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateDefaultConnectionStringInput.cs new file mode 100644 index 00000000..13ac523e --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateDefaultConnectionStringInput.cs @@ -0,0 +1,11 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace CompanyName.ProjectName.Tenants.Dtos +{ + public class UpdateConnectionStringInput + { + public Guid Id { get; set; } + [Required(ErrorMessage = "连接字符串不能为空")] public string ConnectionString { get; set; } + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateTenantInput.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateTenantInput.cs new file mode 100644 index 00000000..ca699ee2 --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application.Contracts/Tenants/Dtos/UpdateTenantInput.cs @@ -0,0 +1,12 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace CompanyName.ProjectName.Tenants.Dtos +{ + public class UpdateTenantInput + { + public Guid Id { get; set; } + + [Required(ErrorMessage = "租户名称不能为空")] public string Name { get; set; } + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs index 203833d0..f4c04410 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application/Roles/RoleAppService.cs @@ -118,13 +118,13 @@ namespace CompanyName.ProjectName.Roles "AbpIdentity.Users.ManagePermissions", "FeatureManagement", "FeatureManagement.ManageHostFeatures", - "AbpTenantManagement", - "AbpTenantManagement.Tenants", - "AbpTenantManagement.Tenants.Create", - "AbpTenantManagement.Tenants.Update", - "AbpTenantManagement.Tenants.Delete", - "AbpTenantManagement.Tenants.ManageFeatures", - "AbpTenantManagement.Tenants.ManageConnectionStrings", + // "AbpTenantManagement", + // "AbpTenantManagement.Tenants", + // "AbpTenantManagement.Tenants.Create", + // "AbpTenantManagement.Tenants.Update", + // "AbpTenantManagement.Tenants.Delete", + "AbpTenantManagement.Tenants.ManageFeatures", + // "AbpTenantManagement.Tenants.ManageConnectionStrings", "SettingManagement", "SettingManagement.Emailing", "SettingUi" diff --git a/aspnet-core/services/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs b/aspnet-core/services/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs index 6994d1e0..80fcc09f 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs +++ b/aspnet-core/services/src/CompanyName.ProjectName.Application/Users/LoginAppService.cs @@ -15,6 +15,7 @@ using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using Volo.Abp.Identity; +using Volo.Abp.MultiTenancy; using Volo.Abp.Security.Claims; namespace CompanyName.ProjectName.Users @@ -25,29 +26,37 @@ namespace CompanyName.ProjectName.Users private readonly JwtOptions _jwtOptions; private readonly Microsoft.AspNetCore.Identity.SignInManager _signInManager; private readonly IHttpClientFactory _httpClientFactory; - private readonly ILogger _logger; + private readonly ICurrentTenant _currentTenant; public LoginAppService( IdentityUserManager userManager, IOptionsSnapshot jwtOptions, Microsoft.AspNetCore.Identity.SignInManager signInManager, - IHttpClientFactory httpClientFactory, ILogger logger) + IHttpClientFactory httpClientFactory, ICurrentTenant currentTenant) { _userManager = userManager; _jwtOptions = jwtOptions.Value; _signInManager = signInManager; _httpClientFactory = httpClientFactory; - _logger = logger; + _currentTenant = currentTenant; } public async Task LoginAsync(LoginInput input) { - _logger.LogError("test"); try { var result = await _signInManager.PasswordSignInAsync(input.Name, input.Password, false, true); - if (result.IsLockedOut) throw new Exception("当前用户已被锁定"); - if (!result.Succeeded) throw new Exception("用户名或者密码错误"); + if (result.IsLockedOut) + { + throw new Exception("当前用户已被锁定"); + } + + if (!result.Succeeded) + { + throw new Exception("用户名或者密码错误"); + } + + var s = _currentTenant.Id; var user = await _userManager.FindByNameAsync(input.Name); return await BuildResult(user); } diff --git a/aspnet-core/services/src/CompanyName.ProjectName.DbMigrator/appsettings.json b/aspnet-core/services/src/CompanyName.ProjectName.DbMigrator/appsettings.json index 47063d9a..1f210a15 100644 --- a/aspnet-core/services/src/CompanyName.ProjectName.DbMigrator/appsettings.json +++ b/aspnet-core/services/src/CompanyName.ProjectName.DbMigrator/appsettings.json @@ -1,5 +1,5 @@ { "ConnectionStrings": { - "Default": "Data Source=localhost;Database=CompanyNameProjectName;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" + "Default": "Data Source=localhost;Database=CompanyNameProjectNameDB;uid=root;pwd=1q2w3E*;charset=utf8mb4;Allow User Variables=true;AllowLoadLocalInfile=true" } } \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/AbpTenantController.cs b/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/AbpTenantController.cs new file mode 100644 index 00000000..e3ec939f --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/AbpTenantController.cs @@ -0,0 +1,26 @@ +using System.Threading.Tasks; +using CompanyName.ProjectName.Tenants.Dtos; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Volo.Abp.AspNetCore.Mvc.MultiTenancy; + +namespace CompanyName.ProjectName.Controllers.Tenants +{ + [Route("Tenants")] + public class AbpTenantController : ProjectNameController + { + private readonly IAbpTenantAppService _abpTenantAppService; + + public AbpTenantController(IAbpTenantAppService abpTenantAppService) + { + _abpTenantAppService = abpTenantAppService; + } + + [HttpPost("find")] + [SwaggerOperation(summary: "通过名称获取租户信息", Tags = new[] {"Tenants"})] + public async Task FindTenantByNameAsync(FindTenantByNameInput input) + { + return await _abpTenantAppService.FindTenantByNameAsync(input.Name); + } + } +} \ No newline at end of file diff --git a/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/TenantController.cs b/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/TenantController.cs new file mode 100644 index 00000000..b812c9f9 --- /dev/null +++ b/aspnet-core/services/src/CompanyName.ProjectName.HttpApi/Controllers/Tenants/TenantController.cs @@ -0,0 +1,83 @@ +using System.Threading.Tasks; +using CompanyName.ProjectName.Publics.Dtos; +using CompanyName.ProjectName.Tenants.Dtos; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Swashbuckle.AspNetCore.Annotations; +using Volo.Abp.Application.Dtos; +using Volo.Abp.TenantManagement; + +namespace CompanyName.ProjectName.Controllers.Tenants +{ + [Route("Tenants")] + [Authorize(TenantManagementPermissions.Tenants.Default)] + public class TenantController : ProjectNameController + { + private readonly ITenantAppService _tenantAppService; + + public TenantController(ITenantAppService tenantAppService) + { + _tenantAppService = tenantAppService; + } + + [HttpPost("page")] + [SwaggerOperation(summary: "分页获取租户信息", Tags = new[] {"Tenants"})] + public Task> ListAsync(PagingTenantInput input) + { + var request = new GetTenantsInput {Filter = input.Filter, SkipCount = input.SkipCount, MaxResultCount = input.PageSize}; + return _tenantAppService.GetListAsync(request); + } + + [HttpPost("create")] + [SwaggerOperation(summary: "创建租户", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.Create)] + public Task CreateAsync(TenantCreateDto input) + { + return _tenantAppService.CreateAsync(input); + } + + [HttpPost("update")] + [SwaggerOperation(summary: "更新租户", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.Update)] + public Task UpdateAsync(UpdateTenantInput input) + { + var request = new TenantUpdateDto() + { + Name = input.Name.Trim() + }; + return _tenantAppService.UpdateAsync(input.Id, request); + } + + [HttpPost("delete")] + [SwaggerOperation(summary: "删除租户", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.Delete)] + public Task DeleteAsync(IdInput input) + { + return _tenantAppService.DeleteAsync(input.Id); + } + + [HttpPost("getConnectionString")] + [SwaggerOperation(summary: "获取租户连接字符串", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] + public Task GetDefaultConnectionStringAsync(IdInput input) + { + return _tenantAppService.GetDefaultConnectionStringAsync(input.Id); + } + + [HttpPost("updateConnectionString")] + [SwaggerOperation(summary: "更新租户连接字符串", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] + public Task UpdateDefaultConnectionStringAsync(UpdateConnectionStringInput input) + { + return _tenantAppService.UpdateDefaultConnectionStringAsync(input.Id, input.ConnectionString); + } + + [HttpPost("deleteConnectionString")] + [SwaggerOperation(summary: "删除租户连接字符串", Tags = new[] {"Tenants"})] + [Authorize(TenantManagementPermissions.Tenants.ManageConnectionStrings)] + public Task DeleteDefaultConnectionStringAsync(IdInput input) + { + return _tenantAppService.DeleteDefaultConnectionStringAsync(input.Id); + } + } +} \ No newline at end of file diff --git a/vben271/src/api/sys/model/userModel.ts b/vben271/src/api/sys/model/userModel.ts index 444a7436..5be6ab9c 100644 --- a/vben271/src/api/sys/model/userModel.ts +++ b/vben271/src/api/sys/model/userModel.ts @@ -4,6 +4,7 @@ export interface LoginParams { username: string; password: string; + tenantId: string; } /** @@ -48,6 +49,7 @@ export interface GetUserInfoByUserIdModel { export interface LoginParams { username: string; password: string; + tenantId: string; } export interface RoleInfo { diff --git a/vben271/src/assets/images/header.jpg b/vben271/src/assets/images/header.jpg new file mode 100644 index 00000000..977584b6 Binary files /dev/null and b/vben271/src/assets/images/header.jpg differ diff --git a/vben271/src/enums/cacheEnum.ts b/vben271/src/enums/cacheEnum.ts index 8eac7b1f..3d71b47b 100644 --- a/vben271/src/enums/cacheEnum.ts +++ b/vben271/src/enums/cacheEnum.ts @@ -27,6 +27,8 @@ export const APP_SESSION_CACHE_KEY = 'COMMON__SESSION__KEY__'; export const ABP_LOCALE_KEY = 'ABP_LOCALE__'; +export const ABP_TETANT_KEY = 'ABP_TETANT__'; + export const AUHT_KEY = 'AUTH__KEY__'; export enum CacheTypeEnum { diff --git a/vben271/src/locales/lang/en/routes/tenant.ts b/vben271/src/locales/lang/en/routes/tenant.ts new file mode 100644 index 00000000..0311f108 --- /dev/null +++ b/vben271/src/locales/lang/en/routes/tenant.ts @@ -0,0 +1,6 @@ +export default { + name: 'Name', + connectionString: 'ConnectionString', + tenantManagement: 'TenantManagement', + tenantList: 'TenantList', +}; diff --git a/vben271/src/locales/lang/en/sys.ts b/vben271/src/locales/lang/en/sys.ts index 3b296007..c94920b2 100644 --- a/vben271/src/locales/lang/en/sys.ts +++ b/vben271/src/locales/lang/en/sys.ts @@ -70,7 +70,7 @@ export default { signInFormTitle: 'Sign in', signUpFormTitle: 'Sign up', forgetFormTitle: 'Reset password', - + tenantFormTitle: 'Tenant sign in', signInTitle: 'Backstage management system', signInDesc: 'Enter your personal details and get started!', policy: 'I agree to the xxx Privacy Policy', @@ -92,6 +92,7 @@ export default { smsPlaceholder: 'Please input sms code', mobilePlaceholder: 'Please input mobile', policyPlaceholder: 'Register after checking', + tenantPlaceholder: 'Please input tenant', diffPwd: 'The two passwords are inconsistent', userName: 'Username', @@ -100,5 +101,6 @@ export default { email: 'Email', smsCode: 'SMS code', mobile: 'Mobile', + tenant: 'Tenant', }, }; diff --git a/vben271/src/locales/lang/zh-CN/routes/tenant.ts b/vben271/src/locales/lang/zh-CN/routes/tenant.ts new file mode 100644 index 00000000..1f8b25ca --- /dev/null +++ b/vben271/src/locales/lang/zh-CN/routes/tenant.ts @@ -0,0 +1,6 @@ +export default { + name: '名称', + connectionString: '连接字符串', + tenantManagement: '租户管理', + tenantList: '租户列表', +}; diff --git a/vben271/src/locales/lang/zh-CN/sys.ts b/vben271/src/locales/lang/zh-CN/sys.ts index 8dad1cf4..05575b7f 100644 --- a/vben271/src/locales/lang/zh-CN/sys.ts +++ b/vben271/src/locales/lang/zh-CN/sys.ts @@ -64,7 +64,7 @@ export default { qrSignInFormTitle: '二维码登录', signUpFormTitle: '注册', forgetFormTitle: '重置密码', - + tenantFormTitle: '租户登录', signInTitle: '开箱即用的中后台管理系统', signInDesc: '输入您的个人详细信息开始使用!', policy: '我同意xxx隐私政策', @@ -86,6 +86,7 @@ export default { smsPlaceholder: '请输入验证码', mobilePlaceholder: '请输入手机号码', policyPlaceholder: '勾选后才能注册', + tenantPlaceholder: '请输入租户', diffPwd: '两次输入密码不一致', userName: '账号', @@ -94,5 +95,6 @@ export default { email: '邮箱', smsCode: '短信验证码', mobile: '手机号码', + tenant: '租户', }, }; diff --git a/vben271/src/router/routes/modules/admin.ts b/vben271/src/router/routes/modules/admin.ts index 4e2c67b2..fd26fd72 100644 --- a/vben271/src/router/routes/modules/admin.ts +++ b/vben271/src/router/routes/modules/admin.ts @@ -63,7 +63,7 @@ const admin: AppRouteModule = { component: () => import('/@/views/admin/elasticSearch/ElasticSearch.vue'), meta: { title: t('routes.admin.esLogs'), - policy: 'System.AuditLog', + policy: 'System.ES', icon: 'ant-design:snippets-twotone', }, }, diff --git a/vben271/src/router/routes/modules/tenant.ts b/vben271/src/router/routes/modules/tenant.ts new file mode 100644 index 00000000..e1494e1b --- /dev/null +++ b/vben271/src/router/routes/modules/tenant.ts @@ -0,0 +1,27 @@ +import type { AppRouteModule } from '/@/router/types'; +import { LAYOUT } from '/@/router/constant'; +import { t } from '/@/hooks/web/useI18n'; +const tenant: AppRouteModule = { + path: '/tenant', + name: 'Tenant', + component: LAYOUT, + meta: { + orderNo: 30, + icon: 'ion:grid-outline', + title: t('routes.tenant.tenantManagement'), + }, + children: [ + { + path: 'Tenant', + name: 'Tenant', + component: () => import('/@/views/tenants/Tenant.vue'), + meta: { + title: t('routes.tenant.tenantList'), + icon: 'ant-design:switcher-filled', + policy: 'AbpTenantManagement.Tenants', + }, + }, + ], +}; + +export default tenant; diff --git a/vben271/src/services/ServiceProxies.ts b/vben271/src/services/ServiceProxies.ts index 92e1c1d0..e88088bc 100644 --- a/vben271/src/services/ServiceProxies.ts +++ b/vben271/src/services/ServiceProxies.ts @@ -217,6 +217,758 @@ export class AbpApplicationConfigurationServiceProxy extends ServiceProxyBase { } } +export class TenantsServiceProxy extends ServiceProxyBase { + private instance: AxiosInstance; + private baseUrl: string; + protected jsonParseReviver: ((key: string, value: any) => any) | undefined = undefined; + + constructor(baseUrl?: string, instance?: AxiosInstance) { + super(); + this.instance = instance ? instance : axios.create(); + this.baseUrl = baseUrl !== undefined && baseUrl !== null ? baseUrl : ""; + } + + /** + * 通过名称获取租户信息 + * @param body (optional) + * @return Success + */ + find(body: FindTenantByNameInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/find"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processFind(_response)); + }); + } + + protected processFind(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = FindTenantResultDto.fromJS(resultData200); + return result200; + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 分页获取租户信息 + * @param body (optional) + * @return Success + */ + page(body: PagingTenantInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/page"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processPage(_response)); + }); + } + + protected processPage(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = TenantDtoPagedResultDto.fromJS(resultData200); + return result200; + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 创建租户 + * @param body (optional) + * @return Success + */ + create(body: TenantCreateDto | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/create"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processCreate(_response)); + }); + } + + protected processCreate(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = TenantDto.fromJS(resultData200); + return result200; + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 更新租户 + * @param body (optional) + * @return Success + */ + update(body: UpdateTenantInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/update"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processUpdate(_response)); + }); + } + + protected processUpdate(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = TenantDto.fromJS(resultData200); + return result200; + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 删除租户 + * @param body (optional) + * @return Success + */ + delete(body: IdInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/delete"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processDelete(_response)); + }); + } + + protected processDelete(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + return Promise.resolve(null); + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 获取租户连接字符串 + * @param body (optional) + * @return Success + */ + getConnectionString(body: IdInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/getConnectionString"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + "Accept": "text/plain" + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processGetConnectionString(_response)); + }); + } + + protected processGetConnectionString(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + let result200: any = null; + let resultData200 = _responseText; + result200 = resultData200 !== undefined ? resultData200 : null; + return result200; + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 更新租户连接字符串 + * @param body (optional) + * @return Success + */ + updateConnectionString(body: UpdateConnectionStringInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/updateConnectionString"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processUpdateConnectionString(_response)); + }); + } + + protected processUpdateConnectionString(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + return Promise.resolve(null); + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } + + /** + * 删除租户连接字符串 + * @param body (optional) + * @return Success + */ + deleteConnectionString(body: IdInput | undefined , cancelToken?: CancelToken | undefined): Promise { + let url_ = this.baseUrl + "/Tenants/deleteConnectionString"; + url_ = url_.replace(/[?&]$/, ""); + + const content_ = JSON.stringify(body); + + let options_ = { + data: content_, + method: "POST", + url: url_, + headers: { + "Content-Type": "application/json", + }, + cancelToken + }; + + return this.transformOptions(options_).then(transformedOptions_ => { + return this.instance.request(transformedOptions_); + }).catch((_error: any) => { + if (isAxiosError(_error) && _error.response) { + return _error.response; + } else { + throw _error; + } + }).then((_response: AxiosResponse) => { + return this.transformResult(url_, _response, (_response: AxiosResponse) => this.processDeleteConnectionString(_response)); + }); + } + + protected processDeleteConnectionString(response: AxiosResponse): Promise { + const status = response.status; + let _headers: any = {}; + if (response.headers && typeof response.headers === "object") { + for (let k in response.headers) { + if (response.headers.hasOwnProperty(k)) { + _headers[k] = response.headers[k]; + } + } + } + if (status === 200) { + const _responseText = response.data; + return Promise.resolve(null); + } else if (status === 403) { + const _responseText = response.data; + let result403: any = null; + let resultData403 = _responseText; + result403 = RemoteServiceErrorResponse.fromJS(resultData403); + return throwException("Forbidden", status, _responseText, _headers, result403); + } else if (status === 401) { + const _responseText = response.data; + let result401: any = null; + let resultData401 = _responseText; + result401 = RemoteServiceErrorResponse.fromJS(resultData401); + return throwException("Unauthorized", status, _responseText, _headers, result401); + } else if (status === 400) { + const _responseText = response.data; + let result400: any = null; + let resultData400 = _responseText; + result400 = RemoteServiceErrorResponse.fromJS(resultData400); + return throwException("Bad Request", status, _responseText, _headers, result400); + } else if (status === 404) { + const _responseText = response.data; + let result404: any = null; + let resultData404 = _responseText; + result404 = RemoteServiceErrorResponse.fromJS(resultData404); + return throwException("Not Found", status, _responseText, _headers, result404); + } else if (status === 501) { + const _responseText = response.data; + let result501: any = null; + let resultData501 = _responseText; + result501 = RemoteServiceErrorResponse.fromJS(resultData501); + return throwException("Server Error", status, _responseText, _headers, result501); + } else if (status === 500) { + const _responseText = response.data; + let result500: any = null; + let resultData500 = _responseText; + result500 = RemoteServiceErrorResponse.fromJS(resultData500); + return throwException("Server Error", status, _responseText, _headers, result500); + } else if (status !== 200 && status !== 204) { + const _responseText = response.data; + return throwException("An unexpected server error occurred.", status, _responseText, _headers); + } + return Promise.resolve(null); + } +} + export class AccountServiceProxy extends ServiceProxyBase { private instance: AxiosInstance; private baseUrl: string; @@ -8535,6 +9287,42 @@ export interface IFeatureProviderDto { key: string | undefined; } +export class FindTenantByNameInput implements IFindTenantByNameInput { + name!: string | undefined; + + constructor(data?: IFindTenantByNameInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.name = _data["name"]; + } + } + + static fromJS(data: any): FindTenantByNameInput { + data = typeof data === 'object' ? data : {}; + let result = new FindTenantByNameInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["name"] = this.name; + return data; + } +} + +export interface IFindTenantByNameInput { + name: string | undefined; +} + export class FindTenantResultDto implements IFindTenantResultDto { success!: boolean; tenantId!: string | undefined; @@ -11859,6 +12647,54 @@ export interface IPagingRoleListInput { filter: string | undefined; } +export class PagingTenantInput implements IPagingTenantInput { + pageIndex!: number; + pageSize!: number; + readonly skipCount!: number; + filter!: string | undefined; + + constructor(data?: IPagingTenantInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.pageIndex = _data["pageIndex"]; + this.pageSize = _data["pageSize"]; + (this).skipCount = _data["skipCount"]; + this.filter = _data["filter"]; + } + } + + static fromJS(data: any): PagingTenantInput { + data = typeof data === 'object' ? data : {}; + let result = new PagingTenantInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["pageIndex"] = this.pageIndex; + data["pageSize"] = this.pageSize; + data["skipCount"] = this.skipCount; + data["filter"] = this.filter; + return data; + } +} + +export interface IPagingTenantInput { + pageIndex: number; + pageSize: number; + skipCount: number; + filter: string | undefined; +} + export class PagingUserListInput implements IPagingUserListInput { pageIndex!: number; pageSize!: number; @@ -13731,6 +14567,46 @@ export interface IUpdateApiResourceInput { apiScopes: string[] | undefined; } +export class UpdateConnectionStringInput implements IUpdateConnectionStringInput { + id!: string; + connectionString!: string; + + constructor(data?: IUpdateConnectionStringInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.id = _data["id"]; + this.connectionString = _data["connectionString"]; + } + } + + static fromJS(data: any): UpdateConnectionStringInput { + data = typeof data === 'object' ? data : {}; + let result = new UpdateConnectionStringInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["id"] = this.id; + data["connectionString"] = this.connectionString; + return data; + } +} + +export interface IUpdateConnectionStringInput { + id: string; + connectionString: string; +} + export class UpdateCreateApiScopeInput implements IUpdateCreateApiScopeInput { enabled!: boolean; name!: string | undefined; @@ -14335,6 +15211,46 @@ export interface IUpdateSettingInput { values: { [key: string]: string; } | undefined; } +export class UpdateTenantInput implements IUpdateTenantInput { + id!: string; + name!: string; + + constructor(data?: IUpdateTenantInput) { + if (data) { + for (var property in data) { + if (data.hasOwnProperty(property)) + (this)[property] = (data)[property]; + } + } + } + + init(_data?: any) { + if (_data) { + this.id = _data["id"]; + this.name = _data["name"]; + } + } + + static fromJS(data: any): UpdateTenantInput { + data = typeof data === 'object' ? data : {}; + let result = new UpdateTenantInput(); + result.init(data); + return result; + } + + toJSON(data?: any) { + data = typeof data === 'object' ? data : {}; + data["id"] = this.id; + data["name"] = this.name; + return data; + } +} + +export interface IUpdateTenantInput { + id: string; + name: string; +} + export class UpdateUserInput implements IUpdateUserInput { userId!: string; userInfo!: IdentityUserUpdateDto; diff --git a/vben271/src/services/ServiceProxyBase.ts b/vben271/src/services/ServiceProxyBase.ts index bdb872bd..4127745e 100644 --- a/vben271/src/services/ServiceProxyBase.ts +++ b/vben271/src/services/ServiceProxyBase.ts @@ -10,9 +10,9 @@ export class ServiceProxyBase { protected transformOptions(options: AxiosRequestConfig) { options.baseURL = import.meta.env.VITE_API_URL as string; const guard: boolean = this.urlGuard(options.url as string); + const userStore = useUserStoreWithOut(); - if (!guard) { - const userStore = useUserStoreWithOut(); + if (guard) { if (userStore.checkUserLoginExpire) { router.replace(PageEnum.BASE_LOGIN); return; @@ -23,6 +23,12 @@ export class ServiceProxyBase { 'accept-language': language, 'Content-Type': 'application/json', Authorization: 'Bearer ' + token, + __tenant: userStore.tenantId, + }; + } else { + options.headers = { + 'Content-Type': 'application/json', + __tenant: userStore.tenantId, }; } @@ -55,8 +61,8 @@ export class ServiceProxyBase { //判决接口是否需要拦截 private urlGuard(url: string): boolean { - // 登录接口不需要拦截 - return (url.indexOf('login') as number) > 0; + let arr = ['/api/app/account/login', '/Tenants/find']; + return !arr.includes(url); } private buildRequestMessage(): any { diff --git a/vben271/src/store/modules/user.ts b/vben271/src/store/modules/user.ts index 6def5298..e56c4bf6 100644 --- a/vben271/src/store/modules/user.ts +++ b/vben271/src/store/modules/user.ts @@ -4,7 +4,13 @@ import { defineStore } from 'pinia'; import { store } from '/@/store'; import { RoleEnum } from '/@/enums/roleEnum'; import { PageEnum } from '/@/enums/pageEnum'; -import { ROLES_KEY, TOKEN_KEY, USER_INFO_KEY, ABP_LOCALE_KEY } from '/@/enums/cacheEnum'; +import { + ROLES_KEY, + TOKEN_KEY, + USER_INFO_KEY, + ABP_LOCALE_KEY, + ABP_TETANT_KEY, +} from '/@/enums/cacheEnum'; import { getAuthCache, setAuthCache } from '/@/utils/auth'; import { GetUserInfoByUserIdModel, LoginParams } from '/@/api/sys/model/userModel'; import { @@ -30,6 +36,7 @@ interface UserState { sessionTimeout?: boolean; lastUpdateTime: number; language: string; + tenantId: string; } export const useUserStore = defineStore({ @@ -46,6 +53,7 @@ export const useUserStore = defineStore({ // Last fetch time lastUpdateTime: 0, language: '', + tenantId: '', }), getters: { getUserInfo(): UserInfo { @@ -66,6 +74,9 @@ export const useUserStore = defineStore({ getLanguage(): string { return this.language || getAuthCache(ABP_LOCALE_KEY); }, + getTenant(): string { + return this.tenantId || getAuthCache(ABP_TETANT_KEY); + }, checkUserLoginExpire(): boolean { try { const userStore = useUserStoreWithOut(); @@ -98,6 +109,10 @@ export const useUserStore = defineStore({ this.lastUpdateTime = new Date().getTime(); setAuthCache(USER_INFO_KEY, info); }, + setTenant(tenantId: string) { + this.tenantId = tenantId; + setAuthCache(ABP_TETANT_KEY, tenantId); + }, setSessionTimeout(flag: boolean) { this.sessionTimeout = flag; }, diff --git a/vben271/src/utils/cache/persistent.ts b/vben271/src/utils/cache/persistent.ts index e02e9a30..cbfc6ffb 100644 --- a/vben271/src/utils/cache/persistent.ts +++ b/vben271/src/utils/cache/persistent.ts @@ -15,6 +15,7 @@ import { MULTIPLE_TABS_KEY, AUHT_KEY, ABP_LOCALE_KEY, + ABP_TETANT_KEY, } from '/@/enums/cacheEnum'; import { DEFAULT_CACHE_TIME } from '/@/settings/encryptionSetting'; import { toRaw } from 'vue'; @@ -29,6 +30,7 @@ interface BasicStore { [MULTIPLE_TABS_KEY]: RouteLocationNormalized[]; [AUHT_KEY]: ApplicationAuthConfigurationDto; [ABP_LOCALE_KEY]: string; + [ABP_TETANT_KEY]: string; } type LocalStore = BasicStore; diff --git a/vben271/src/views/identityServers/apiScopes/EditApiScope.vue b/vben271/src/views/identityServers/apiScopes/EditApiScope.vue index 097b9257..fb99b8c3 100644 --- a/vben271/src/views/identityServers/apiScopes/EditApiScope.vue +++ b/vben271/src/views/identityServers/apiScopes/EditApiScope.vue @@ -52,7 +52,7 @@ await editApiScopeAsync({ request, changeOkLoading, validate, closeModal }); resetFields(); emit('reload'); - } catch (error) { + } finally { changeOkLoading(false); } }; diff --git a/vben271/src/views/sys/login/Login.vue b/vben271/src/views/sys/login/Login.vue index 8c3bd4bb..d6073dda 100644 --- a/vben271/src/views/sys/login/Login.vue +++ b/vben271/src/views/sys/login/Login.vue @@ -55,6 +55,7 @@ + @@ -70,6 +71,7 @@ import RegisterForm from './RegisterForm.vue'; import MobileForm from './MobileForm.vue'; import QrCodeForm from './QrCodeForm.vue'; + import TenantLoginForm from './TenantLoginForm.vue'; import { useGlobSetting } from '/@/hooks/setting'; import { useI18n } from '/@/hooks/web/useI18n'; import { useDesign } from '/@/hooks/web/useDesign'; diff --git a/vben271/src/views/sys/login/LoginForm.vue b/vben271/src/views/sys/login/LoginForm.vue index 582cecf4..debcefcd 100644 --- a/vben271/src/views/sys/login/LoginForm.vue +++ b/vben271/src/views/sys/login/LoginForm.vue @@ -33,7 +33,13 @@ {{ t('sys.login.registerButton') }} --> - + + + + + {{ t('sys.login.otherSignIn') }}
@@ -58,13 +64,7 @@ import { useMessage } from '/@/hooks/web/useMessage'; import { useUserStore } from '/@/store/modules/user'; - import { - LoginStateEnum, - useLoginState, - useFormRules, - useFormValid, - useOidcLogin, - } from './useLogin'; + import { LoginStateEnum, useLoginState, useFormRules, useFormValid } from './useLogin'; import { useDesign } from '/@/hooks/web/useDesign'; //import { onKeyStroke } from '@vueuse/core'; @@ -104,6 +104,7 @@ toRaw({ password: data.password, username: data.account, + tenantId: '', mode: 'none', //不要默认的错误提示 }) ); diff --git a/vben271/src/views/sys/login/LoginFormTitle.vue b/vben271/src/views/sys/login/LoginFormTitle.vue index a673636e..3a70c84b 100644 --- a/vben271/src/views/sys/login/LoginFormTitle.vue +++ b/vben271/src/views/sys/login/LoginFormTitle.vue @@ -19,6 +19,7 @@ [LoginStateEnum.REGISTER]: t('sys.login.signUpFormTitle'), [LoginStateEnum.MOBILE]: t('sys.login.mobileSignInFormTitle'), [LoginStateEnum.QR_CODE]: t('sys.login.qrSignInFormTitle'), + [LoginStateEnum.TENANT]: t('sys.login.tenantFormTitle'), }; return titleObj[unref(getLoginState)]; }); diff --git a/vben271/src/views/sys/login/MobileForm.vue b/vben271/src/views/sys/login/MobileForm.vue index 88b9f82e..27325bae 100644 --- a/vben271/src/views/sys/login/MobileForm.vue +++ b/vben271/src/views/sys/login/MobileForm.vue @@ -2,6 +2,14 @@ + diff --git a/vben271/src/views/sys/login/useLogin.ts b/vben271/src/views/sys/login/useLogin.ts index 89729630..951e8c72 100644 --- a/vben271/src/views/sys/login/useLogin.ts +++ b/vben271/src/views/sys/login/useLogin.ts @@ -9,6 +9,7 @@ export enum LoginStateEnum { RESET_PASSWORD, MOBILE, QR_CODE, + TENANT, } const currentState = ref(LoginStateEnum.LOGIN); @@ -45,7 +46,7 @@ export function useFormRules(formData?: Recordable) { const getPasswordFormRule = computed(() => createRule(t('sys.login.passwordPlaceholder'))); const getSmsFormRule = computed(() => createRule(t('sys.login.smsPlaceholder'))); const getMobileFormRule = computed(() => createRule(t('sys.login.mobilePlaceholder'))); - + const getTenantFormRule = computed(() => createRule(t('sys.login.tenantPlaceholder'))); const validatePolicy = async (_: RuleObject, value: boolean) => { return !value ? Promise.reject(t('sys.login.policyPlaceholder')) : Promise.resolve(); }; @@ -67,11 +68,13 @@ export function useFormRules(formData?: Recordable) { const passwordFormRule = unref(getPasswordFormRule); const smsFormRule = unref(getSmsFormRule); const mobileFormRule = unref(getMobileFormRule); + const tenantFormRule = unref(getTenantFormRule); const mobileRule = { sms: smsFormRule, mobile: mobileFormRule, }; + switch (unref(currentState)) { // register form rules case LoginStateEnum.REGISTER: @@ -95,7 +98,12 @@ export function useFormRules(formData?: Recordable) { // mobile form rules case LoginStateEnum.MOBILE: return mobileRule; - + case LoginStateEnum.TENANT: + return { + account: accountFormRule, + password: passwordFormRule, + tenant: tenantFormRule, + }; // login form rules default: return { diff --git a/vben271/src/views/tenants/CreateTenant.vue b/vben271/src/views/tenants/CreateTenant.vue new file mode 100644 index 00000000..4fb8c740 --- /dev/null +++ b/vben271/src/views/tenants/CreateTenant.vue @@ -0,0 +1,63 @@ + + + + + diff --git a/vben271/src/views/tenants/EditConnectionString.vue b/vben271/src/views/tenants/EditConnectionString.vue new file mode 100644 index 00000000..5446f3fc --- /dev/null +++ b/vben271/src/views/tenants/EditConnectionString.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/vben271/src/views/tenants/EditTenant.vue b/vben271/src/views/tenants/EditTenant.vue new file mode 100644 index 00000000..f2cb7030 --- /dev/null +++ b/vben271/src/views/tenants/EditTenant.vue @@ -0,0 +1,69 @@ + + + + + diff --git a/vben271/src/views/tenants/Tenant.ts b/vben271/src/views/tenants/Tenant.ts new file mode 100644 index 00000000..23783421 --- /dev/null +++ b/vben271/src/views/tenants/Tenant.ts @@ -0,0 +1,125 @@ +import _ from 'lodash'; +import { FormSchema } from '/@/components/Table'; +import { BasicColumn } from '/@/components/Table'; +import { useI18n } from '/@/hooks/web/useI18n'; +const { t } = useI18n(); +import { TenantsServiceProxy, PagingTenantInput, IdInput } from '/@/services/ServiceProxies'; +export const searchFormSchema: FormSchema[] = [ + { + field: 'filter', + component: 'Input', + label: t('common.key'), + labelWidth: 80, + colProps: { + span: 6, + }, + }, +]; +export const tableColumns: BasicColumn[] = [ + { + title: t('routes.tenant.name'), + dataIndex: 'name', + }, +]; + +export const createFormSchema: FormSchema[] = [ + { + field: 'name', + label: 'Name', + component: 'Input', + required: true, + labelWidth: 150, + colProps: { span: 20 }, + }, + { + field: 'adminEmailAddress', + label: 'AdminEmailAddress', + component: 'Input', + required: true, + labelWidth: 150, + colProps: { span: 20 }, + }, + { + field: 'adminPassword', + label: 'AdminPassword', + component: 'InputPassword', + required: true, + labelWidth: 150, + colProps: { span: 20 }, + }, +]; +export const editFormSchema: FormSchema[] = [ + { + field: 'id', + label: 'Id', + component: 'Input', + required: true, + labelWidth: 150, + show: false, + colProps: { span: 20 }, + }, + { + field: 'name', + label: 'Name', + component: 'Input', + required: true, + labelWidth: 150, + colProps: { span: 20 }, + }, +]; +export const updateConnectionStringFormSchema: FormSchema[] = [ + { + field: 'id', + label: 'Id', + component: 'Input', + required: true, + labelWidth: 150, + show: false, + colProps: { span: 20 }, + }, + { + field: 'connectionString', + label: 'ConnectionString', + component: 'Input', + labelWidth: 150, + colProps: { span: 20 }, + }, +]; +export async function getTenantListAsync(request: PagingTenantInput) { + const _tenantsServiceProxy = new TenantsServiceProxy(); + return await _tenantsServiceProxy.page(request); +} +export async function createTenantAsync({ request, changeOkLoading, validate, closeModal }) { + changeOkLoading(true); + await validate(); + const _tenantsServiceProxy = new TenantsServiceProxy(); + await _tenantsServiceProxy.create(request); + changeOkLoading(false); + closeModal(); +} + +export async function updateTenantAsync({ request, changeOkLoading, validate, closeModal }) { + changeOkLoading(true); + await validate(); + const _tenantsServiceProxy = new TenantsServiceProxy(); + await _tenantsServiceProxy.update(request); + changeOkLoading(false); + closeModal(); +} + +export async function deleteTenantAsync({ id }) { + const _tenantsServiceProxy = new TenantsServiceProxy(); + let request = new IdInput(); + request.id = id; + await _tenantsServiceProxy.delete(request); +} +export async function getConnectionStringAsync({ id }) { + const _tenantsServiceProxy = new TenantsServiceProxy(); + let request = new IdInput(); + request.id = id; + return await _tenantsServiceProxy.getConnectionString(request); +} +export async function updateConnectionStringAsync({ request }) { + const _tenantsServiceProxy = new TenantsServiceProxy(); + return await _tenantsServiceProxy.updateConnectionString(request); +} diff --git a/vben271/src/views/tenants/Tenant.vue b/vben271/src/views/tenants/Tenant.vue new file mode 100644 index 00000000..51b57518 --- /dev/null +++ b/vben271/src/views/tenants/Tenant.vue @@ -0,0 +1,150 @@ + + + + +