Skip to content

Commit dacbe4c

Browse files
authored
feat(Region): add SelectProvince component (#608)
* refactor: 调整暗黑主题字体颜色 * refactor: 移除可为空标记 * refactor: 符合命名规范 * refactor: 精简代码 * refactor: 优化代码 * feat: 增加省选择组件 * refactor: 移动 InputId 到基类 * chore: bump version 9.0.3
1 parent db93fc3 commit dacbe4c

10 files changed

Lines changed: 186 additions & 49 deletions

src/components/BootstrapBlazor.Region/BootstrapBlazor.Region.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.0.2</Version>
4+
<Version>9.0.3</Version>
55
</PropertyGroup>
66

77
<PropertyGroup>

src/components/BootstrapBlazor.Region/Components/SelectCity.razor.cs

Lines changed: 14 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,6 @@ public partial class SelectCity
1515
[Parameter]
1616
public bool IsMultiple { get; set; }
1717

18-
private string? InputId => $"{Id}_input";
19-
2018
private string? ClassString => CssBuilder.Default("select bb-city")
2119
.AddClass("disabled", IsDisabled)
2220
.AddClassFromAttributes(AdditionalAttributes)
@@ -42,30 +40,22 @@ private async Task OnClearValue()
4240

4341
private void OnSelectProvince(string province)
4442
{
45-
if (IsMultiple)
43+
if (!IsMultiple)
4644
{
47-
HashSet<string> cities;
48-
if (province == "直辖市")
49-
{
50-
cities = Municipalities;
51-
}
52-
else if (province == "特别行政区")
53-
{
54-
cities = SpecialAdministrativeRegions;
55-
}
56-
else
57-
{
58-
cities = GetCities(province);
59-
}
60-
foreach (var city in cities)
61-
{
62-
if (!_values.Remove(city))
63-
{
64-
_values.Add(city);
65-
}
66-
}
67-
CurrentValue = string.Join(",", _values);
45+
return;
46+
}
47+
48+
HashSet<string> cities = province switch
49+
{
50+
"直辖市" => Municipalities,
51+
"特别行政区" => SpecialAdministrativeRegions,
52+
_ => GetCities(province)
53+
};
54+
foreach (var city in cities.Where(city => !_values.Remove(city)))
55+
{
56+
_values.Add(city);
6857
}
58+
CurrentValue = string.Join(",", _values);
6959
}
7060

7161
private void OnSelectCity(string item)

src/components/BootstrapBlazor.Region/Components/SelectCity.razor.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
}
5353

