diff --git a/templates/kin/tree.php b/templates/kin/tree.php index 2c99b63..37c5d06 100644 --- a/templates/kin/tree.php +++ b/templates/kin/tree.php @@ -75,21 +75,39 @@ foreach ($units as $i => $u) { if (!$cards) { continue; } - // ⚠️ 户内部:**血亲在前、配偶在后**(配偶排右手边)。 - // 只按长幼排会让"妻子排到丈夫左边",夫妻横线看着别扭。 - $head = null; - foreach ($cards as $c) { - // 血亲 = 这个户里"有父母在本图上"的那一位;都没有就取第一位 - if ($head === null) { - $head = $c; - } - foreach ($graph['parents'][(int)$c['id']] ?? [] as $par) { - if (isset($unitOf[(int)$par]) && (int)$unitOf[(int)$par] !== $i) { - $head = $c; - break 2; + // ⚠️⚠️ 户内部:**本家血亲在前、配偶在后**(配偶排右手边,参考实现就是这样)。 + // + // "血亲"不能只按"他有父母在本图上"判定 —— 一对夫妻**两边父母都可能在图上** + // (我的父母 + 妻子的父母),那样两边都算血亲,取到第一个就成了"妻子当主位、 + // 我排在她右边"(实测线上就是这个症状:红围脖@639 在我的左边)。 + // + // 正解:按「**与"我"的血缘距离**」判定 —— 这一户里离「我」更近的那一位才是主位。 + // 我用一次不带配偶边的 BFS 算出血亲集合(Kinship::bloodRelatives 语义), + // 两边都在血亲集合里时,退到「与我的步数」比大小。 + $blood = []; + $bq = [$meId]; + $blood[$meId] = true; + while ($bq) { + $bid = array_shift($bq); + foreach (array_merge($graph['parents'][$bid] ?? [], $graph['children'][$bid] ?? []) as $nb) { + $nb = (int)$nb; + if (!isset($blood[$nb])) { + $blood[$nb] = true; + $bq[] = $nb; } } } + $head = null; + $headScore = null; + foreach ($cards as $c) { + $cid = (int)$c['id']; + // 分数越小越"本家":0 = 血亲本身,1 = 配偶,2 = 其它 + $sc = isset($blood[$cid]) ? 0 : 1; + if ($head === null || $sc < $headScore) { + $head = $c; + $headScore = $sc; + } + } if ($head !== null) { $rest = []; foreach ($cards as $c) {