Browse Source

完善系统配置页面

pull/1/head
cKey 6 years ago
parent
commit
97de8bc271
  1. 58
      aspnet-core/modules/common/LINGYUN.Abp.Identity.OverrideOptions/LINGYUN/Abp/Identity/AbpIdentityOverrideOptionsFactory.cs
  2. 5
      aspnet-core/modules/common/LINGYUN.Abp.Location.Baidu/LINGYUN.Abp.Location.Baidu.csproj
  3. 19
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs
  4. 2
      aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/ApiGatewayHttpApiHostModule.cs
  5. 8
      aspnet-core/services/cleanup-logs.bat
  6. 10
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj
  7. 268
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs
  8. 5
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/Identity/Localization/en.json
  9. 7
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/Identity/Localization/zh-Hans.json
  10. 11
      aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs
  11. 13
      vueJs/src/api/abpconfiguration.ts
  12. 17
      vueJs/src/api/settings.ts
  13. 8
      vueJs/src/lang/zh.ts
  14. 1
      vueJs/src/permission.ts
  15. 10
      vueJs/src/store/modules/abp.ts
  16. 33
      vueJs/src/store/modules/user.ts
  17. 51
      vueJs/src/utils/localStorage.ts
  18. 11
      vueJs/src/utils/request.ts
  19. 2
      vueJs/src/views/admin/apigateway/components/GlobalCreateOrEditForm.vue
  20. 2
      vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue
  21. 2
      vueJs/src/views/admin/identityServer/client/components/ClientPropertyEditForm.vue
  22. 277
      vueJs/src/views/admin/settings/components/GlobalSettingEditForm.vue
  23. 42
      vueJs/src/views/admin/settings/index.vue

58
aspnet-core/modules/common/LINGYUN.Abp.Identity.OverrideOptions/LINGYUN/Abp/Identity/AbpIdentityOverrideOptionsFactory.cs

@ -1,23 +1,77 @@
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Identity.Settings;
using Volo.Abp.Options; using Volo.Abp.Options;
using Volo.Abp.Settings;
using Volo.Abp.Threading;
namespace LINGYUN.Abp.Identity namespace LINGYUN.Abp.Identity
{ {
public class AbpIdentityOverrideOptionsFactory : AbpOptionsFactory<IdentityOptions> public class AbpIdentityOverrideOptionsFactory : AbpOptionsFactory<IdentityOptions>
{ {
protected ISettingStore SettingStore { get; }
public AbpIdentityOverrideOptionsFactory( public AbpIdentityOverrideOptionsFactory(
ISettingStore settingStore,
IEnumerable<IConfigureOptions<IdentityOptions>> setups, IEnumerable<IConfigureOptions<IdentityOptions>> setups,
IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures) IEnumerable<IPostConfigureOptions<IdentityOptions>> postConfigures)
: base(setups, postConfigures) : base(setups, postConfigures)
{ {
SettingStore = settingStore;
} }
public override IdentityOptions Create(string name) public override IdentityOptions Create(string name)
{ {
return base.Create(name); var options = base.Create(name);
// 重写为只获取公共配置
OverrideOptions(options);
return options;
}
protected virtual void OverrideOptions(IdentityOptions options)
{
AsyncHelper.RunSync(() => OverrideOptionsAsync(options));
}
protected virtual async Task OverrideOptionsAsync(IdentityOptions options)
{
options.Password.RequiredLength = await GetOrDefaultAsync(IdentitySettingNames.Password.RequiredLength, options.Password.RequiredLength);
options.Password.RequiredUniqueChars = await GetOrDefaultAsync(IdentitySettingNames.Password.RequiredUniqueChars, options.Password.RequiredUniqueChars);
options.Password.RequireNonAlphanumeric = await GetOrDefaultAsync(IdentitySettingNames.Password.RequireNonAlphanumeric, options.Password.RequireNonAlphanumeric);
options.Password.RequireLowercase = await GetOrDefaultAsync(IdentitySettingNames.Password.RequireLowercase, options.Password.RequireLowercase);
options.Password.RequireUppercase = await GetOrDefaultAsync(IdentitySettingNames.Password.RequireUppercase, options.Password.RequireUppercase);
options.Password.RequireDigit = await GetOrDefaultAsync(IdentitySettingNames.Password.RequireDigit, options.Password.RequireDigit);
options.Lockout.AllowedForNewUsers = await GetOrDefaultAsync(IdentitySettingNames.Lockout.AllowedForNewUsers, options.Lockout.AllowedForNewUsers);
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromSeconds(await GetOrDefaultAsync(IdentitySettingNames.Lockout.LockoutDuration, options.Lockout.DefaultLockoutTimeSpan.TotalSeconds.To<int>()));
options.Lockout.MaxFailedAccessAttempts = await GetOrDefaultAsync(IdentitySettingNames.Lockout.MaxFailedAccessAttempts, options.Lockout.MaxFailedAccessAttempts);
options.SignIn.RequireConfirmedEmail = await GetOrDefaultAsync(IdentitySettingNames.SignIn.RequireConfirmedEmail, options.SignIn.RequireConfirmedEmail);
options.SignIn.RequireConfirmedPhoneNumber = await GetOrDefaultAsync(IdentitySettingNames.SignIn.RequireConfirmedPhoneNumber, options.SignIn.RequireConfirmedPhoneNumber);
}
protected virtual async Task<T> GetOrDefaultAsync<T>(string name, T defaultValue = default(T)) where T : struct
{
var setting = await SettingStore.GetOrNullAsync(name, GlobalSettingValueProvider.ProviderName, null);
if (setting.IsNullOrWhiteSpace())
{
return defaultValue;
}
return setting.To<T>();
}
protected virtual async Task<string> GetOrDefaultAsync(string name, string defaultValue = "")
{
var setting = await SettingStore.GetOrNullAsync(name, GlobalSettingValueProvider.ProviderName, null);
if (setting.IsNullOrWhiteSpace())
{
return defaultValue;
}
return setting;
} }
} }
} }

5
aspnet-core/modules/common/LINGYUN.Abp.Location.Baidu/LINGYUN.Abp.Location.Baidu.csproj

