diff --git a/app/Calendar.php b/app/Calendar.php index e52788f..7aac0c9 100644 --- a/app/Calendar.php +++ b/app/Calendar.php @@ -296,7 +296,7 @@ final class Calendar } } - /** 升级 / 安装时给全家每个账号补一遍(老库也要有这两本) */ + /** 升级 / 安装时给全家每个账号补一遍(老库也要有这些本) */ public static function seedDefaultsForFamily(int $familyId): void { $st = Database::get()->prepare( @@ -309,6 +309,40 @@ final class Calendar } } + /** + * 补一本「我的日程」(kind='custom')—— 每个人都要有。 + * + * 🔴 v24 第 21 批 第 7 条:`DEFAULT_KINDS` 里原来只有 6 本**派生**本, + * 于是"新建日程 → 放在哪本"全是派生本、默认还选中排最前的**观影** —— + * 用户直接打字点「加上」,建出来的是**观影记录**("建错东西", + * 事后极难发现)。所以默认清单里补了 'custom' => 「我的日程」。 + * + * ⚠️ **但只补清单是不够的**:`seedDefaults()` 只在**安装**与**结构升级** + * 那两条路径上被调用,而线上这套库早就升过级了 → 老用户**永远拿不到**这一本 + * (实测线上:owner=1 可写的普通本 0 本,唯一那本 custom 是用户自己建的)。 + * 所以必须有这条"按需补"的路径,由**打开日历时**顺手调一次(见 calendar 路由)。 + * + * ⚠️ 幂等:`owner_id + kind='custom'` 只要有一本就不再补 —— 名字**不计入判据**, + * 否则用户把自己的本子改名成别的之后,会又冒出一本「我的日程」 + * (`seedDefaults()` 是按 `owner_id + kind + name` 判重的,这里刻意更宽)。 + * ⚠️ 一次请求只跑一条 `SELECT`(有就不再写),对打开日历的开销可忽略。 + */ + public static function ensurePersonalBook(int $familyId, int $personId): void + { + if ($familyId <= 0 || $personId <= 0) { + return; + } + $st = Database::get()->prepare( + "SELECT id FROM calendars WHERE owner_id = ? AND kind = 'custom' LIMIT 1" + ); + $st->execute([$personId]); + if ($st->fetchColumn() !== false) { + return; // 已经有一本可写的普通本了(不管它叫什么名字) + } + [$name, $color] = self::DEFAULT_KINDS['custom']; + self::create($familyId, $personId, $name, $color, 'custom'); + } + // ---------------- 共享 ---------------- public static function shares(int $calendarId): array diff --git a/index.php b/index.php index c0d3363..560f5a3 100644 --- a/index.php +++ b/index.php @@ -3764,6 +3764,14 @@ switch ($r) { $anchor = date('Y-m-d'); } $ym = substr($anchor, 0, 7); + /* 🔴 v24 第 21 批 第 7 条:**打开日历顺手补一本「我的日程」**。 + 为什么必须在这儿补(而不是只改 DEFAULT_KINDS): + `Calendar::seedDefaults()` 只在**安装**与**结构升级**两条路径上跑过, + 线上这套库早就升完级了 → 老用户永远拿不到那一本。 + 结果:可写的普通本 0 本、"放在哪本"全是派生本、默认还选中排最前的 + **观影** → 用户直接点「加上」建出来的是一条**观影记录**(建错东西)。 + ⚠️ 幂等(owner_id + kind='custom' 有就不再补),一次请求只多一条 SELECT。 */ + Calendar::ensurePersonalBook($familyId, $me); $cals = Calendar::mine($familyId, $me); // 用户第 4 条:哪些本子显示,改由设置里的复选框决定(以前是左侧那一栏)。 // 藏掉的本子**不参与取数**,而不是"取出来再 display:none" —— diff --git a/templates/calendar/index.php b/templates/calendar/index.php index 8254ebc..1c809d3 100644 --- a/templates/calendar/index.php +++ b/templates/calendar/index.php @@ -181,7 +181,13 @@ $headText = $view === 'month' ? date('Y 年 n 月', $ts) foreach ($writable as $c) { if ((string)($c['kind'] ?? '') === 'custom') { $firstCal = $c; break; } } - if ($firstCal === null) { $firstCal = $writable ? $writable[0] : null; } ?> + if ($firstCal === null) { $firstCal = $writable ? $writable[0] : null; } + /* ⚠️ 模板里**再兜一道**"快照":路由只会在**页面级**补一次本子, + 而这张表单是页面渲染时定格的 —— 万一补本失败(DB 异常等), + 这里至少还能看出"没有可写的普通本",不至于把"选中了观影本" + 当成正常状态。 */ + $hasPersonal = $firstCal !== null + && (string)($firstCal['kind'] ?? '') === 'custom'; ?>
@@ -200,6 +206,13 @@ $headText = $view === 'month' ? date('Y 年 n 月', $ts)
+ + + ⚠️ 你还没有**自己的日程本**,上面选的是一本"派生本" + (加进去会变成观影 / 旅程记录)。去 + 日历本 建一本吧。 + +