This commit is contained in:
owenchen committed 2026-10-23 09:46:48 +08:00
1 parent 94d5fb2ec9
commit 6c86c59bdc
15 files changed
+429 -14

No files matched your search

@@ -1396,5 +1396,64 @@ namespace CloudBuilder.Master.Service
}
catch (Exception ex) { Console.WriteLine($"[FamilyTreeExchange] 审计写入失败: {ex.Message}"); }
}
/// <summary>
/// 族谱「统计」 tab 的聚合查询:总数/男/女/世代层数 + 各世代人数分布。
/// 世代 = 始祖起 BFS 深度(始祖=1 世);未连到始祖的旁支不入世代桶,只计入 Total。
/// 与 ListExchangeFiles/SaveExchangeFile 同套成员闸:非本族成员不能拉本族聚合数据。
/// </summary>
[PermissionOperate(name: MasterPermissionPolicy.FamilyTree, operate: Operate.Find)]
public FamilyTreeStatisticsData GetStatistics(string treeId)
{
FamilyTreeStatisticsData data = new FamilyTreeStatisticsData();
if (string.IsNullOrEmpty(treeId)) return data;
FamilyTreeEntity d = repository.DetachedEntities.Where(x => x.TreeId == treeId).FirstOrDefault();
if (d == null) throw new ValidatedException("族谱不存在.");
var helper = new FamilyTreePermissionHelper(service);
if (!helper.IsMember(treeId) && !helper.IsManager(treeId))
throw new ValidatedException("您不是该族谱成员.");
IRepository<FamilyPersonEntity> repositoryPerson = repository.GetRepository<IRepository<FamilyPersonEntity>>();
IRepository<FamilyTreeChildrenMapEntity> repositoryChildrenMap = repository.GetRepository<IRepository<FamilyTreeChildrenMapEntity>>();
FamilyPersonEntity[] persons = repositoryPerson.DetachedEntities.Where(x => x.TreeId == treeId).ToArray();
FamilyTreeChildrenMapEntity[] childrenMaps = repositoryChildrenMap.DetachedEntities.Where(x => x.TreeId == treeId).ToArray();
data.Total = persons.Length;
data.Male = persons.Count(x => x.Gender == "M");
data.Female = persons.Count(x => x.Gender == "W");
// BFS 从始祖起逐层下钻,记录每人世代号;genByPerson 去重兼做环保护
Dictionary<string, int> genByPerson = new Dictionary<string, int>();
if (!string.IsNullOrEmpty(d.AncestorPersonId))
{
Queue<KeyValuePair<string, int>> q = new Queue<KeyValuePair<string, int>>();
q.Enqueue(new KeyValuePair<string, int>(d.AncestorPersonId, 1));
genByPerson[d.AncestorPersonId] = 1;
while (q.Count > 0)
{
var cur = q.Dequeue();
foreach (var c in childrenMaps.Where(x => x.PersonId == cur.Key))
{
if (string.IsNullOrEmpty(c.ChildrenId) || genByPerson.ContainsKey(c.ChildrenId)) continue;
genByPerson[c.ChildrenId] = cur.Value + 1;
q.Enqueue(new KeyValuePair<string, int>(c.ChildrenId, cur.Value + 1));
}
}
}
data.GenerationCount = genByPerson.Count > 0 ? genByPerson.Values.Max() : 0;
// 按世代升序聚合;未入桶的旁支不入世代分布(仅计 Total)
data.PerGeneration = genByPerson.Values
.GroupBy(g => g)
.OrderBy(grp => grp.Key)
.Select(grp => new FamilyTreeGenerationCountData { Generation = grp.Key, Count = grp.Count() })
.ToArray();
return data;
}
}
}