@ -5,6 +5,11 @@
<RootNamespace /> <RootNamespace />
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Http" Version="3.1.2" />
<PackageReference Include="Volo.Abp.Json" Version="2.8.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\LINGYUN.Abp.Location\LINGYUN.Abp.Location.csproj" /> <ProjectReference Include="..\LINGYUN.Abp.Location\LINGYUN.Abp.Location.csproj" />
</ItemGroup> </ItemGroup>

19
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs

@ -5,6 +5,7 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Volo.Abp.Application.Dtos; using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services; using Volo.Abp.Application.Services;
using Volo.Abp.Caching;
using Volo.Abp.SettingManagement; using Volo.Abp.SettingManagement;
using Volo.Abp.SettingManagement.Localization; using Volo.Abp.SettingManagement.Localization;
using Volo.Abp.Settings; using Volo.Abp.Settings;
@ -16,9 +17,14 @@ namespace LINGYUN.Abp.SettingManagement
{ {
protected ISettingManager SettingManager { get; } protected ISettingManager SettingManager { get; }
protected ISettingDefinitionManager SettingDefinitionManager { get; } protected ISettingDefinitionManager SettingDefinitionManager { get; }
public SettingAppService(ISettingManager settingManager,
protected IDistributedCache<SettingCacheItem> Cache { get; }
public SettingAppService(
ISettingManager settingManager,
IDistributedCache<SettingCacheItem> cache,
ISettingDefinitionManager settingDefinitionManager) ISettingDefinitionManager settingDefinitionManager)
{ {
Cache = cache;
SettingManager = settingManager; SettingManager = settingManager;
SettingDefinitionManager = settingDefinitionManager; SettingDefinitionManager = settingDefinitionManager;
LocalizationResource = typeof(AbpSettingManagementResource); LocalizationResource = typeof(AbpSettingManagementResource);
@ -54,8 +60,17 @@ namespace LINGYUN.Abp.SettingManagement
{ {
foreach (var setting in input.Settings) foreach (var setting in input.Settings)
{ {
await SettingManager.SetAsync(setting.Name, providerName, providerKey, setting.Value); await SettingManager.SetAsync(setting.Name, setting.Value, providerName, providerKey);
// 同步变更缓存配置
var settingCacheKey = CalculateCacheKey(setting.Name, providerName, providerKey);
var settignCacheItem = new SettingCacheItem(setting.Value);
await Cache.SetAsync(settingCacheKey, settignCacheItem);
} }
} }
protected virtual string CalculateCacheKey(string name, string providerName, string providerKey)
{
return SettingCacheItem.CalculateCacheKey(name, providerName, providerKey);
}
} }
} }

2
aspnet-core/services/apigateway/LINGYUN.ApiGateway.HttpApi.Host/ApiGatewayHttpApiHostModule.cs

@ -163,7 +163,7 @@ namespace LINGYUN.ApiGateway
// 审计日志 // 审计日志
app.UseAuditing(); app.UseAuditing();
// 路由 // 路由
app.UseMvcWithDefaultRouteAndArea(); app.UseConfiguredEndpoints();
} }
} }
} }

8
aspnet-core/services/cleanup-logs.bat

@ -0,0 +1,8 @@
@echo off
cls
chcp 65001
echo. 启动平台管理服务
cd .\platform\LINGYUN.Platform.HttpApi.Host

10
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN.Platform.HttpApi.Host.csproj

@ -5,6 +5,16 @@
<RootNamespace>LINGYUN.Platform</RootNamespace> <RootNamespace>LINGYUN.Platform</RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Content Remove="LINGYUN\Platform\Identity\Localization\en.json" />
<Content Remove="LINGYUN\Platform\Identity\Localization\zh-Hans.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="LINGYUN\Platform\Identity\Localization\en.json" />
<EmbeddedResource Include="LINGYUN\Platform\Identity\Localization\zh-Hans.json" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DotNetCore.CAP.MySql" Version="3.0.3" /> <PackageReference Include="DotNetCore.CAP.MySql" Version="3.0.3" />
<PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="3.0.3" /> <PackageReference Include="DotNetCore.CAP.RabbitMQ" Version="3.0.3" />

268
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/AspNetCore/Mvc/ApplicationConfigurations/AbpApplicationConfigurationAppService.cs

