22// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
33// Website: https://www.blazor.zone or https://argozhang.github.io/
44
5+ using System . Runtime . CompilerServices ;
6+
57namespace BootstrapBlazor . Components ;
68
79/// <summary>
@@ -15,14 +17,75 @@ public partial class SelectCity
1517 [ Parameter ]
1618 public bool IsMultiple { get ; set ; }
1719
20+ /// <summary>
21+ /// 获得/设置 是否开启搜索功能 默认 true 开启
22+ /// </summary>
23+ [ Parameter ]
24+ public bool ShowSearch { get ; set ; } = true ;
25+
26+ /// <summary>
27+ /// Gets or sets the search icon.
28+ /// </summary>
29+ [ Parameter ]
30+ public string ? SearchIcon { get ; set ; }
31+
32+ /// <summary>
33+ /// 获得/设置 单选时选择后是否自动关闭 默认 true
34+ /// </summary>
35+ [ Parameter ]
36+ public bool AutoClose { get ; set ; } = true ;
37+
1838 private string ? ClassString => CssBuilder . Default ( "select bb-city" )
1939 . AddClass ( "disabled" , IsDisabled )
2040 . AddClassFromAttributes ( AdditionalAttributes )
2141 . Build ( ) ;
2242
43+ private string ? SearchIconString => CssBuilder . Default ( "icon search-icon" )
44+ . AddClass ( SearchIcon )
45+ . Build ( ) ;
46+
47+ private string ? ClearIconString => CssBuilder . Default ( "icon clear-icon" )
48+ . AddClass ( ClearIcon )
49+ . Build ( ) ;
50+
2351 private readonly HashSet < string > _values = [ ] ;
52+ private string ? _searchText ;
53+
54+ private string ? GetActiveClass ( string item ) => CssBuilder . Default ( )
55+ . AddClass ( "active" , _values . Contains ( item ) || CurrentValue == item )
56+ . AddClass ( "prev" , ! string . IsNullOrEmpty ( _searchText ) && PinYinService . GetFirstLetters ( item ) . StartsWith ( _searchText ) )
57+ . Build ( ) ;
2458
25- private string ? GetActiveClass ( string item ) => _values . Contains ( item ) || CurrentValue == item ? "active" : null ;
59+ /// <summary>
60+ /// <inheritdoc/>
61+ /// </summary>
62+ protected override void OnParametersSet ( )
63+ {
64+ base . OnParametersSet ( ) ;
65+
66+ SearchIcon ??= IconTheme . GetIconByKey ( ComponentIcons . SelectSearchIcon ) ;
67+ }
68+
69+ /// <summary>
70+ /// <inheritdoc/>
71+ /// </summary>
72+ /// <returns></returns>
73+ protected override Task InvokeInitAsync ( ) => InvokeVoidAsync ( "init" , Id , Interop , new
74+ {
75+ TriggerSearch = nameof ( TriggerSearch )
76+ } ) ;
77+
78+ /// <summary>
79+ /// 触发过滤方法 由 JavaScript 触发
80+ /// </summary>
81+ /// <param name="v"></param>
82+ /// <returns></returns>
83+ [ JSInvokable ]
84+ public void TriggerSearch ( string v )
85+ {
86+ _searchText = v . ToUpperInvariant ( ) ;
87+ StateHasChanged ( ) ;
88+ }
2689
2790 private async Task OnClearValue ( )
2891 {
@@ -38,18 +101,26 @@ private async Task OnClearValue()
38101 }
39102 }
40103
41- private void OnSelectProvince ( string province )
104+ private RenderFragment RenderCities ( ) => builder =>
105+ {
106+ foreach ( var item in GetProvinces ( ) )
107+ {
108+ builder . AddContent ( 0 , RenderItem ( item ) ) ;
109+ }
110+ } ;
111+
112+ private void OnSelectProvince ( string provinceName )
42113 {
43114 if ( ! IsMultiple )
44115 {
45116 return ;
46117 }
47118
48- HashSet < string > cities = province switch
119+ HashSet < string > cities = provinceName switch
49120 {
50121 "直辖市" => Municipalities ,
51122 "特别行政区" => SpecialAdministrativeRegions ,
52- _ => GetCities ( province )
123+ _ => GetCities ( provinceName )
53124 } ;
54125 foreach ( var city in cities . Where ( city => ! _values . Remove ( city ) ) )
55126 {
@@ -58,7 +129,7 @@ private void OnSelectProvince(string province)
58129 CurrentValue = string . Join ( "," , _values ) ;
59130 }
60131
61- private void OnSelectCity ( string item )
132+ private async Task OnSelectCity ( string item )
62133 {
63134 if ( IsMultiple )
64135 {
@@ -72,61 +143,93 @@ private void OnSelectCity(string item)
72143 {
73144 CurrentValue = item ;
74145 }
75- }
76146
77- private static HashSet < string > GetProvinces ( )
78- {
79- return
80- [
81- "直辖市" ,
82- "河北省" ,
83- "山西省" ,
84- "辽宁省" ,
85- "吉林省" ,
86- "黑龙江省" ,
87- "江苏省" ,
88- "浙江省" ,
89- "安徽省" ,
90- "福建省" ,
91- "江西省" ,
92- "山东省" ,
93- "河南省" ,
94- "湖北省" ,
95- "湖南省" ,
96- "广东省" ,
97- "海南省" ,
98- "四川省" ,
99- "贵州省" ,
100- "云南省" ,
101- "陕西省" ,
102- "甘肃省" ,
103- "青海省" ,
104- "内蒙古自治区" ,
105- "广西壮族自治区" ,
106- "西藏自治区" ,
107- "宁夏回族自治区" ,
108- "新疆维吾尔自治区" ,
109- "台湾省" ,
110- "特别行政区"
111- ] ;
147+ if ( AutoClose )
148+ {
149+ await InvokeVoidAsync ( "hide" , Id ) ;
150+ }
112151 }
113152
114- private static readonly HashSet < string > Municipalities = [ "北京市" , "天津市" , "上海市" , "重庆市" ] ;
115-
116- private static readonly HashSet < string > SpecialAdministrativeRegions = [ "香港特别行政区" , "澳门特别行政区" ] ;
117-
118- private HashSet < string > GetCities ( string provinceName )
153+ private HashSet < string > GetProvinces ( )
119154 {
120- if ( provinceName == "直辖市" )
155+ if ( string . IsNullOrEmpty ( _searchText ) )
121156 {
122- return Municipalities ;
157+ return Provinces ;
123158 }
124159
125- if ( provinceName == "特别行政区" )
160+ if ( IsChinese ( _searchText ) )
126161 {
127- return SpecialAdministrativeRegions ;
162+ return [ .. Provinces . Where ( i => i . Contains ( _searchText ) || GetCities ( i ) . Any ( city => city . Contains ( _searchText ) ) ) ] ;
128163 }
129164
130- return RegionService . GetCities ( provinceName ) ;
165+ return [ .. GenerateProvincePinYin ( ) . Where ( i => FilterProvince ( i , _searchText ) ) . Select ( i => i . Name ) ] ;
131166 }
167+
168+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
169+ private static bool FilterProvince ( ProvinceItem item , string searchText ) => item . PinYin . StartsWith ( searchText ) || item . Cities . Any ( city => city . PinYin . StartsWith ( searchText ) ) ;
170+
171+ private static HashSet < ProvinceItem > ? _provinceItems ;
172+
173+ private HashSet < ProvinceItem > GenerateProvincePinYin ( )
174+ {
175+ _provinceItems ??= [ .. Provinces . Select ( i => new ProvinceItem ( )
176+ {
177+ PinYin = PinYinService . GetFirstLetters ( i ) ,
178+ Name = i ,
179+ Cities = GenerateCityPinYin ( i )
180+ } ) ] ;
181+ return _provinceItems ;
182+ }
183+
184+ private HashSet < string > GetCities ( string provinceName ) => provinceName switch
185+ {
186+ "直辖市" => Municipalities ,
187+ "特别行政区" => SpecialAdministrativeRegions ,
188+ _ => RegionService . GetCities ( provinceName )
189+ } ;
190+
191+ private HashSet < CityItem > GenerateCityPinYin ( string provinceName ) => [ .. GetCities ( provinceName ) . Select ( i => new CityItem ( )
192+ {
193+ PinYin = PinYinService . GetFirstLetters ( i ) ,
194+ Name = i
195+ } ) ] ;
196+
197+ private bool IsChinese ( string text ) => text . Any ( i => i >= 0x4E00 && i <= 0x9FFF ) ;
198+
199+ private static readonly HashSet < string > Provinces = [
200+ "直辖市" ,
201+ "河北省" ,
202+ "山西省" ,
203+ "辽宁省" ,
204+ "吉林省" ,
205+ "黑龙江省" ,
206+ "江苏省" ,
207+ "浙江省" ,
208+ "安徽省" ,
209+ "福建省" ,
210+ "江西省" ,
211+ "山东省" ,
212+ "河南省" ,
213+ "湖北省" ,
214+ "湖南省" ,
215+ "广东省" ,
216+ "海南省" ,
217+ "四川省" ,
218+ "贵州省" ,
219+ "云南省" ,
220+ "陕西省" ,
221+ "甘肃省" ,
222+ "青海省" ,
223+ "内蒙古自治区" ,
224+ "广西壮族自治区" ,
225+ "西藏自治区" ,
226+ "宁夏回族自治区" ,
227+ "新疆维吾尔自治区" ,
228+ "台湾省" ,
229+ "特别行政区"
230+ ] ;
231+
232+ private static readonly HashSet < string > Municipalities = [ "北京市" , "天津市" , "上海市" , "重庆市" ] ;
233+
234+ private static readonly HashSet < string > SpecialAdministrativeRegions = [ "香港特别行政区" , "澳门特别行政区" ] ;
132235}
0 commit comments