From 1d1e6a80b9db06c9421292233ffc4a3948cb2ba2 Mon Sep 17 00:00:00 2001 From: colin Date: Tue, 10 Mar 2026 16:34:04 +0800 Subject: [PATCH] feat: TimeZoneSettings Support - Add TimeZoneSettings Interface - Use IanaTimezones for time zone settings --- .../SettingManagement/SettingAppService.cs | 7 +- .../TimeZoneSettingsAppService.cs | 67 +++++++++++++++++++ .../TimeZoneSettingsController.cs | 42 ++++++++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/TimeZoneSettingsAppService.cs create mode 100644 aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN/Abp/SettingManagement/TimeZoneSettingsController.cs diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs index 7a40bc1ac..9ebac6603 100644 --- a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs @@ -145,7 +145,12 @@ public class SettingAppService : ApplicationService, ISettingAppService, ISettin providerName) ?.AddOptions(LocalizationOptions.Languages.Select(l => new OptionDto(l.DisplayName, l.CultureName))); // 时区 - var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetWindowsTimezones()); + var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetIanaTimezones()); + timezones.Insert(0, new NameValue + { + Name = L["DefaultTimeZone"], + Value = "Unspecified" + }); var timingSetting = sysSettingGroup.AddSetting(L["DisplayName:System.Timing"], L["Description:System.Timing"]); timingSetting.AddDetail( await SettingDefinitionManager.GetAsync(TimingSettingNames.TimeZone), diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/TimeZoneSettingsAppService.cs b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/TimeZoneSettingsAppService.cs new file mode 100644 index 000000000..c2ed056b5 --- /dev/null +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/TimeZoneSettingsAppService.cs @@ -0,0 +1,67 @@ +using Microsoft.AspNetCore.Authorization; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.MultiTenancy; +using Volo.Abp.SettingManagement; +using Volo.Abp.Timing; + +namespace LINGYUN.Abp.SettingManagement; + +[Authorize(Volo.Abp.SettingManagement.SettingManagementPermissions.TimeZone)] +public class TimeZoneSettingsAppService : SettingManagementAppServiceBase, ITimeZoneSettingsAppService +{ + protected ISettingManager SettingManager { get; } + protected ITimezoneProvider TimezoneProvider { get; } + + private const string UnspecifiedTimeZone = "Unspecified"; + + public TimeZoneSettingsAppService(ISettingManager settingManager, ITimezoneProvider timezoneProvider) + { + SettingManager = settingManager; + TimezoneProvider = timezoneProvider; + } + + public virtual async Task GetAsync() + { + var timezone = CurrentTenant.GetMultiTenancySide() == MultiTenancySides.Host + ? await SettingManager.GetOrNullGlobalAsync(TimingSettingNames.TimeZone) + : await SettingManager.GetOrNullForCurrentTenantAsync(TimingSettingNames.TimeZone); + + if (timezone.IsNullOrWhiteSpace()) + { + timezone = UnspecifiedTimeZone; + } + + return timezone; + } + + public virtual Task> GetTimezonesAsync() + { + var timezones = TimeZoneHelper.GetTimezones(TimezoneProvider.GetIanaTimezones()); + timezones.Insert(0, new NameValue + { + Name = L["DefaultTimeZone"], + Value = UnspecifiedTimeZone + }); + return Task.FromResult(timezones); + } + + public virtual async Task UpdateAsync(string timezone) + { + if (timezone.Equals(UnspecifiedTimeZone, StringComparison.OrdinalIgnoreCase)) + { + timezone = null; + } + + if (CurrentTenant.GetMultiTenancySide() == MultiTenancySides.Host) + { + await SettingManager.SetGlobalAsync(TimingSettingNames.TimeZone, timezone); + } + else + { + await SettingManager.SetForCurrentTenantAsync(TimingSettingNames.TimeZone, timezone); + } + } +} diff --git a/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN/Abp/SettingManagement/TimeZoneSettingsController.cs b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN/Abp/SettingManagement/TimeZoneSettingsController.cs new file mode 100644 index 000000000..724563df9 --- /dev/null +++ b/aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.HttpApi/LINGYUN/Abp/SettingManagement/TimeZoneSettingsController.cs @@ -0,0 +1,42 @@ +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using System.Collections.Generic; +using System.Threading.Tasks; +using Volo.Abp; +using Volo.Abp.AspNetCore.Mvc; +using Volo.Abp.SettingManagement; + +namespace LINGYUN.Abp.SettingManagement; + +[RemoteService(Name = AbpSettingManagementRemoteServiceConsts.RemoteServiceName)] +[Area(AbpSettingManagementRemoteServiceConsts.ModuleName)] +[Route("api/setting-management/timezone")] +[Authorize(Volo.Abp.SettingManagement.SettingManagementPermissions.TimeZone)] +public class TimeZoneSettingsController : AbpControllerBase, ITimeZoneSettingsAppService +{ + private readonly ITimeZoneSettingsAppService _service; + + public TimeZoneSettingsController(ITimeZoneSettingsAppService service) + { + _service = service; + } + + [HttpGet] + public virtual Task GetAsync() + { + return _service.GetAsync(); + } + + [HttpGet] + [Route("timezones")] + public virtual Task> GetTimezonesAsync() + { + return _service.GetTimezonesAsync(); + } + + [HttpPost] + public virtual Task UpdateAsync(string timezone) + { + return _service.UpdateAsync(timezone); + } +}