From 266f20568eb1ba1cc8b8b8bce331211836407961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=99=BA=E8=83=BD=E5=A4=A7=E7=9F=B3=E5=A4=B4?= Date: Tue, 27 May 2025 07:30:37 +0800 Subject: [PATCH] =?UTF-8?q?Area=E6=94=AF=E6=8C=81=E5=8C=85=E5=90=AB?= =?UTF-8?q?=E8=87=AA=E8=BA=AB=E7=9A=84GetAllParents=EF=BC=9B=E4=BC=98?= =?UTF-8?q?=E5=8C=96IP=E6=90=9C=E7=B4=A2=EF=BC=8C=E6=94=AF=E6=8C=81=20?= =?UTF-8?q?=E4=B8=8A=E6=B5=B7-=E4=B8=8A=E6=B5=B7-=E5=BE=90=E6=B1=87?= =?UTF-8?q?=E5=8C=BA=20=E6=A0=BC=E5=BC=8F=E7=9A=84=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XCode/Membership/地区.Biz.cs | 49 ++++++++++++++----------- XUnitTest.XCode/Membership/AreaTests.cs | 25 +++++++++++-- 2 files changed, 48 insertions(+), 26 deletions(-) diff --git a/XCode/Membership/地区.Biz.cs b/XCode/Membership/地区.Biz.cs index 04ae91beb..6ebe30104 100644 --- a/XCode/Membership/地区.Biz.cs +++ b/XCode/Membership/地区.Biz.cs @@ -120,7 +120,12 @@ public partial class Area : Entity /// 所有父级,从高到底 /// - public IList GetAllParents() + public IList GetAllParents() => GetAllParents(false); + + /// 所有父级,从高到底 + /// 是否包括自己 + /// + public IList GetAllParents(Boolean includeSelf) { var list = new List(); var entity = Parent; @@ -136,6 +141,8 @@ public partial class Area : Entity // 倒序 list.Reverse(); + if (includeSelf && !list.Any(e => e.ID == ID)) list.Add(this); + return list; } @@ -254,6 +261,11 @@ public partial class Area : Entity if (!item.IsNullOrEmpty()) { var r2 = r.Childs.Find(e => e.Name == item || e.FullName == item); + // 可能中间不叫市辖区,而是跟第一段同名。例如 上海-上海市-徐汇区 + if (r2 == null && item.EqualIgnoreCase(r.Name, r.FullName)) + { + r2 = r.Childs.FirstOrDefault(e => e.IsVirtual); + } // 可能中间隔了一层市辖区,如上海青浦 if (r2 == null) { @@ -407,8 +419,9 @@ public partial class Area : Entity private static IDictionary SearchLike(Int32 parentid, String key, Boolean? enable, Int32 count) { // 两级搜索,特殊处理直辖 - var list = FindAllByParentID(parentid) as List; - if (list.Count == 1 && list[0].Name.StartsWithIgnoreCase("直辖", "省辖", "市辖")) list = FindAllByParentID(list[0].ID) as List; + var list = (FindAllByParentID(parentid) as List)!; + if (list.Count == 1 && list[0].Name.StartsWithIgnoreCase("直辖", "省辖", "市辖")) + list = (FindAllByParentID(list[0].ID) as List)!; foreach (var item in list.ToArray()) { var list2 = FindAllByParentID(item.ID); @@ -435,7 +448,7 @@ public partial class Area : Entity } // 近似搜索 - return list.Match(key, e => e.FullName).OrderByDescending(e => e.Value).Take(count).ToDictionary(e => e.Key, e => e.Value); + return list.Match(key, e => e.FullName!).OrderByDescending(e => e.Value).Take(count).ToDictionary(e => e.Key, e => e.Value); } /// 搜索地址所属地区(模糊匹配) @@ -504,30 +517,27 @@ public partial class Area : Entity } } - var list = new List(); - // 新的IP解析器 if (_GetIp != null) { var (area, addr) = _GetIp(ip); area = area?.TrimStart("中国\u2013"); - if (area.IsNullOrEmpty()) return list; + if (area.IsNullOrEmpty()) return []; var ss = area.Split("\u2013"); var r = FindByNames(ss); - if (r != null) - { - list.AddRange(r.GetAllParents()); - list.Add(r); + if (r == null) return []; + + var list = r.GetAllParents(true); + + if (maxLevel > 0 && list.Count > maxLevel) list = list.Take(maxLevel).ToList(); - if (maxLevel > 0 && list.Count > maxLevel) list = list.Take(maxLevel).ToList(); - } return list; } else { var address = ip.IPToAddress(); - if (address.IsNullOrEmpty()) return list; + if (address.IsNullOrEmpty()) return []; return SearchAddress(address, maxLevel); } @@ -542,17 +552,12 @@ public partial class Area : Entity /// public static IList SearchAddress(String address, Int32 maxLevel = 3) { - var list = new List(); - if (address.IsNullOrEmpty() || maxLevel <= 0) return list; + if (address.IsNullOrEmpty() || maxLevel <= 0) return []; var r = FindAddress(Root, address, maxLevel); - if (r != null) - { - list.AddRange(r.GetAllParents()); - list.Add(r); - } + if (r == null) return []; - return list; + return r.GetAllParents(true); //// IP数据库里,缺失自治区分隔符 //foreach (var item in _zzq) diff --git a/XUnitTest.XCode/Membership/AreaTests.cs b/XUnitTest.XCode/Membership/AreaTests.cs index 8ad9f6350..9c1ac8566 100644 --- a/XUnitTest.XCode/Membership/AreaTests.cs +++ b/XUnitTest.XCode/Membership/AreaTests.cs @@ -184,8 +184,8 @@ public class AreaTests var ar = Area.FindByID(310116); Assert.Equal("金山", ar.Name); - var ps = ar.GetAllParents(); - Assert.Equal(2, ps.Count); + var ps = ar.GetAllParents(true); + Assert.Equal(3, ps.Count); ar = ar.Parent; Assert.Equal("市辖区", ar.Name); @@ -434,8 +434,8 @@ public class AreaTests [TestOrder(80)] [Theory] [InlineData("112.32.148.126", 340100)] - [InlineData("116.234.90.174", 310000)] - [InlineData("116.233.20.228", 310000)] + [InlineData("116.234.90.174", 310100)] + [InlineData("116.233.20.228", 310100)] [InlineData("122.231.253.198", 330400)] public void SearchIP2(String ip, Int32 areaId) { @@ -478,4 +478,21 @@ public class AreaTests XTrace.WriteLine("{0} => {1} {2}", ip, ar.ID, ar.Path); Assert.Equal(areaId, ar.ID); } + + [TestOrder(92)] + [Theory] + [InlineData("112.65.49.174", 310104)] + public void SearchIP上海(String ip, Int32 areaId) + { + var addr = ip.IPToAddress(); + Assert.Equal("中国–上海–上海–徐汇区 联通/漕河泾数据中心", addr); + + var list = Area.SearchIP(ip, 3); + + Assert.True(list.Count > 0); + + var ar = list[^1]; + XTrace.WriteLine("{0} => {1} {2}", ip, ar.ID, ar.Path); + Assert.Equal(areaId, ar.ID); + } } \ No newline at end of file