5454
[data-bs-theme="dark"] .dropdown-menu {
55-
--bb-region-body-color: #ddd;
55+
--bb-region-body-color: #c0c4cc;
5656
--bb-region-body-hover-color: #fff;
5757
--bb-region-body-active-color: #fff;
5858
--bb-region-body-hover-bg-color: #495057;
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
@namespace BootstrapBlazor.Components
2+
@inherits SelectRegionBase
3+
@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.Region/Components/SelectRegion.razor.js")]
4+
5+
@if (IsShowLabel)
6+
{
7+
<BootstrapLabel required="@Required" for="@InputId" ShowLabelTooltip="ShowLabelTooltip" Value="@DisplayText" />
8+
}
9+
<div @attributes="AdditionalAttributes" id="@Id" class="@ClassString">
10+
<div class="dropdown-toggle" data-bs-toggle="bb.dropdown" data-bs-placement="@PlacementString" data-bs-offset="@OffsetString" data-bs-custom-class="@CustomClassString">
11+
<input type="text" id="@InputId" disabled="@Disabled" readonly placeholder="@PlaceHolder" class="@InputClassString" value="@CurrentValueAsString" />
12+
<span class="@AppendClassString"><i class="@DropdownIcon"></i></span>
13+
</div>
14+
@if (!IsDisabled)
15+
{
16+
<span class="@ClearClassString" @onclick="OnClearValue"><i class="@ClearIcon"></i></span>
17+
}
18+
<div class="dropdown-menu bb-region-body">
19+
<ul>
20+
@foreach (var item in GetProvinces())
21+
{
22+
<li class="@GetActiveClass(item)" @onclick="() => OnSelectProvince(item)">@item</li>
23+
}
24+
</ul>
25+
</div>
26+
</div>
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Copyright (c) BootstrapBlazor & Argo Zhang (argo@live.ca). All rights reserved.
2+
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
3+
// Website: https://www.blazor.zone or https://argozhang.github.io/
4+
5+
namespace BootstrapBlazor.Components;
6+
7+
/// <summary>
8+
/// SelectProvince 组件
9+
/// </summary>
10+
public partial class SelectProvince
11+
{
12+
/// <summary>
13+
/// 获得/设置 是否可多选 默认 false 单选
14+
/// </summary>
15+
[Parameter]
16+
public bool IsMultiple { get; set; }
17+
18+
private string? ClassString => CssBuilder.Default("select bb-province")
19+
.AddClass("disabled", IsDisabled)
20+
.AddClassFromAttributes(AdditionalAttributes)
21+
.Build();
22+
23+
private readonly HashSet<string> _values = [];
24+
25+
private string? GetActiveClass(string item) => _values.Contains(item) || CurrentValue == item ? "active" : null;
26+
27+
private async Task OnClearValue()
28+
{
29+
if (IsMultiple)
30+
{
31+
_values.Clear();
32+
}
33+
CurrentValue = "";
34+
35+
if (OnClearAsync != null)
36+
{
37+
await OnClearAsync();
38+
}
39+
}
40+
41+
private void OnSelectProvince(string item)
42+
{
43+
if (IsMultiple)
44+
{
45+
if (!_values.Remove(item))
46+
{
47+
_values.Add(item);
48+
}
49+
CurrentValue = string.Join(",", _values);
50+
}
51+
else
52+
{
53+
CurrentValue = item;
54+
}
55+
}
56+
57+
private HashSet<string> GetProvinces() => RegionService.GetProvinces();
58+
}
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
.bb-province {
2+
position: relative;
3+
}
4+
5+
.bb-province:not(.disabled):hover .form-select-append {
6+
display: none;
7+
}
8+
9+
.dropdown-menu {
10+
--bs-dropdown-padding-y: 0;
11+
--bb-region-body-color: #495057;
12+
--bb-region-body-hover-bg-color: #e9ecef;
13+
--bb-region-body-active-bg-color: #dee2e6;
14+
--bb-region-body-hover-color: #000;
15+
--bb-region-body-active-color: #000;
16+
--bb-region-body-width: 400px;
17+
--bb-region-body-padding: .5rem;
18+
--bb-region-body-item-padding: 3px 12px;
19+
--bb-region-body-gap: 5px;
20+
}
21+
22+
.dropdown-menu ul {
23+
margin: 0;
24+
padding: 0;
25+
}
26+
27+
.dropdown-menu li {
28+
list-style: none;
29+
transition: background-color .3s linear, color .3s linear;
30+
}
31+
32+
[data-bs-theme="dark"] .dropdown-menu {
33+
--bb-region-body-color: #c0c4cc;
34+
--bb-region-body-hover-color: #fff;
35+
--bb-region-body-active-color: #fff;
36+
--bb-region-body-hover-bg-color: #495057;
37+
--bb-region-body-active-bg-color: #6c757d;
38+
}
39+
40+
.bb-region-body {
41+
padding: var(--bb-region-body-padding);
42+
width: var(--bb-region-body-width);
43+
}
44+
45+
.bb-region-body ul {
46+
display: flex;
47+
flex-wrap: wrap;
48+
gap: var(--bb-region-body-gap);
49+
}
50+
51+
.bb-region-body ul li {
52+
padding: var(--bb-region-body-item-padding);
53+
border-radius: var(--bs-border-radius);
54+
color: var(--bb-region-body-color);
55+
cursor: pointer;
56+
}
57+
58+
.bb-region-body ul li:hover {
59+
background-color: var(--bb-region-body-hover-bg-color);
60+
color: var(--bb-region-body-hover-color);
61+
}
62+
63+
.bb-region-body ul li.active {
64+
background-color: var(--bb-region-body-active-bg-color);
65+
color: var(--bb-region-body-active-color);
66+
}

src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.cs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,6 @@ namespace BootstrapBlazor.Components;
99
/// </summary>
1010
public partial class SelectRegion
1111
{
12-
private string? InputId => $"{Id}_input";
13-
1412
private string? ClassString => CssBuilder.Default("select bb-region")
1513
.AddClass("disabled", IsDisabled)
1614
.AddClassFromAttributes(AdditionalAttributes)

src/components/BootstrapBlazor.Region/Components/SelectRegion.razor.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
[data-bs-theme="dark"] .dropdown-menu {
3636
--bb-region-header-hover-bg-color: #495057;
3737
--bb-region-header-active-bg-color: #6c757d;
38-
--bb-region-body-color: #ddd;
38+
--bb-region-body-color: #c0c4cc;
3939
--bb-region-body-hover-color: #fff;
4040
--bb-region-body-active-color: #fff;
4141
--bb-region-body-hover-bg-color: #495057;

src/components/BootstrapBlazor.Region/Components/SelectRegionBase.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ public abstract class SelectRegionBase : PopoverSelectBase<string>
8383
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
8484
.Build();
8585

86+
/// <summary>
87+
/// 获得 选择框组件 Id
88+
/// </summary>
89+
protected string InputId => $"{Id}_input";
90+
8691
/// <summary>
8792
/// <inheritdoc/>
8893
/// </summary>

src/components/BootstrapBlazor.Region/Services/DefaultRegionService.cs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,35 @@ namespace BootstrapBlazor.Components;
1010

1111
class DefaultRegionService : IRegionService
1212
{
13-
private static readonly ConcurrentDictionary<string, HashSet<string>> _citiesCache = new();
14-
private static readonly ConcurrentDictionary<string, HashSet<CountyItem>> _countiesCache = new();
15-
private static readonly ConcurrentDictionary<string, HashSet<string>> _detailCache = new();
13+
private static readonly ConcurrentDictionary<string, HashSet<string>> CitiesCache = new();
14+
private static readonly ConcurrentDictionary<string, HashSet<CountyItem>> CountiesCache = new();
15+
private static readonly ConcurrentDictionary<string, HashSet<string>> DetailCache = new();
1616

17-
private static bool _initialized = false;
17+
private static bool _initialized;
1818

1919
#if NET9_0_OR_GREATER
20-
private static readonly Lock _lock = new();
20+
private static readonly Lock Lock = new();
2121
#else
22-
private static readonly object _lock = new();
23-
#endif
24-
25-
#if NET9_0_OR_GREATER
26-
private static readonly Lock _lockDetail = new();
27-
#else
28-
private static readonly object _lockDetail = new();
22+
private static readonly object Lock = new();
2923
#endif
3024

3125
public HashSet<string> GetProvinces() => Provinces;
3226

3327
public HashSet<string> GetCities(string province)
3428
{
3529
LoadCityData();
36-
return _citiesCache.TryGetValue(province, out var cities) ? cities : [];
30+
return CitiesCache.TryGetValue(province, out var cities) ? cities : [];
3731
}
3832

3933
public HashSet<CountyItem> GetCounties(string city)
4034
{
4135
LoadCityData();
42-
return _countiesCache.TryGetValue(city, out var counties) ? counties : [];
36+
return CountiesCache.TryGetValue(city, out var counties) ? counties : [];
4337
}
4438

4539
public HashSet<string> GetDetails(string countyCode)
4640
{
47-
return _detailCache.GetOrAdd(countyCode, LoadDetailData);
41+
return DetailCache.GetOrAdd(countyCode, LoadDetailData);
4842
}
4943

5044
private static HashSet<string> LoadDetailData(string countyCode)
@@ -71,7 +65,7 @@ private static void LoadCityData()
7165
{
7266
if (!_initialized)
7367
{
74-
lock (_lock)
68+
lock (Lock)
7569
{
7670
if (!_initialized)
7771
{
@@ -105,7 +99,7 @@ private static void LoadDataCore(Stream data)
10599

106100
var mem = content.AsMemory();
107101
var code = Trim(mem[0..index].ToString());
108-
var value = Trim(mem[(index + 1)..(mem.Length - 1)].ToString());
102+
var value = Trim(mem[(index + 1)..^1].ToString());
109103

110104
if (code[2..] == "0000")
111105
{
@@ -117,7 +111,7 @@ private static void LoadDataCore(Stream data)
117111
cities.Add(value);
118112
}
119113

120-
_citiesCache.TryAdd(value, cities);
114+
CitiesCache.TryAdd(value, cities);
121115
counties = null;
122116
continue;
123117
}
@@ -126,14 +120,14 @@ private static void LoadDataCore(Stream data)
126120
{
127121
cities.Add(value);
128122
counties = [];
129-
_countiesCache.TryAdd(value, counties);
123+
CountiesCache.TryAdd(value, counties);
130124
continue;
131125
}
132126

133127
if (counties == null)
134128
{
135129
counties = [];
136-
_countiesCache.TryAdd(city, counties);
130+
CountiesCache.TryAdd(city, counties);
137131
}
138132

139133
counties.Add(new CountyItem() { Name = value, Code = code });

0 commit comments

Comments
 (0)