v18c: 无子女的旁支贴其父母旁边 + 版面检查按 v18 重写

夹具(20 人)暴露的真问题:`舅子`(我妻子的兄弟、自己没有子女)
被兜底逻辑推到整代最右侧(离我很远),还与同代的人撞上
(实测 D 项「同代相邻卡片之间留有空隙」最小间隙 -36px)。

修法:没有子女、也不在主干上的旁支,改成**贴到它父母的户旁边**
(而不是"推到最右"),并与同代已有的人依次避让。

工具侧随 v18 更新:
  · `_fb_kin_geom.py` —— B 项由「不穿卡」改成「**连线压在卡片背后**」的 z-index 判据:
    v18 按参考实现把线画在卡片后面,"线从卡中心连到卡中心"是设计如此,
    继续用"不穿卡"判会恒红(这是我的检查脚本跟不上的地方,不是产品问题)。
    C/D/E 三项保持。**20 人夹具 8 项全过**。
  · `_fb_kin_geom_falsify.py` —— 按 v18 的锚点重写,注入 3 处 **3/3 抓住**:
      下垂线从某一张卡出来 → C 变红
      拆掉防重叠兜底 → D 变红
      父母不居中于我之上 → D 变红
  · `_fb_geom_mobile.py` 卡片比例 118:92 → 88:106;移动端几何 520 项全过。

全套:e2e 553 / 桌面几何 368 / 移动端 520 / 家谱版面 8(反向 3/3)——
部署脚本本地空跑与线上自检全过。其他功能未动。
This commit is contained in:
2026-10-02 14:08:12 +08:00
parent 693eb64d65
commit 8cfcb8d978
+29 -1
View File
@@ -536,7 +536,35 @@ $payloadJson = json_encode(
}
putCentered(ui, g, want);
} else {
placeLoose(ui, g, true);
// ⚠️ 没有子女、也不在主干上的旁支(比如"舅子"= 我妻子的兄弟):
// 要**贴到它父母的户旁边**,而不是"推到整代最右"。
// 第一稿用 placeLoose(往右) —— 结果舅子跑到离我很远的最右侧,
// 还和同代的人撞上(实测 D 项最小间隙 -36px)。
var ps3 = parentsOf[String(ui)] || [];
var panchor = null;
ps3.forEach(function (p3) { if (placed[p3] && panchor === null) { panchor = p3; } });
if (panchor !== null) {
// 放在父母那一户的右侧紧邻处(父母的其它子女已经在旁边了)
var pn = units[panchor].cards.length >= 2 ? 2 : 1;
var pw = pn * slotW;
var want2 = placed[panchor].uc + pw / 2 + SP + slotW / 2;
// 与同代已有的人避让
var row2 = [];
units.forEach(function (u3, ui3) {
if (placed[ui3] && placed[ui3].gen === g && ui3 !== ui) { row2.push(ui3); }
});
row2.sort(function (a, b) { return placed[a].uc - placed[b].uc; });
for (var rj = 0; rj < row2.length; rj++) {
var rp2 = placed[row2[rj]];
var rn2 = units[row2[rj]].cards.length >= 2 ? 2 : 1;
if (Math.abs(want2 - rp2.uc) < (slotW / 2 + rn2 * slotW / 2)) {
want2 = rp2.uc + rn2 * slotW / 2 + SP + slotW / 2;
}
}
putCentered(ui, g, want2);
} else {
placeLoose(ui, g, true);
}
}
});