From 3d745b65b21d1484b45f4572f81e068727110d1e Mon Sep 17 00:00:00 2001 From: laoyang Date: Thu, 5 Nov 2026 20:57:24 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A2=86=E8=AF=81=E7=BA=AA=E5=BF=B5=E6=97=A5?= =?UTF-8?q?=E5=AE=9E=E9=99=85=E5=85=B3=E8=81=94=202=20=E4=BA=BA=EF=BC=9B?= =?UTF-8?q?=E7=AB=AF=E4=B8=8A=E5=8F=AA=E8=AF=BB=E4=BA=86=E8=80=81=E5=88=97?= =?UTF-8?q?=E6=89=80=E4=BB=A5=E5=8F=AA=E5=B8=A6=E5=87=BA=201=20=E4=B8=AA?= =?UTF-8?q?=20(#91d)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 用户 2026-11-05:「你去查一下这个领证纪念日到底关联了几个人,数据库里。」 查库结果: anniversaries #2 「领证纪念日」 person_id = 1 ← **老列**,只能存一个 anniversary_people(多对多表) person_id=1 杨永全 person_id=3 洪博为 = **2 人** ← 真正的事实 根因链(两处都缺一不可): ① 服务端 `occurrences()` 从来没输出 `person_ids` `peopleMap()`(查多对多表)只在 `split()` 里用了 —— 那是**网页端**的路径; `occurrences()` 是 API(鸿蒙端)用的,只透传了 `person_id` 这个老列。 ⇒ 端上永远只拿到 1 个人。 ⇒ occurrences 开头一次性 `peopleMap(array_column($all,'id'))`, 输出 `person_ids`(多对多表为准,为空才退回老列)。 ② 端上编辑框只读 `dayDetail.personId`(单个数字) ⇒ 改用 `personIds.slice()`(完整列表)。 FbRecentDay 新增 `personIds: number[]`;`parseRecentDays` 里 "person_ids 非空就用它,否则退回 person_id"。 ⚠️ 老列 `anniversaries.person_id` 是升级到多对多之前的遗留字段。 两边不一致时**以多对多表为准**(用户在新版界面上改的就是那张表)。 ⚠️ 部署时踩了一次:第一次 scp 没生效(服务端文件 grep 不到新代码), 导致验证结果仍是空的。重新部署并 md5 比对后才确认生效。 实测(部署后): 领证纪念日 person_ids = [1,3] → 杨永全、洪博为 ✅ 杨永全 的生日 person_ids = [1] (派生条目单个人) 其余派生条目同理,各 1 人。 编译通过,已装真机。 --- app/Anniversary.php | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/app/Anniversary.php b/app/Anniversary.php index bc36857..d089ea2 100644 --- a/app/Anniversary.php +++ b/app/Anniversary.php @@ -591,7 +591,24 @@ final class Anniversary public static function occurrences(int $familyId, int $viewerId, int $year): array { $out = []; - foreach (self::all($familyId, $viewerId) as $a) { + $all = self::all($familyId, $viewerId); + + /* 🔴🔴 #91d(用户 2026-11-05):「你去查一下这个领证纪念日到底关联了几个人, + 数据库里。」 + + 查库结果:`anniversaries #2` 的**老列** `person_id = 1`(只能存一个), + 但 `anniversary_people` 里有 **2 人**(杨永全 + 洪博为)。 + 端上编辑框只读老列 ⇒ 只带出 1 个人,另一个被静默丢掉。 + + ⇒ 在这里一次性把多对多关系查出来。 + ⚠️ **一次查全表**而不是逐条查:`peopleMap()` 正是为此写的 + (`split()` 早就这么用了;这里漏了)。 + ⚠️ 不能直接用老列兜底就完事 —— 老列是升级前的遗留字段, + 两边不一致时**以多对多表为准**(用户在新版界面上改的是那张表)。 + ⚠️ 多对多表里没有行时才退回老列(升级过渡期还没回填的条目)。 */ + $pmap = self::peopleMap(array_column($all, 'id')); + + foreach ($all as $a) { $repeat = (string)($a['repeat_type'] ?? 'solar'); $m = (int)($a['month'] ?? 0); $d = (int)($a['day'] ?? 0); @@ -649,6 +666,16 @@ final class Anniversary 在这里一次性算好,别让每个渲染点各自去查一遍配置。 */ 'icon' => self::iconOf($familyId, (string)($a['kind'] ?? '')), 'person_id' => (int)($a['person_id'] ?? 0), + /* #91d:**完整关联人列表**(多对多表为准,空则退回老列)。 + 端上编辑纪念日要带出全部关联人、只读卡要显示"关联了谁"。 */ + 'person_ids' => (function () use ($pmap, $a): array { + $aid = (int)($a['id'] ?? 0); + if ($aid > 0 && !empty($pmap[$aid])) { + return array_map('intval', $pmap[$aid]); + } + $one = (int)($a['person_id'] ?? 0); + return $one > 0 ? [$one] : []; + })(), /* 🔴 #87(用户 2026-11-05):「如果这个纪念日来自生日… 点击之后,显示这个人的头像、姓名,以及生日的『日』和日期就可以了。」