@ -0,0 +1,268 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations;
using Volo.Abp.AspNetCore.Mvc.ApplicationConfigurations.ObjectExtending;
using Volo.Abp.AspNetCore.Mvc.MultiTenancy;
using Volo.Abp.Authorization.Permissions;
using Volo.Abp.Clients;
using Volo.Abp.DependencyInjection;
using Volo.Abp.EventBus.Local;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.MultiTenancy;
using Volo.Abp.PermissionManagement;
using Volo.Abp.Settings;
using Volo.Abp.Users;
namespace LINGYUN.Platform.AspNetCore.Mvc.ApplicationConfigurations
{
[Dependency(ServiceLifetime.Transient)]
[ExposeServices(typeof(IAbpApplicationConfigurationAppService))]
public class AbpApplicationConfigurationAppService : ApplicationService, IAbpApplicationConfigurationAppService
{
private readonly AbpLocalizationOptions _localizationOptions;
private readonly AbpMultiTenancyOptions _multiTenancyOptions;
private readonly IServiceProvider _serviceProvider;
private readonly ISettingProvider _settingProvider;
private readonly ISettingDefinitionManager _settingDefinitionManager;
private readonly IFeatureDefinitionManager _featureDefinitionManager;
private readonly IPermissionGrantRepository _permissionGrantRepository;
private readonly IPermissionDefinitionManager _permissionDefinitionManager;
private readonly ILanguageProvider _languageProvider;
private readonly ICachedObjectExtensionsDtoService _cachedObjectExtensionsDtoService;
private ICurrentClient _currentClient;
protected ICurrentClient CurrentClient => LazyGetRequiredService(ref _currentClient);
private ILocalEventBus _localEventBus;
//用于发布权限事件,每次请求此接口后,通过事件总线来缓存权限
protected ILocalEventBus LocalEventBus => LazyGetRequiredService(ref _localEventBus);
public AbpApplicationConfigurationAppService(
IOptions<AbpLocalizationOptions> localizationOptions,
IOptions<AbpMultiTenancyOptions> multiTenancyOptions,
IServiceProvider serviceProvider,
ISettingProvider settingProvider,
ISettingDefinitionManager settingDefinitionManager,
IFeatureDefinitionManager featureDefinitionManager,
IPermissionGrantRepository permissionGrantRepository,
IPermissionDefinitionManager permissionDefinitionManager,
ILanguageProvider languageProvider,
ICachedObjectExtensionsDtoService cachedObjectExtensionsDtoService)
{
_serviceProvider = serviceProvider;
_settingProvider = settingProvider;
_settingDefinitionManager = settingDefinitionManager;
_featureDefinitionManager = featureDefinitionManager;
_permissionGrantRepository = permissionGrantRepository;
_permissionDefinitionManager = permissionDefinitionManager;
_languageProvider = languageProvider;
_cachedObjectExtensionsDtoService = cachedObjectExtensionsDtoService;
_localizationOptions = localizationOptions.Value;
_multiTenancyOptions = multiTenancyOptions.Value;
}
public virtual async Task<ApplicationConfigurationDto> GetAsync()
{
//TODO: Optimize & cache..?
Logger.LogDebug("Executing AbpApplicationConfigurationAppService.GetAsync()...");
var result = new ApplicationConfigurationDto
{
Auth = await GetAuthConfigAsync(),
Features = await GetFeaturesConfigAsync(),
Localization = await GetLocalizationConfigAsync(),
CurrentUser = GetCurrentUser(),
Setting = await GetSettingConfigAsync(),
MultiTenancy = GetMultiTenancy(),
CurrentTenant = GetCurrentTenant(),
ObjectExtensions = _cachedObjectExtensionsDtoService.Get()
};
Logger.LogDebug("Executed AbpApplicationConfigurationAppService.GetAsync().");
return result;
}
protected virtual CurrentTenantDto GetCurrentTenant()
{
return new CurrentTenantDto()
{
Id = CurrentTenant.Id,
Name = CurrentTenant.Name,
IsAvailable = CurrentTenant.IsAvailable
};
}
protected virtual MultiTenancyInfoDto GetMultiTenancy()
{
return new MultiTenancyInfoDto
{
IsEnabled = _multiTenancyOptions.IsEnabled
};
}
protected virtual CurrentUserDto GetCurrentUser()
{
return new CurrentUserDto
{
IsAuthenticated = CurrentUser.IsAuthenticated,
Id = CurrentUser.Id,
TenantId = CurrentUser.TenantId,
UserName = CurrentUser.UserName,
Email = CurrentUser.Email
};
}
protected virtual async Task<ApplicationAuthConfigurationDto> GetAuthConfigAsync()
{
var authConfig = new ApplicationAuthConfigurationDto();
var permissions = _permissionDefinitionManager.GetPermissions();
IEnumerable<PermissionGrant> grantPermissions = new List<PermissionGrant>();
// TODO: 重写为每次调用接口都在数据库统一查询权限
// 待框架改进权限Provider机制后再移除
// 如果用户已登录,获取用户和角色权限
if (CurrentUser.IsAuthenticated)
{
var userPermissions = await _permissionGrantRepository.GetListAsync(UserPermissionValueProvider.ProviderName,
CurrentUser.GetId().ToString());
grantPermissions = grantPermissions.Union(userPermissions);
foreach(var userRole in CurrentUser.Roles)
{
var rolePermissions = await _permissionGrantRepository.GetListAsync(RolePermissionValueProvider.ProviderName,
userRole);
grantPermissions = grantPermissions.Union(rolePermissions);
}
}
// 如果客户端已验证,获取客户端权限
if(CurrentClient.IsAuthenticated)
{
var clientPermissions = await _permissionGrantRepository.GetListAsync(ClientPermissionValueProvider.ProviderName,
CurrentClient.Id);
grantPermissions = grantPermissions.Union(clientPermissions);
}
foreach(var permission in permissions)
{
authConfig.Policies[permission.Name] = true;
if(grantPermissions.Any(p => p.Name.Equals(permission.Name)))
{
authConfig.GrantedPolicies[permission.Name] = true;
}
}
return authConfig;
}
protected virtual async Task<ApplicationLocalizationConfigurationDto> GetLocalizationConfigAsync()
{
var localizationConfig = new ApplicationLocalizationConfigurationDto();
localizationConfig.Languages.AddRange(await _languageProvider.GetLanguagesAsync());
foreach (var resource in _localizationOptions.Resources.Values)
{
var dictionary = new Dictionary<string, string>();
var localizer = _serviceProvider.GetRequiredService(
typeof(IStringLocalizer<>).MakeGenericType(resource.ResourceType)
) as IStringLocalizer;
foreach (var localizedString in localizer.GetAllStrings())
{
dictionary[localizedString.Name] = localizedString.Value;
}
localizationConfig.Values[resource.ResourceName] = dictionary;
}
localizationConfig.CurrentCulture = GetCurrentCultureInfo();
if (_localizationOptions.DefaultResourceType != null)
{
localizationConfig.DefaultResourceName = LocalizationResourceNameAttribute.GetName(
_localizationOptions.DefaultResourceType
);
}
return localizationConfig;
}
private static CurrentCultureDto GetCurrentCultureInfo()
{
return new CurrentCultureDto
{
Name = CultureInfo.CurrentUICulture.Name,
DisplayName = CultureInfo.CurrentUICulture.DisplayName,
EnglishName = CultureInfo.CurrentUICulture.EnglishName,
NativeName = CultureInfo.CurrentUICulture.NativeName,
IsRightToLeft = CultureInfo.CurrentUICulture.TextInfo.IsRightToLeft,
CultureName = CultureInfo.CurrentUICulture.TextInfo.CultureName,
TwoLetterIsoLanguageName = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName,
ThreeLetterIsoLanguageName = CultureInfo.CurrentUICulture.ThreeLetterISOLanguageName,
DateTimeFormat = new DateTimeFormatDto
{
CalendarAlgorithmType = CultureInfo.CurrentUICulture.DateTimeFormat.Calendar.AlgorithmType.ToString(),
DateTimeFormatLong = CultureInfo.CurrentUICulture.DateTimeFormat.LongDatePattern,
ShortDatePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern,
FullDateTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.FullDateTimePattern,
DateSeparator = CultureInfo.CurrentUICulture.DateTimeFormat.DateSeparator,
ShortTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.ShortTimePattern,
LongTimePattern = CultureInfo.CurrentUICulture.DateTimeFormat.LongTimePattern,
}
};
}
private async Task<ApplicationSettingConfigurationDto> GetSettingConfigAsync()
{
var result = new ApplicationSettingConfigurationDto
{
Values = new Dictionary<string, string>()
};
foreach (var settingDefinition in _settingDefinitionManager.GetAll())
{
if (!settingDefinition.IsVisibleToClients)
{
continue;
}
result.Values[settingDefinition.Name] = await _settingProvider.GetOrNullAsync(settingDefinition.Name);
}
return result;
}
protected virtual async Task<ApplicationFeatureConfigurationDto> GetFeaturesConfigAsync()
{
var result = new ApplicationFeatureConfigurationDto();
foreach (var featureDefinition in _featureDefinitionManager.GetAll())
{
if (!featureDefinition.IsVisibleToClients)
{
continue;
}
result.Values[featureDefinition.Name] = await FeatureChecker.GetOrNullAsync(featureDefinition.Name);
}
return result;
}
}
}

