纪念日:生日改成只读卡、自建纪念日才可编辑 (#87)

用户 2026-11-05 四条:
  1.「如果这个纪念日来自生日,我们是不能编辑的。」
  2.「点击之后,像日程那样弹出一个框来显示就行:显示这个人的头像、姓名,
     以及生日的『日』和日期就可以了。」
  3.「如果是我们自己创建的纪念日,那么这里面就是编辑纪念日。」
  4.「这个框和刚才我们编辑任务的框是一样的做法。样式、格式全部都一样。」

🔴 先说一个**会改坏用户数据的 bug**(这次一并修掉):
   原来派生生日也走 FbDayEditSheet,而且传的是
     editingMonth: 1, editingDay: 1   ← 写死的 1 月 1 日
   结果点开任何一个生日都显示「1 月 1 日」,点保存还能把
   **成员档案里的真实生日覆盖成 1 月 1 日**。
   这不是样式问题,是数据损坏。

改动:

① 新增 components/FbDayBirthdaySheet.ets(派生生日的只读卡)
   · 外壳用 FbSheetRing + 遮罩点击关闭 + 右上角 FbSheetClose
     —— 与 FbTaskPanel / FbDayEditSheet 同一套版式(用户第 4 条)
   · 左上角「生日 / 农历生日」主题色粗体 + 一行小字
     「来自成员资料,不能在这里修改」——把"不能编辑"这条边界写明白,
     否则用户会以为卡片坏了(用户第 1 条)
   · 主体:FbAvatar(56) + 姓名(主题色粗体) + 完整日期
   · 「日」做成视觉焦点:84×84 浅主题色块里放 34 号大字数字 + 「11 月」
   · 右侧:还有几天 / 满 N 周岁 / 农历说明
   · 底部:「要修改生日,请到「家人」里打开这位成员的资料」
     —— 只读也要给出口,不然用户不知道去哪儿改

② FbHomePage 按 source 分发
   birthday_solar / birthday_lunar → FbDayBirthdaySheet(只读)
   custom                          → FbDayEditSheet(可编辑,原行为)
   ⚠️ 判据用 source 前缀而不是 id === 0:两者目前等价,但 source 是语义、
      id 是实现细节 —— 万一以后派生条目也带 id,用 id 判会静默错。

③ 服务端 Anniversary::occurrences() 补输出
   · person_name —— `birthdays()` 算出来了,但 occurrences 逐个字段挑着抄时漏了
   · avatar / avatar_color —— 只读卡要画头像(key,端上拼 URL)
   · day / month —— 用户要的「生日的『日』」
     ⚠️ 用 $a['day'] 而不是从 $date 截:农历生日的 day 是农历日
        (初五 = 5),date 是换算后的公历日 —— 两者不同,用户要看"生日那天"
   · birthdays() 同步补 avatar / avatar_color(它原来也没有)

④ Types / FbParse 补五个字段
   personName / avatar / avatarColor / day / month

编译通过,已装真机。
This commit is contained in:
2026-11-05 20:32:02 +08:00
parent d9ca9dbe31
commit 41e3354fc8
4 changed files with 358 additions and 1 deletions
+39 -1
View File
@@ -62,6 +62,8 @@ import { FbTaskPanel } from '../../components/FbTaskPanel';
import { FbTaskEditSheet } from '../../components/FbTaskEditSheet';
/* v86:三张卡的新建表单 —— 全是**模块页正在用的同一个组件**,不另写。 */
import { FbDayEditSheet } from '../../components/FbDayEditSheet';
/* #87:派生生日的只读卡(用户:「如果这个纪念日来自生日,我们是不能编辑的」) */
import { FbDayBirthdaySheet } from '../../components/FbDayBirthdaySheet';
import { FbPersonSheet } from '../../components/FbPersonSheet';
import { FbSheetRing } from '../../components/FbSheetRing';
import { FbMovieNewSheet } from '../../components/FbMovieNewSheet';
@@ -681,6 +683,23 @@ export struct FbHomePage {
this.pfDetail = null;
}
/**
* 这条纪念日是不是「派生生日」(不能编辑的那种)。
*
* 判据用 `source` 前缀而不是 `id === 0`:
* · 派生生日:`birthday_solar` / `birthday_lunar`,服务端保证 `id = 0`;
* · 自建纪念日:`custom`,`id > 0`。
* 两个判据目前等价,但 `source` 是**语义**、`id` 是**实现细节** ——
* 万一以后派生条目也带 id(比如就想让它能点进某处),用 id 判会静默错。
*/
private isBirthdayDay(): boolean {
const d: FbRecentDay | null = this.dayDetail;
if (d === null) {
return false;
}
return d.source === 'birthday_solar' || d.source === 'birthday_lunar';
}
/** 打开纪念日详情(#63)。 */
private openDayDetail(d: FbRecentDay): void {
this.dayDetail = d;
@@ -2106,7 +2125,26 @@ export struct FbHomePage {
⚠️ 复用 `FbDayEditSheet`(它就是"回填一条已有纪念日"的表单)。
它的保存/删除按钮在卡里,看着是"可改的详情卡",
符合用户"先看到信息"的要求。 */
if (this.dayDetail !== null) {
if (this.dayDetail !== null && this.isBirthdayDay()) {
/* 🔴🔴 #87(用户 2026-11-05):
「1. 如果这个纪念日来自生日,我们是不能编辑的。
2. 点击之后,像日程那样弹出一个框来显示就行:显示这个人的头像、姓名,
以及生日的『日』和日期就可以了。」
⚠️ **这里原来是个会改坏数据的 bug**:派生生日也走 `FbDayEditSheet`,
而且传的是 `editingMonth: 1, editingDay: 1`(写死的 1 月 1 日)。
结果点开任何一个生日都显示「1 月 1 日」,点保存还能把
**真实生日覆盖成 1 月 1 日** —— 等于把成员档案里的生日改掉了。
只读卡从根上避开这件事。 */
FbDayBirthdaySheet({
accent: this.daysAccent(),
item: this.dayDetail,
onClose: (): void => {
this.closeDayDetail();
}
})
.transition(fbSheetTransition())
} else if (this.dayDetail !== null) {
FbDayEditSheet({
accent: this.daysAccent(),
editingId: this.dayDetail.id,