'曾祖辈', -2 => '祖辈', -1 => '父母辈']; return $up[$level] ?? '上 ' . abs($level) . ' 代'; } $down = [1 => '子女辈', 2 => '孙辈', 3 => '曾孙辈']; return $down[$level] ?? '下 ' . $level . ' 代'; }; $levels = array_keys($gens); // 整棵图的宽度取「最宽那一代」—— 所有代共用一个宽度,连线才能跟人对齐 $maxUnits = 1; foreach ($levels as $lv) { $maxUnits = max($maxUnits, count($units[$lv] ?? [])); } // ⚠️ 列宽最小值必须是 min-content(**不能**是 0): // v11 实测踩到 —— 最小值给 0 时列会被压到 96px 以下,而卡片是固定 96px 宽, // 于是窄屏 + 户数多时同代卡片**互相重叠**(照片与名字糊成一团)。 // minmax(min-content, 1fr) 给列一个「不小于内容」的地板:内容窄时照旧均分填满, // 内容宽过版心时整棵树交给 .tree-inner 横向滚动(这正是家谱的设计意图)。 $colStyle = 'grid-template-columns: repeat(' . (int)$maxUnits . ', minmax(min-content, 1fr));'; ?>

我的家谱

同代按长幼从左到右 · 夫妻并排 · 括号表示谁是谁的父母
还没连上任何亲属关系 到「」的资料页,把父母、配偶、子女填进去, 这张家谱就会自动长出来。兄弟姐妹不用单独填 —— 只要你们有同一对父母,就会自动认出来。
$level): ?>
户
$id): ?> 待确认 姻亲
[第一个子女列, 最后一个子女列] foreach ($kids as $i => $ku) { $pk = $ku['parent_key']; if ($pk === null) { continue; } if (!isset($ranges[$pk])) { $ranges[$pk] = [$i, $i]; } else { $ranges[$pk][1] = $i; } } // 父母单元key => 它在上一代里的列号(拿来决定竖线落点) $pidx = []; foreach (($units[$level] ?? []) as $i => $pu) { $pidx[$pu['key']] = $i; } ?>
$rg): ?> '', 'spouse' => null]; $who = $pn['head'] . ($pn['spouse'] !== null ? ' 夫妇' : ''); $pCol = $pidx[$pk] ?? $rg[0]; $lo = min($pCol, $rg[0]); $hi = max($pCol, $rg[1]); $span = $hi - $lo + 1; // 竖线落在父母列的中心(在横杆这一段里的百分比位置) $pct = ($pCol - $lo + 0.5) / $span * 100; ?>
$ku): ?>

「姻亲」= 因为婚姻进到这张图里的人(如我妻子的父母),不是本家的血亲。 括号横跨的那几户,就是括号上方那一户的子女。