5
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/Identity/Localization/en.json

@ -0,0 +1,5 @@
{
"culture": "en",
"texts": {
}
}

7
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/LINGYUN/Platform/Identity/Localization/zh-Hans.json

@ -0,0 +1,7 @@
{
"culture": "zh-Hans",
"texts": {
"DisplayName:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "启用电话号码确认",
"Description:Abp.Identity.SignIn.EnablePhoneNumberConfirmation": "用户是否可以确认电话号码."
}
}

11
aspnet-core/services/platform/LINGYUN.Platform.HttpApi.Host/PlatformHttpApiHostModule.cs

@ -29,6 +29,7 @@ using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.MySQL; using Volo.Abp.EntityFrameworkCore.MySQL;
using Volo.Abp.Identity; using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore; using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.Identity.Localization;
using Volo.Abp.IdentityServer.EntityFrameworkCore; using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Localization; using Volo.Abp.Localization;
using Volo.Abp.Modularity; using Volo.Abp.Modularity;
@ -40,6 +41,7 @@ using Volo.Abp.PermissionManagement.IdentityServer;
using Volo.Abp.Security.Claims; using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.EntityFrameworkCore; using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement.EntityFrameworkCore; using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.VirtualFileSystem;
using AbpPermissionManagementApplicationModule = LINGYUN.Abp.PermissionManagement.AbpPermissionManagementApplicationModule; using AbpPermissionManagementApplicationModule = LINGYUN.Abp.PermissionManagement.AbpPermissionManagementApplicationModule;
namespace LINGYUN.Platform namespace LINGYUN.Platform
@ -107,6 +109,11 @@ namespace LINGYUN.Platform
options.UseMySQL(); options.UseMySQL();
}); });
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<PlatformHttpApiHostModule>("LINGYUN.Platform");
});
// 多租户 // 多租户
Configure<AbpMultiTenancyOptions>(options => Configure<AbpMultiTenancyOptions>(options =>
{ {
@ -132,6 +139,10 @@ namespace LINGYUN.Platform
{ {
options.Languages.Add(new LanguageInfo("en", "en", "English")); options.Languages.Add(new LanguageInfo("en", "en", "English"));
options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文")); options.Languages.Add(new LanguageInfo("zh-Hans", "zh-Hans", "简体中文"));
options.Resources
.Get<IdentityResource>()
.AddVirtualJson("/LINGYUN/Platform/Identity/Localization");
}); });
context.Services.AddAuthentication("Bearer") context.Services.AddAuthentication("Bearer")

13
vueJs/src/api/abpconfiguration.ts

@ -5,7 +5,12 @@ const serviceUrl = process.env.VUE_APP_BASE_API
export default class AbpConfigurationService { export default class AbpConfigurationService {
public static getAbpConfiguration() { public static getAbpConfiguration() {
const _url = '/api/abp/application-configuration' const _url = '/api/abp/application-configuration'
return ApiService.Get<AbpConfiguration>(_url, serviceUrl) return ApiService.HttpRequest<AbpConfiguration>({
url: _url,
baseURL: serviceUrl,
method: 'GET',
timeout: 120000
})
} }
} }
@ -65,15 +70,15 @@ export class Localization {
currentCulture!: CurrentCulture currentCulture!: CurrentCulture
defaultResourceName?: string defaultResourceName?: string
languages!: Language[] languages!: Language[]
values!: {[key:string]: {[key:string]: string}} values!: {[key:string]:{[key:string]:string}}
} }
export class MultiTenancy { export class MultiTenancy {
isEnabled!: boolean isEnabled = false
} }
export class Setting { export class Setting {
values?: {[key:string]: string} values?: {[key:string]:string}
} }
export interface IAbpConfiguration { export interface IAbpConfiguration {

17
vueJs/src/api/settings.ts

@ -13,7 +13,7 @@ export default class SettingApiService {
public static getSettings(providerName: string, providerKey: string) { public static getSettings(providerName: string, providerKey: string) {
let _url = '/api/abp/setting' let _url = '/api/abp/setting'
_url += '?providerName=' + providerName _url += '?providerName=' + providerName
_url += '?providerKey=' + providerKey _url += '&providerKey=' + providerKey
return ApiService.Get<ListResultDto<Setting>>(_url, IdentityService) return ApiService.Get<ListResultDto<Setting>>(_url, IdentityService)
} }
@ -24,10 +24,10 @@ export default class SettingApiService {
* @param payload * @param payload
* @returns Promise对象 * @returns Promise对象
*/ */
public setSettings(providerName: string, providerKey: string, payload: SettingsUpdate) { public static setSettings(providerName: string, providerKey: string, payload: SettingsUpdate) {
let _url = '/api/abp/setting' let _url = '/api/abp/setting'
_url += '?providerName=' + providerName _url += '?providerName=' + providerName
_url += '?providerKey=' + providerKey _url += '&providerKey=' + providerKey
return ApiService.Put<any>(_url, payload, IdentityService) return ApiService.Put<any>(_url, payload, IdentityService)
} }
} }
@ -36,17 +36,24 @@ export class SettingBase {
/** 名称 */ /** 名称 */
name!: string name!: string
/** 当前设置值 */ /** 当前设置值 */
value!: string value!: any
} }
/** 设置对象 */ /** 设置对象 */
export class Setting extends SettingBase{ export class Setting extends SettingBase {
/** 显示名称 */ /** 显示名称 */
displayName!: string displayName!: string
/** 说明 */ /** 说明 */
description!: string description!: string
/** 默认设置 */ /** 默认设置 */
defaultValue!: string defaultValue!: string
public getValue() {
if (this.value) {
return this.value
}
return this.defaultValue
}
} }
/** 配置变更对象 */ /** 配置变更对象 */

8
vueJs/src/lang/zh.ts

@ -197,7 +197,13 @@ export default {
showTagsView: '显示 Tags-View', showTagsView: '显示 Tags-View',
showSidebarLogo: '显示侧边栏 Logo', showSidebarLogo: '显示侧边栏 Logo',
fixedHeader: '固定 Header', fixedHeader: '固定 Header',
sidebarTextTheme: '侧边栏文字主题色' sidebarTextTheme: '侧边栏文字主题色',
globalSetting: '公共设置',
tenantSetting: '租户设置',
userSetting: '用户设置',
passwordSecurity: '密码安全',
systemSetting: '系统配置',
userAccount: '用户账户'
}, },
task: { task: {
title: '任务管理' title: '任务管理'

1
vueJs/src/permission.ts

@ -4,6 +4,7 @@ import 'nprogress/nprogress.css'
import { Message } from 'element-ui' import { Message } from 'element-ui'
import { Route } from 'vue-router' import { Route } from 'vue-router'
import { UserModule } from '@/store/modules/user' import { UserModule } from '@/store/modules/user'
import { AbpConfigurationModule } from '@/store/modules/abp'
import { PermissionModule } from '@/store/modules/permission' import { PermissionModule } from '@/store/modules/permission'
import i18n from '@/lang' // Internationalization import i18n from '@/lang' // Internationalization
import settings from './settings' import settings from './settings'

10
vueJs/src/store/modules/abp.ts

@ -1,20 +1,22 @@
import store from '@/store' import store from '@/store'
import { getAbpConfig, setAbpConfig } from '@/utils/localStorage' import { getItemJson, setItem } from '@/utils/localStorage'
import AbpConfigurationService, { IAbpConfiguration } from '@/api/abpconfiguration' import AbpConfigurationService, { IAbpConfiguration, AbpConfiguration as AbpConfig } from '@/api/abpconfiguration'
import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators' import { VuexModule, Module, Mutation, Action, getModule } from 'vuex-module-decorators'
export interface IAbpConfigurationState { export interface IAbpConfigurationState {
configuration: IAbpConfiguration configuration: IAbpConfiguration
} }
const abpConfigurationKey = 'vue_admin_abp_configuration'
@Module({ dynamic: true, store, name: 'abpconfiguration' }) @Module({ dynamic: true, store, name: 'abpconfiguration' })
class AbpConfiguration extends VuexModule implements IAbpConfigurationState { class AbpConfiguration extends VuexModule implements IAbpConfigurationState {
configuration = getAbpConfig() configuration = getItemJson(abpConfigurationKey) || new AbpConfig()
@Mutation @Mutation
private SET_ABPCONFIGURATION(configuration: IAbpConfiguration) { private SET_ABPCONFIGURATION(configuration: IAbpConfiguration) {
this.configuration = configuration this.configuration = configuration
setAbpConfig(configuration) setItem(abpConfigurationKey, JSON.stringify(configuration))
} }
@Action({ rawError: true }) @Action({ rawError: true })

33
vueJs/src/store/modules/user.ts

@ -1,7 +1,7 @@
import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators' import { VuexModule, Module, Action, Mutation, getModule } from 'vuex-module-decorators'
import UserApiService, { UserLoginData, UserLoginPhoneData } from '@/api/users' import UserApiService, { UserLoginData, UserLoginPhoneData } from '@/api/users'
import TenantService from '@/api/tenant' import TenantService from '@/api/tenant'
import { getToken, setToken, removeToken, getRefreshToken, setRefreshToken } from '@/utils/localStorage' import { getItem, setItem, removeItem } from '@/utils/localStorage'
import { resetRouter } from '@/router' import { resetRouter } from '@/router'
import { TagsViewModule } from './tags-view' import { TagsViewModule } from './tags-view'
import { removeTenant, setTenant } from '@/utils/sessions' import { removeTenant, setTenant } from '@/utils/sessions'
@ -11,15 +11,20 @@ import store from '@/store'
export interface IUserState { export interface IUserState {
token: string token: string
refreshToken: string
id: string id: string
name: string name: string
roles: string[] roles: string[]
email: string email: string
} }
const tokenKey = 'vue_typescript_admin_token'
const refreshTokenKey = 'vue_typescript_admin_refresh_token'
@Module({ dynamic: true, store, name: 'user' }) @Module({ dynamic: true, store, name: 'user' })
class User extends VuexModule implements IUserState { class User extends VuexModule implements IUserState {
public token = getToken() || '' public token = getItem(tokenKey)
public refreshToken = getItem(refreshTokenKey)
public id = '' public id = ''
public name = '' public name = ''
public roles: string[] = [] public roles: string[] = []
@ -28,7 +33,13 @@ class User extends VuexModule implements IUserState {
@Mutation @Mutation
private SET_TOKEN(token: string) { private SET_TOKEN(token: string) {
this.token = token this.token = token
setToken(token) setItem(tokenKey, token)
}
@Mutation
private SET_REFRESHTOKEN(token: string) {
this.refreshToken = token
setItem(refreshTokenKey, token)
} }
@Mutation @Mutation
@ -62,7 +73,7 @@ class User extends VuexModule implements IUserState {
const loginResult = await UserApiService.userLogin(userLoginData) const loginResult = await UserApiService.userLogin(userLoginData)
const token = loginResult.token_type + ' ' + loginResult.access_token const token = loginResult.token_type + ' ' + loginResult.access_token
this.SET_TOKEN(token) this.SET_TOKEN(token)
setRefreshToken(loginResult.refresh_token) this.SET_REFRESHTOKEN(loginResult.refresh_token)
await this.PostLogin() await this.PostLogin()
} }
@ -77,13 +88,13 @@ class User extends VuexModule implements IUserState {
const loginResult = await UserApiService.userLoginWithPhone(userLoginData) const loginResult = await UserApiService.userLoginWithPhone(userLoginData)
const token = loginResult.token_type + ' ' + loginResult.access_token const token = loginResult.token_type + ' ' + loginResult.access_token
this.SET_TOKEN(token) this.SET_TOKEN(token)
setRefreshToken(loginResult.refresh_token) this.SET_REFRESHTOKEN(loginResult.refresh_token)
await this.PostLogin() await this.PostLogin()
} }
@Action @Action
public ResetToken() { public ResetToken() {
removeToken() removeItem(tokenKey)
removeTenant() removeTenant()
this.SET_TOKEN('') this.SET_TOKEN('')
this.SET_ROLES([]) this.SET_ROLES([])
@ -106,13 +117,15 @@ class User extends VuexModule implements IUserState {
if (this.token === '') { if (this.token === '') {
throw Error('LogOut: token is undefined!') throw Error('LogOut: token is undefined!')
} }
const token = getRefreshToken() const token = getItem(refreshTokenKey)
if (token) { if (token) {
await UserApiService.userLogout(token) await UserApiService.userLogout(token)
} }
this.SET_TOKEN('') this.SET_TOKEN('')
this.SET_REFRESHTOKEN('')
this.SET_ROLES([]) this.SET_ROLES([])
removeToken() removeItem(tokenKey)
removeItem(refreshTokenKey)
removeTenant() removeTenant()
resetRouter() resetRouter()
// Reset visited views and cached views // Reset visited views and cached views
@ -124,12 +137,12 @@ class User extends VuexModule implements IUserState {
@Action @Action
public RefreshSession() { public RefreshSession() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const token = getToken() const token = getItem(tokenKey)
if (token) { if (token) {
UserApiService.refreshToken(token).then(result => { UserApiService.refreshToken(token).then(result => {
const token = result.token_type + ' ' + result.access_token const token = result.token_type + ' ' + result.access_token
setRefreshToken(result.refresh_token)
this.SET_TOKEN(token) this.SET_TOKEN(token)
this.SET_REFRESHTOKEN(result.refresh_token)
return resolve(result) return resolve(result)
}).catch(error => { }).catch(error => {
return reject(error) return reject(error)

51
vueJs/src/utils/localStorage.ts

@ -1,38 +1,27 @@
import { AbpConfiguration } from '@/api/abpconfiguration' export function getItem(key: string) {
const abpConfigKey = 'vue_admin_abp_configuration' const item = localStorage.getItem(key)
export const getAbpConfig = () => { if (item) {
const abpConfigItem = localStorage.getItem(abpConfigKey) return item
if (abpConfigItem) {
return JSON.parse(abpConfigItem) as AbpConfiguration
} }
return new AbpConfiguration() return ''
}
export const setAbpConfig = (abpConfig: AbpConfiguration) => {
const abpConfigItem = JSON.stringify(abpConfig)
localStorage.setItem(abpConfigKey, abpConfigItem)
} }
export const removeAbpConfig = () => localStorage.removeItem(abpConfigKey)
// User export function getItemJson(key: string) {
const tokenKey = 'vue_typescript_admin_token' const item = localStorage.getItem(key)
const refreshTokenKey = 'vue_typescript_admin_refresh_token' if (item) {
export function getToken() { return JSON.parse(item)
const tokenItem = localStorage.getItem(tokenKey)
if (tokenItem) {
return tokenItem
} }
return '' return null
} }
export const setToken = (token: string) => localStorage.setItem(tokenKey, token)
export const getRefreshToken = () => { export function setItem(key: string, value: string) {
const tokenItem = localStorage.getItem(refreshTokenKey) localStorage.setItem(key, value)
if (tokenItem) { }
return tokenItem
} export function removeItem(key: string) {
return '' localStorage.removeItem(key)
} }
export const setRefreshToken = (token: string) => localStorage.setItem(refreshTokenKey, token)
export const removeToken = () => { export function clear() {
localStorage.removeItem(tokenKey) localStorage.clear()
localStorage.removeItem(refreshTokenKey)
} }

11
vueJs/src/utils/request.ts

@ -4,7 +4,6 @@ import { MessageBox, Notification } from 'element-ui'
import { UserModule } from '@/store/modules/user' import { UserModule } from '@/store/modules/user'
import { getTenant } from '@/utils/sessions' import { getTenant } from '@/utils/sessions'
import { getLanguage } from '@/utils/cookies' import { getLanguage } from '@/utils/cookies'
import { getToken, getRefreshToken } from '@/utils/localStorage'
const service = axios.create({ const service = axios.create({
baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url baseURL: process.env.VUE_APP_BASE_API, // url = base url + request url
@ -18,10 +17,9 @@ service.interceptors.request.use(
if (config.url === '/connect/token') { if (config.url === '/connect/token') {
return config return config
} }
const token = getToken()
// Add X-Access-Token header to every request, you can add other custom headers here // Add X-Access-Token header to every request, you can add other custom headers here
if (token) { if (UserModule.token) {
config.headers.Authorization = token config.headers.Authorization = UserModule.token
} }
const tenantId = getTenant() const tenantId = getTenant()
if (tenantId) { if (tenantId) {
@ -100,8 +98,7 @@ service.interceptors.response.use(
(error) => { (error) => {
showError(error.response.data, error.response.status) showError(error.response.data, error.response.status)
if (error.response.status === 401) { if (error.response.status === 401) {
const token = getRefreshToken() if (UserModule.refreshToken) {
if (token) {
UserModule.RefreshSession().then(() => { UserModule.RefreshSession().then(() => {
return service.request(error.config) return service.request(error.config)
}).catch(() => { }).catch(() => {
@ -110,7 +107,7 @@ service.interceptors.response.use(
l('login.confirmLogout'), l('login.confirmLogout'),
{ {
confirmButtonText: l('login.relogin'), confirmButtonText: l('login.relogin'),
cancelButtonText: l('global.cancel'), cancelButtonText: l('global.cancel'),
type: 'error' type: 'error'
}).then(() => { }).then(() => {
UserModule.ResetToken() UserModule.ResetToken()

2
vueJs/src/views/admin/apigateway/components/GlobalCreateOrEditForm.vue

@ -445,7 +445,7 @@ export default class extends Vue {
} }
private onCancel() { private onCancel() {
this.appId = '' this.globalConfiguration = new GlobalConfigurationDto()
const formGlobal = this.$refs.formGlobal as any const formGlobal = this.$refs.formGlobal as any
formGlobal.resetFields() formGlobal.resetFields()
this.$emit('closed', false) this.$emit('closed', false)

2
vueJs/src/views/admin/identityServer/api-resources/components/ApiResourceCreateOrEditForm.vue

@ -91,7 +91,7 @@ export default class extends Vue {
private apiResource: ApiResource private apiResource: ApiResource
private apiResourceRules = { private apiResourceRules = {
name: [ name: [
{ required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.apiResourceName') }), trigger: 'blur' } { required: true, message: this.l('pleaseInputBy', { key: this.l('identityServer.resourceName') }), trigger: 'blur' }
] ]
} }

2
vueJs/src/views/admin/identityServer/client/components/ClientPropertyEditForm.vue

@ -36,7 +36,7 @@
:disabled="!checkPermission(['IdentityServer.Clients.Properties.Create'])" :disabled="!checkPermission(['IdentityServer.Clients.Properties.Create'])"
@click="onSaveClientProperty" @click="onSaveClientProperty"
> >
{{ $t('identityServer.createProperty') }} {{ $t('identityServer.createClientProperty') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>

277
vueJs/src/views/admin/settings/components/GlobalSettingEditForm.vue

@ -0,0 +1,277 @@
<template>
<div v-if="globalSettingLoaded">
<el-form
v-if="globalSettingLoaded"
ref="formGlobalSetting"
v-model="globalSetting"
label-width="180px"
style="width: 96%"
>
<el-tabs>
<el-tab-pane :label="$t('settings.systemSetting')">
<el-form-item
prop="globalSetting['Abp.Localization.DefaultLanguage'].value"
:label="globalSetting['Abp.Localization.DefaultLanguage'].displayName"
>
<el-input
v-model="globalSetting['Abp.Localization.DefaultLanguage'].value"
:placeholder="globalSetting['Abp.Localization.DefaultLanguage'].description"
@input="(value) => handleSettingValueChanged('Abp.Localization.DefaultLanguage', value)"
/>
</el-form-item>
</el-tab-pane>
<el-tab-pane
v-if="allowIdentitySetting"
:label="$t('settings.passwordSecurity')"
>
<el-form-item :label="globalSetting['Abp.Identity.Password.RequiredLength'].displayName">
<el-input
v-model="globalSetting['Abp.Identity.Password.RequiredLength'].value"
:placeholder="globalSetting['Abp.Identity.Password.RequiredLength'].description"
type="number"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequiredLength', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Identity.Password.RequiredUniqueChars'].displayName">
<el-input
v-model="globalSetting['Abp.Identity.Password.RequiredUniqueChars'].value"
type="number"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequiredUniqueChars', value)"
/>
</el-form-item>
<el-row>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.Password.RequireNonAlphanumeric'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.Password.RequireNonAlphanumeric'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequireNonAlphanumeric', value)"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.Password.RequireLowercase'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.Password.RequireLowercase'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequireLowercase', value)"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.Password.RequireUppercase'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.Password.RequireUppercase'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequireUppercase', value)"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.Password.RequireDigit'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.Password.RequireDigit'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.Password.RequireDigit', value)"
/>
</el-form-item>
</el-col>
<el-form-item :label="globalSetting['Abp.Identity.Lockout.AllowedForNewUsers'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.Lockout.AllowedForNewUsers'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.Lockout.AllowedForNewUsers', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Identity.Lockout.MaxFailedAccessAttempts'].displayName">
<el-input
v-model="globalSetting['Abp.Identity.Lockout.MaxFailedAccessAttempts'].value"
:placeholder="globalSetting['Abp.Identity.Lockout.MaxFailedAccessAttempts'].description"
type="number"
@input="(value) => handleSettingValueChanged('Abp.Identity.Lockout.MaxFailedAccessAttempts', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Identity.Lockout.LockoutDuration'].displayName">
<el-input
v-model="globalSetting['Abp.Identity.Lockout.LockoutDuration'].value"
:placeholder="globalSetting['Abp.Identity.Lockout.LockoutDuration'].description"
type="number"
@input="(value) => handleSettingValueChanged('Abp.Identity.Lockout.LockoutDuration', value)"
/>
</el-form-item>
</el-row>
</el-tab-pane>
<el-tab-pane
v-if="allowAccountSetting"
:label="$t('settings.userAccount')"
>
<el-row>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.SignIn.RequireConfirmedEmail'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.SignIn.RequireConfirmedEmail'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.SignIn.RequireConfirmedEmail', value)"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.SignIn.EnablePhoneNumberConfirmation'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.SignIn.EnablePhoneNumberConfirmation'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.SignIn.EnablePhoneNumberConfirmation', value)"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.SignIn.RequireConfirmedPhoneNumber'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.SignIn.RequireConfirmedPhoneNumber'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.SignIn.RequireConfirmedPhoneNumber', value)"
/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Identity.User.IsUserNameUpdateEnabled'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.User.IsUserNameUpdateEnabled'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.User.IsUserNameUpdateEnabled', value)"
/>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="globalSetting['Abp.Identity.User.IsEmailUpdateEnabled'].displayName">
<el-switch
v-model="globalSetting['Abp.Identity.User.IsEmailUpdateEnabled'].value"
@input="(value) => handleSettingValueChanged('Abp.Identity.User.IsEmailUpdateEnabled', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Account.SmsRegisterTemplateCode'].displayName">
<el-input
v-model="globalSetting['Abp.Account.SmsRegisterTemplateCode'].value"
:placeholder="globalSetting['Abp.Account.SmsRegisterTemplateCode'].description"
@input="(value) => handleSettingValueChanged('Abp.Account.SmsRegisterTemplateCode', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Account.SmsSigninTemplateCode'].displayName">
<el-input
v-model="globalSetting['Abp.Account.SmsSigninTemplateCode'].value"
:placeholder="globalSetting['Abp.Account.SmsSigninTemplateCode'].description"
@input="(value) => handleSettingValueChanged('Abp.Account.SmsSigninTemplateCode', value)"
/>
</el-form-item>
<el-form-item :label="globalSetting['Abp.Account.PhoneVerifyCodeExpiration'].displayName">
<el-input
v-model="globalSetting['Abp.Account.PhoneVerifyCodeExpiration'].value"
:placeholder="globalSetting['Abp.Account.PhoneVerifyCodeExpiration'].description"
@input="(value) => handleSettingValueChanged('Abp.Account.PhoneVerifyCodeExpiration', value)"
/>
</el-form-item>
<el-row>
<el-col :span="8">
<el-form-item :label="globalSetting['Abp.Account.IsSelfRegistrationEnabled'].displayName">
<el-switch
v-model="globalSetting['Abp.Account.IsSelfRegistrationEnabled'].value"
@input="(value) => handleSettingValueChanged('Abp.Account.IsSelfRegistrationEnabled', value)"
/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="globalSetting['Abp.Account.EnableLocalLogin'].displayName">
<el-switch
v-model="globalSetting['Abp.Account.EnableLocalLogin'].value"
@input="(value) => handleSettingValueChanged('Abp.Account.EnableLocalLogin', value)"
/>
</el-form-item>
</el-col>
</el-row>
</el-tab-pane>
</el-tabs>
<el-form-item>
<el-button
type="primary"
style="width:200px;margin:inherit;"
@click="onSaveGlobalSetting"
>
{{ $t('global.confirm') }}
</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import SettingService, { Setting, SettingUpdate, SettingsUpdate } from '@/api/settings'
const booleanStrings = ['True', 'true', 'False', 'false']
@Component({
name: 'GlobalSettingEditForm'
})
export default class extends Vue {
private globalSettingLoaded = false
private globalSetting: {[key: string]: Setting} = {}
private globalSettingChangeKeys = new Array<string>()
get allowIdentitySetting() {
if (this.globalSetting['Abp.Identity.Password.RequiredLength']) {
return true
}
return false
}
get allowAccountSetting() {
if (this.globalSetting['Abp.Account.EnableLocalLogin']) {
return true
}
return false
}
mounted() {
this.handleGetGlobalSettings()
}
private handleSettingValueChanged(key: string, value: any) {
if (!this.globalSettingChangeKeys.includes(key)) {
this.globalSettingChangeKeys.push(key)
}
this.$set(this.globalSetting[key], 'value', value)
this.$forceUpdate()
}
private handleGetGlobalSettings() {
SettingService.getSettings('G', '').then(settings => {
settings.items.forEach(setting => {
if (setting.value) {
const value = setting.value.toLowerCase()
if (booleanStrings.includes(value)) {
setting.value = value === 'true'
}
} else {
const defaultValue = setting.defaultValue.toLowerCase()
if (booleanStrings.includes(defaultValue)) {
setting.value = defaultValue === 'true'
}
}
this.globalSetting[setting.name] = setting
})
this.globalSettingLoaded = true
})
}
private onSaveGlobalSetting() {
const updateSettings = new SettingsUpdate()
this.globalSettingChangeKeys.forEach(key => {
const updateSetting = new SettingUpdate()
updateSetting.name = key
updateSetting.value = this.globalSetting[key].value
updateSettings.settings.push(updateSetting)
})
if (updateSettings.settings.length > 0) {
SettingService.setSettings('G', '', updateSettings).then(() => {
this.$message.success(this.$t('AbpSettingManagement.SuccessfullySaved').toString())
})
}
}
}
</script>

42
vueJs/src/views/admin/settings/index.vue

@ -1,53 +1,37 @@
<template> <template>
<el-tabs <el-tabs
tab-position="left" tab-position="left"
style="height: 200px;"
> >
<el-tab-pane <el-tab-pane
label="系统配置" :label="$t('settings.globalSetting')"
> >
系统配置 <GlobalSettingEditForm />
</el-tab-pane> </el-tab-pane>
<el-tab-pane <el-tab-pane
label="租户配置" :label="$t('settings.tenantSetting')"
> >
租户配置 {{ $t('settings.tenantSetting') }}
</el-tab-pane> </el-tab-pane>
<el-tab-pane <el-tab-pane
label="用户配置" :label="$t('settings.userSetting')"
> >
用户配置 {{ $t('settings.userSetting') }}
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</template> </template>
<script lang="ts"> <script lang="ts">
import SettingService, { Setting } from '@/api/settings'
import { Component, Vue } from 'vue-property-decorator' import { Component, Vue } from 'vue-property-decorator'
@Component({ import GlobalSettingEditForm from './components/GlobalSettingEditForm.vue'
name: 'Settings'
})
export default class extends Vue {
private settings: Setting[]
constructor() {
super()
this.settings = new Array<Setting>()
}
mounted() { @Component({
this.handleGetSettings() name: 'Settings',
} components: {
GlobalSettingEditForm
private handleGetSettings() {
SettingService.getSettings('G', '').then(settings => {
this.settings = settings.items
console.log(this.settings)
})
} }
} })
export default class extends Vue {}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

Loading…
Cancel
Save