diff --git a/src/components/BootstrapBlazor.Region/BootstrapBlazor.Region.csproj b/src/components/BootstrapBlazor.Region/BootstrapBlazor.Region.csproj index f2a99d7d..629c4484 100644 --- a/src/components/BootstrapBlazor.Region/BootstrapBlazor.Region.csproj +++ b/src/components/BootstrapBlazor.Region/BootstrapBlazor.Region.csproj @@ -1,7 +1,7 @@  - 9.0.2 + 9.0.3 diff --git a/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.cs b/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.cs index c4287977..bd8f66ae 100644 --- a/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.cs +++ b/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.cs @@ -15,8 +15,6 @@ public partial class SelectCity [Parameter] public bool IsMultiple { get; set; } - private string? InputId => $"{Id}_input"; - private string? ClassString => CssBuilder.Default("select bb-city") .AddClass("disabled", IsDisabled) .AddClassFromAttributes(AdditionalAttributes) @@ -42,30 +40,22 @@ private async Task OnClearValue() private void OnSelectProvince(string province) { - if (IsMultiple) + if (!IsMultiple) { - HashSet cities; - if (province == "直辖市") - { - cities = Municipalities; - } - else if (province == "特别行政区") - { - cities = SpecialAdministrativeRegions; - } - else - { - cities = GetCities(province); - } - foreach (var city in cities) - { - if (!_values.Remove(city)) - { - _values.Add(city); - } - } - CurrentValue = string.Join(",", _values); + return; + } + + HashSet cities = province switch + { + "直辖市" => Municipalities, + "特别行政区" => SpecialAdministrativeRegions, + _ => GetCities(province) + }; + foreach (var city in cities.Where(city => !_values.Remove(city))) + { + _values.Add(city); } + CurrentValue = string.Join(",", _values); } private void OnSelectCity(string item) diff --git a/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.css b/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.css index 37e1a5e6..a2a6b923 100644 --- a/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.css +++ b/src/components/BootstrapBlazor.Region/Components/SelectCity.razor.css @@ -52,7 +52,7 @@ } [data-bs-theme="dark"] .dropdown-menu { - --bb-region-body-color: #ddd; + --bb-region-body-color: #c0c4cc; --bb-region-body-hover-color: #fff; --bb-region-body-active-color: #fff; --bb-region-body-hover-bg-color: #495057; diff --git a/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor new file mode 100644 index 00000000..11434fd0 --- /dev/null +++ b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor @@ -0,0 +1,26 @@ +@namespace BootstrapBlazor.Components +@inherits SelectRegionBase +@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.Region/Components/SelectRegion.razor.js")] + +@if (IsShowLabel) +{ + +} +
+ + @if (!IsDisabled) + { + + } + +
diff --git a/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.cs b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.cs new file mode 100644 index 00000000..e7b075bd --- /dev/null +++ b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.cs @@ -0,0 +1,58 @@ +// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Website: https://www.blazor.zone or https://argozhang.github.io/ + +namespace BootstrapBlazor.Components; + +/// +/// SelectProvince 组件 +/// +public partial class SelectProvince +{ + /// + /// 获得/设置 是否可多选 默认 false 单选 + /// + [Parameter] + public bool IsMultiple { get; set; } + + private string? ClassString => CssBuilder.Default("select bb-province") + .AddClass("disabled", IsDisabled) + .AddClassFromAttributes(AdditionalAttributes) + .Build(); + + private readonly HashSet _values = []; + + private string? GetActiveClass(string item) => _values.Contains(item) || CurrentValue == item ? "active" : null; + + private async Task OnClearValue() + { + if (IsMultiple) + { + _values.Clear(); + } + CurrentValue = ""; + + if (OnClearAsync != null) + { + await OnClearAsync(); + } + } + + private void OnSelectProvince(string item) + { + if (IsMultiple) + { + if (!_values.Remove(item)) + { + _values.Add(item); + } + CurrentValue = string.Join(",", _values); + } + else + { + CurrentValue = item; + } + } + + private HashSet GetProvinces() => RegionService.GetProvinces(); +} diff --git a/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.css b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.css new file mode 100644 index 00000000..267f0e72 --- /dev/null +++ b/src/components/BootstrapBlazor.Region/Components/SelectProvince.razor.css @@ -0,0 +1,66 @@ +.bb-province { + position: relative; +} + + .bb-province:not(.disabled):hover .form-select-append { + display: none; + } + +.dropdown-menu { + --bs-dropdown-padding-y: 0; + --bb-region-body-color: #495057; + --bb-region-body-hover-bg-color: #e9ecef; + --bb-region-body-active-bg-color: #dee2e6; + --bb-region-body-hover-color: #000; + --bb-region-body-active-color: #000; + --bb-region-body-width: 400px; + --bb-region-body-padding: .5rem; + --bb-region-body-item-padding: 3px 12px; + --bb-region-body-gap: 5px; +} + + .dropdown-menu ul { + margin: 0; + padding: 0; + } + + .dropdown-menu li { + list-style: none; + transition: background-color .3s linear, color .3s linear; + } + +[data-bs-theme="dark"] .dropdown-menu { + --bb-region-body-color: #c0c4cc; + --bb-region-body-hover-color: #fff; + --bb-region-body-active-color: #fff; + --bb-region-body-hover-bg-color: #495057; + --bb-region-body-active-bg-color: #6c757d; +} + +.bb-region-body { + padding: var(--bb-region-body-padding); + width: var(--bb-region-body-width); +} + + .bb-region-body ul { + display: flex; + flex-wrap: wrap; + gap: var(--bb-region-body-gap); + } + + .bb-region-body ul li { + padding: var(--bb-region-body-item-padding); + border-radius: var(--bs-border-radius); + color: var(--bb-region-body-color); + cursor: pointer; + } + + .bb-region-body ul li:hover { + background-color: var(--bb-region-body-hover-bg-color); + color: var(--bb-region-body-hover-color); + } + + .bb-region-body ul li.active { + background-color: var(--bb-region-body-active-bg-color); + color: var(--bb-region-body-active-color); + } diff --git a/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.cs b/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.cs index de778f56..d7fd97d3 100644 --- a/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.cs +++ b/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.cs @@ -9,8 +9,6 @@ namespace BootstrapBlazor.Components; /// public partial class SelectRegion { - private string? InputId => $"{Id}_input"; - private string? ClassString => CssBuilder.Default("select bb-region") .AddClass("disabled", IsDisabled) .AddClassFromAttributes(AdditionalAttributes) diff --git a/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.css b/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.css index e19b5261..5b7aaa74 100644 --- a/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.css +++ b/src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.css @@ -35,7 +35,7 @@ [data-bs-theme="dark"] .dropdown-menu { --bb-region-header-hover-bg-color: #495057; --bb-region-header-active-bg-color: #6c757d; - --bb-region-body-color: #ddd; + --bb-region-body-color: #c0c4cc; --bb-region-body-hover-color: #fff; --bb-region-body-active-color: #fff; --bb-region-body-hover-bg-color: #495057; diff --git a/src/components/BootstrapBlazor.Region/Components/SelectRegionBase.cs b/src/components/BootstrapBlazor.Region/Components/SelectRegionBase.cs index 3aa2f320..c2a05f92 100644 --- a/src/components/BootstrapBlazor.Region/Components/SelectRegionBase.cs +++ b/src/components/BootstrapBlazor.Region/Components/SelectRegionBase.cs @@ -83,6 +83,11 @@ public abstract class SelectRegionBase : PopoverSelectBase .AddClass($"text-danger", IsValid.HasValue && !IsValid.Value) .Build(); + /// + /// 获得 选择框组件 Id + /// + protected string InputId => $"{Id}_input"; + /// /// /// diff --git a/src/components/BootstrapBlazor.Region/Services/DefaultRegionService.cs b/src/components/BootstrapBlazor.Region/Services/DefaultRegionService.cs index 66a2acaa..bcd58ec3 100644 --- a/src/components/BootstrapBlazor.Region/Services/DefaultRegionService.cs +++ b/src/components/BootstrapBlazor.Region/Services/DefaultRegionService.cs @@ -10,22 +10,16 @@ namespace BootstrapBlazor.Components; class DefaultRegionService : IRegionService { - private static readonly ConcurrentDictionary> _citiesCache = new(); - private static readonly ConcurrentDictionary> _countiesCache = new(); - private static readonly ConcurrentDictionary> _detailCache = new(); + private static readonly ConcurrentDictionary> CitiesCache = new(); + private static readonly ConcurrentDictionary> CountiesCache = new(); + private static readonly ConcurrentDictionary> DetailCache = new(); - private static bool _initialized = false; + private static bool _initialized; #if NET9_0_OR_GREATER - private static readonly Lock _lock = new(); + private static readonly Lock Lock = new(); #else - private static readonly object _lock = new(); -#endif - -#if NET9_0_OR_GREATER - private static readonly Lock _lockDetail = new(); -#else - private static readonly object _lockDetail = new(); + private static readonly object Lock = new(); #endif public HashSet GetProvinces() => Provinces; @@ -33,18 +27,18 @@ class DefaultRegionService : IRegionService public HashSet GetCities(string province) { LoadCityData(); - return _citiesCache.TryGetValue(province, out var cities) ? cities : []; + return CitiesCache.TryGetValue(province, out var cities) ? cities : []; } public HashSet GetCounties(string city) { LoadCityData(); - return _countiesCache.TryGetValue(city, out var counties) ? counties : []; + return CountiesCache.TryGetValue(city, out var counties) ? counties : []; } public HashSet GetDetails(string countyCode) { - return _detailCache.GetOrAdd(countyCode, LoadDetailData); + return DetailCache.GetOrAdd(countyCode, LoadDetailData); } private static HashSet LoadDetailData(string countyCode) @@ -71,7 +65,7 @@ private static void LoadCityData() { if (!_initialized) { - lock (_lock) + lock (Lock) { if (!_initialized) { @@ -105,7 +99,7 @@ private static void LoadDataCore(Stream data) var mem = content.AsMemory(); var code = Trim(mem[0..index].ToString()); - var value = Trim(mem[(index + 1)..(mem.Length - 1)].ToString()); + var value = Trim(mem[(index + 1)..^1].ToString()); if (code[2..] == "0000") { @@ -117,7 +111,7 @@ private static void LoadDataCore(Stream data) cities.Add(value); } - _citiesCache.TryAdd(value, cities); + CitiesCache.TryAdd(value, cities); counties = null; continue; } @@ -126,14 +120,14 @@ private static void LoadDataCore(Stream data) { cities.Add(value); counties = []; - _countiesCache.TryAdd(value, counties); + CountiesCache.TryAdd(value, counties); continue; } if (counties == null) { counties = []; - _countiesCache.TryAdd(city, counties); + CountiesCache.TryAdd(city, counties); } counties.Add(new CountyItem() { Name = value, Code = code });