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