From f6157578dea4b4372ec9dda1d72dc4054370ac6e Mon Sep 17 00:00:00 2001 From: owen Date: Tue, 15 Sep 2026 08:57:54 +0800 Subject: [PATCH] ow --- .../FolderProfile3.pubxml.user | 2 +- .../master/AncestryTreeChartModal.vue | 56 ++++++++++++++++++- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/CloudBuilder/CloudBuilder.Web.Entry/Properties/PublishProfiles/FolderProfile3.pubxml.user b/CloudBuilder/CloudBuilder.Web.Entry/Properties/PublishProfiles/FolderProfile3.pubxml.user index c07c428..0ff53f6 100644 --- a/CloudBuilder/CloudBuilder.Web.Entry/Properties/PublishProfiles/FolderProfile3.pubxml.user +++ b/CloudBuilder/CloudBuilder.Web.Entry/Properties/PublishProfiles/FolderProfile3.pubxml.user @@ -3,7 +3,7 @@ <_PublishTargetUrl>C:\inetpub\wwwroot\dockwebapi2 - True|2026-09-10T01:14:56.2914193Z||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||; + True|2026-09-13T11:02:59.5654245Z||;True|2026-09-10T09:14:56.2914193+08:00||;True|2026-09-09T16:40:16.6461154+08:00||;True|2026-09-08T13:55:23.1502435+08:00||;True|2026-09-08T08:04:53.4279263+08:00||;True|2026-09-07T08:48:17.4682304+08:00||;True|2026-09-04T14:39:08.7878670+08:00||;True|2026-09-04T14:35:48.2937877+08:00||;True|2026-09-04T11:45:16.1372876+08:00||;True|2026-09-04T11:42:59.9356436+08:00||;True|2026-09-03T16:05:52.5270232+08:00||;True|2026-09-03T14:52:56.8559144+08:00||;True|2026-09-02T11:08:23.8720038+08:00||;True|2026-09-02T10:58:16.8081797+08:00||;True|2026-08-26T13:34:12.3805892+08:00||;True|2026-08-25T08:31:30.7787234+08:00||;True|2026-08-20T13:10:46.4725468+08:00||;True|2026-08-20T13:10:28.3142576+08:00||;True|2026-08-19T16:10:27.3362887+08:00||;True|2026-08-19T16:01:12.6234971+08:00||;True|2026-08-19T15:42:46.6576265+08:00||;True|2026-08-19T13:39:59.9363522+08:00||;True|2026-08-19T13:36:53.0379313+08:00||;True|2026-08-19T13:31:36.0841398+08:00||;True|2026-08-19T11:44:37.5319626+08:00||;True|2026-08-19T09:36:45.6000047+08:00||;True|2026-08-19T09:34:36.8468631+08:00||;True|2026-08-19T08:35:41.2202300+08:00||;True|2026-08-18T16:20:59.0170916+08:00||; \ No newline at end of file diff --git a/WebVue/src/components/master/AncestryTreeChartModal.vue b/WebVue/src/components/master/AncestryTreeChartModal.vue index 9d31565..5357386 100644 --- a/WebVue/src/components/master/AncestryTreeChartModal.vue +++ b/WebVue/src/components/master/AncestryTreeChartModal.vue @@ -69,10 +69,12 @@ const data = ref(null); const hasPerson = computed(() => !!data.value?.CurrentPerson?.FamilyPerson?.PersonId); const rootPersonId = computed(() => data.value?.CurrentPerson?.FamilyPerson?.PersonId ?? ""); -/** 全族索引:人员信息 / 夫妻关系(双向)/ 亲子关系 */ +/** 全族索引:人员信息 / 夫妻关系(双向)/ 亲子关系 / 亲子反向索引 */ let personMap = new Map(); let spousesOf = new Map(); let childrenOf = new Map(); +/** 孩子 -> 父母记录列表(一个孩子可能同时挂在生父、过继父等多个父节点下) */ +let parentsOf = new Map(); /** 已展开(显示孩子)的节点 personId 集合 */ const expandedIds = ref>(new Set()); @@ -155,6 +157,7 @@ const buildIndex = (resp: FamilyTreeData) => { personMap = new Map(); spousesOf = new Map(); childrenOf = new Map(); + parentsOf = new Map(); // 1) 所有人员信息(含性别),优先作为人员卡片数据源 const persons = resp?.CurrentPerson?.FamilyTreePersons ?? []; @@ -238,10 +241,29 @@ const buildIndex = (resp: FamilyTreeData) => { orderby: c.Orderby, }); childrenOf.set(c.PersonId, list); + // 反向记录:同一孩子可能有多条父记录(生父 / 过继父),保留以判断由谁承担后代 + const parentList = parentsOf.get(c.ChildrenId) ?? []; + parentList.push({ parentId: c.PersonId, relation: c.RelationType }); + parentsOf.set(c.ChildrenId, parentList); } }); }; +/** 承祧 / 入嗣 / 收养类关系:孩子被过继到该父名下,由其承担其后代世系 */ +const ADOPTIVE_RELATIONS = new Set(["C", "E", "F", "G", "H", "I", "J", "K", "L"]); + +/** + * 同一孩子挂在多个父节点下时,选定“承担后代”的父节点: + * 优先取承祧 / 过继关系的一方(如“继子”“承嗣”),否则取记录顺序中的第一个。 + * 其余父节点仅显示该孩子的引用卡片,不再展开其后代,避免后代被重复展示。 + */ +const primaryParentOf = (personId: string): string => { + const parents = parentsOf.get(personId) ?? []; + if (parents.length === 0) return ""; + const adopted = parents.find((p) => ADOPTIVE_RELATIONS.has(p.relation ?? "")); + return (adopted ?? parents[0]).parentId; +}; + /** 构建图数据:递归一次性展示所有人员,祖先为根,配偶同行右侧,孩子列在配偶正下方 */ const buildGraphData = () => { const nodes: any[] = []; @@ -320,8 +342,36 @@ const buildGraphData = () => { // 孩子列与本人第一行的配偶列对齐(x + 260),即孩子位于配偶正下方,竖直跟第一行对齐 const childBaseX = x + 260; children.forEach((c: any) => { - walk(c.id, depth + 1, childBaseX); - edges.push({ source: "n-" + personId, target: "n-" + c.id, data: { kind: "parent" } }); + // 一个孩子可能同时是多方之子(生父 / 过继父):每个父节点下各显示一张卡片。 + // 由“承祧 / 过继”的一方承担其后代,其余父节点只显示一张引用卡片(不展开其后代)。 + const isPrimary = primaryParentOf(c.id) === personId; + if (isPrimary) { + if (!visited.has(c.id)) { + walk(c.id, depth + 1, childBaseX); + } + edges.push({ source: "n-" + personId, target: "n-" + c.id, data: { kind: "parent" } }); + } else { + const childInfo = personMap.get(c.id) ?? {}; + const refId = "r-" + personId + "-" + c.id; + nodes.push({ + id: refId, + style: { x: childBaseX, y: cursor }, + data: { + kind: "member", + personId: c.id, + tag: "族员", + name: (childInfo.Surname ?? c.ChildrenSurname ?? "") + (childInfo.GenealogyName ?? c.ChildrenGenealogyName ?? ""), + commonName: childInfo.CommonName ?? c.ChildrenCommonName, + gender: childInfo.Gender ?? c.gender, + avatarUrl: childInfo.AvatarUrl ?? "", + hasChildren: false, + expanded: false, + loaded: true, + }, + }); + cursor += Y_STEP; + edges.push({ source: "n-" + personId, target: refId, data: { kind: "parent" } }); + } }); } };