Skip to content

Commit 086e832

Browse files
authored
feat(SelectCity): add SelectCity component (#602)
* refactor: 移除 JSObjectReference 初始化 * chore: 增加 SelectCity 组件 * refactor: 更新细节 * fix: 修复脚本错误 * feat: 实现城市排列 * feat: 增加选择逻辑 * refactor: 优化代码 * refactor: 更新样式 * chore: 增加全局命名空间 * refactor: 增加多选参数支持 * refactor: 增加清空逻辑 * feat: 增加表头按钮逻辑 * refactor: 更新样式 * feat: 更新样式 * refactor: 增加样式 * chore: bump version 9.0.1 * refactor: 移除赋值
1 parent 3d39e2c commit 086e832

8 files changed

Lines changed: 337 additions & 77 deletions

File tree

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.0</Version>
4+
<Version>9.0.1</Version>
55
</PropertyGroup>
66

77
<PropertyGroup>
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
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">
19+
@foreach (var item in GetProvinces())
20+
{
21+
<div class="bb-region-city-item">
22+
<div class="bb-region-city-title" @onclick="() => OnSelectProvince(item)">@item</div>
23+
<ul>
24+
@foreach (var city in GetCities(item))
25+
{
26+
<li class="@GetActiveClass(city)" @onclick="() => OnSelectCity(city)">@city</li>
27+
}
28+
</ul>
29+
</div>
30+
}
31+
</div>
32+
</div>
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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+
/// SelectCity 组件
9+
/// </summary>
10+
public partial class SelectCity
11+
{
12+
/// <summary>
13+
/// 获得/设置 是否可多选 默认 false 单选
14+
/// </summary>
15+
[Parameter]
16+
public bool IsMultiple { get; set; }
17+
18+
private string? InputId => $"{Id}_input";
19+
20+
private string? ClassString => CssBuilder.Default("select bb-city")
21+
.AddClass("disabled", IsDisabled)
22+
.AddClassFromAttributes(AdditionalAttributes)
23+
.Build();
24+
25+
private readonly HashSet<string> _values = [];
26+
27+
private string? GetActiveClass(string item) => _values.Contains(item) || CurrentValue == item ? "active" : null;
28+
29+
private async Task OnClearValue()
30+
{
31+
if (IsMultiple)
32+
{
33+
_values.Clear();
34+
}
35+
CurrentValue = "";
36+
37+
if (OnClearAsync != null)
38+
{
39+
await OnClearAsync();
40+
}
41+
}
42+
43+
private void OnSelectProvince(string province)
44+
{
45+
if (IsMultiple)
46+
{
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);
68+
}
69+
}
70+
71+
private void OnSelectCity(string item)
72+
{
73+
if (IsMultiple)
74+
{
75+
if (!_values.Remove(item))
76+
{
77+
_values.Add(item);
78+
}
79+
CurrentValue = string.Join(",", _values);
80+
}
81+
else
82+
{
83+
CurrentValue = item;
84+
}
85+
}
86+
87+
private static HashSet<string> GetProvinces()
88+
{
89+
return
90+
[
91+
"直辖市",
92+
"河北省",
93+
"山西省",
94+
"辽宁省",
95+
"吉林省",
96+
"黑龙江省",
97+
"江苏省",
98+
"浙江省",
99+
"安徽省",
100+
"福建省",
101+
"江西省",
102+
"山东省",
103+
"河南省",
104+
"湖北省",
105+
"湖南省",
106+
"广东省",
107+
"海南省",
108+
"四川省",
109+
"贵州省",
110+
"云南省",
111+
"陕西省",
112+
"甘肃省",
113+
"青海省",
114+
"内蒙古自治区",
115+
"广西壮族自治区",
116+
"西藏自治区",
117+
"宁夏回族自治区",
118+
"新疆维吾尔自治区",
119+
"台湾省",
120+
"特别行政区"
121+
];
122+
}
123+
124+
private static readonly HashSet<string> Municipalities = ["北京市", "天津市", "上海市", "重庆市"];
125+
126+
private static readonly HashSet<string> SpecialAdministrativeRegions = ["香港特别行政区", "澳门特别行政区"];
127+
128+
private HashSet<string> GetCities(string provinceName)
129+
{
130+
if (provinceName == "直辖市")
131+
{
132+
return Municipalities;
133+
}
134+
135+
if (provinceName == "特别行政区")
136+
{
137+
return SpecialAdministrativeRegions;
138+
}
139+
140+
return RegionService.GetCities(provinceName);
141+
}
142+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
.bb-city {
2+
position: relative;
3+
}
4+
5+
.bb-city:not(.disabled):hover .form-select-append {
6+
display: none;
7+
}
8+
9+
.dropdown-menu {
10+
--bs-dropdown-padding-y: .5rem;
11+
--bs-dropdown-padding-x: .5rem;
12+
max-width: 400px;
13+
max-height: 400px;
14+
overflow-y: auto;
15+
}
16+
17+
.dropdown-menu ul {
18+
margin: 0;
19+
padding: 0;
20+
display: flex;
21+
flex-wrap: wrap;
22+
gap: 5px;
23+
}
24+
25+
.dropdown-menu li {
26+
list-style: none;
27+
transition: background-color .3s linear, color .3s linear;
28+
cursor: pointer;
29+
padding: 3px 12px;
30+
border-radius: var(--bs-border-radius);
31+
color: #777;
32+
}
33+
34+
.dropdown-menu li:hover {
35+
background-color: #e9ecef;
36+
color: #000;
37+
}
38+
39+
.dropdown-menu li.active {
40+
background-color: #e3e3e3;
41+
color: #000;
42+
}
43+
44+
.bb-region-city-item:not(:last-child) {
45+
margin-bottom: 3px;
46+
padding-bottom: 3px;
47+
border-bottom: 1px solid var(--bs-border-color);
48+
}
49+
50+
.bb-region-city-title {
51+
padding: 3px 12px;
52+
color: #000;
53+
font-weight: bold;
54+
cursor: pointer;
55+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
@namespace BootstrapBlazor.Components
2-
@inherits PopoverSelectBase<string>
2+
@inherits SelectRegionBase
33
@attribute [JSModuleAutoLoader("./_content/BootstrapBlazor.Region/Components/SelectRegion.razor.js")]
44

55
@if (IsShowLabel)

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

Lines changed: 1 addition & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -9,75 +9,13 @@ namespace BootstrapBlazor.Components;
99
/// </summary>
1010
public partial class SelectRegion
1111
{
12-
/// <summary>
13-
/// Gets or sets the placeholder text.
14-
/// </summary>
15-
[Parameter]
16-
public string? PlaceHolder { get; set; }
17-
18-
/// <summary>
19-
/// Gets or sets the color. The default is <see cref="Color.None"/> (no color).
20-
/// </summary>
21-
[Parameter]
22-
public Color Color { get; set; }
23-
24-
/// <summary>
25-
/// Gets or sets the dropdown icon. The default is "fa-solid fa-angle-up".
26-
/// </summary>
27-
[Parameter]
28-
[NotNull]
29-
public string? DropdownIcon { get; set; }
30-
31-
/// <summary>
32-
/// Gets or sets the callback method when the clear button is clicked. Default is null.
33-
/// </summary>
34-
[Parameter]
35-
public Func<Task>? OnClearAsync { get; set; }
36-
37-
/// <summary>
38-
/// Gets or sets the right-side clear icon. Default is fa-solid fa-angle-up.
39-
/// </summary>
40-
[Parameter]
41-
[NotNull]
42-
public string? ClearIcon { get; set; }
43-
44-
/// <summary>
45-
/// Gets or sets the <see cref="IIconTheme"/> service instance.
46-
/// </summary>
47-
[Inject]
48-
[NotNull]
49-
private IIconTheme? IconTheme { get; set; }
50-
51-
[Inject]
52-
[NotNull]
53-
private IRegionService? RegionService { get; set; }
12+
private string? InputId => $"{Id}_input";
5413

5514
private string? ClassString => CssBuilder.Default("select bb-region")
5615
.AddClass("disabled", IsDisabled)
5716
.AddClassFromAttributes(AdditionalAttributes)
5817
.Build();
5918

60-
private string? InputId => $"{Id}_input";
61-
62-
private string? InputClassString => CssBuilder.Default("form-select form-control")
63-
.AddClass($"border-{Color.ToDescriptionString()}", Color != Color.None && !IsDisabled && !IsValid.HasValue)
64-
.AddClass($"border-success", IsValid.HasValue && IsValid.Value)
65-
.AddClass($"border-danger", IsValid.HasValue && !IsValid.Value)
66-
.AddClass(CssClass).AddClass(ValidCss)
67-
.Build();
68-
69-
private string? AppendClassString => CssBuilder.Default("form-select-append")
70-
.AddClass($"text-{Color.ToDescriptionString()}", Color != Color.None && !IsDisabled && !IsValid.HasValue)
71-
.AddClass($"text-success", IsValid.HasValue && IsValid.Value)
72-
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
73-
.Build();
74-
75-
private string? ClearClassString => CssBuilder.Default("clear-icon")
76-
.AddClass($"text-{Color.ToDescriptionString()}", Color != Color.None)
77-
.AddClass($"text-success", IsValid.HasValue && IsValid.Value)
78-
.AddClass($"text-danger", IsValid.HasValue && !IsValid.Value)
79-
.Build();
80-
8119
private string? GetHeaderActiveClass(RegionViewMode type) => _currentViewMode == type ? "active" : null;
8220

8321
private string? GetBodyActiveClass(RegionViewMode type) => CssBuilder.Default("bb-region-body-item")
@@ -109,9 +47,6 @@ protected override void OnParametersSet()
10947
{
11048
base.OnParametersSet();
11149

112-
DropdownIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectDropdownIcon);
113-
ClearIcon ??= IconTheme.GetIconByKey(ComponentIcons.SelectClearIcon);
114-
11550
ResetValue();
11651
}
11752

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

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,19 @@
66
display: none;
77
}
88

9-
.popover-region .dropdown-menu {
9+
.dropdown-menu {
1010
--bs-dropdown-padding-y: 0;
1111
}
1212

13-
.popover-region ul {
14-
margin: 0;
15-
padding: 0;
16-
}
13+
.dropdown-menu ul {
14+
margin: 0;
15+
padding: 0;
16+
}
1717

18-
.popover-region li {
19-
list-style: none;
20-
transition: background-color .3s linear, color .3s linear;
21-
}
18+
.dropdown-menu li {
19+
list-style: none;
20+
transition: background-color .3s linear, color .3s linear;
21+
}
2222

2323
.bb-region-header {
2424
width: 400px;

0 commit comments

Comments
 (0)