纪念日编辑框按任务面板的样式重做 (#90)

用户 2026-11-05:「现在我们来讨论纪念日的弹出框,也就是自己添加的纪念日
那个弹出框。这个做法和那个任务的做法是一样的,包括它的布局、颜色,
你都按照那个编辑,按那个方式去修改。包括删除按钮和保存按钮怎么放,
也都完全按照那个来做。」

逐项对齐 FbTaskPanel:

① 顶栏标题
   改前:fontTitle(17) + Medium + 墨色
   改后:fontBody(15) + **Bold** + **主题色**(与任务面板 headBar 同)
   副标题从「主题色 fontTiny」改成「faint fontTiny」(任务是「属于父任务」,那个是浅灰)
   关闭按钮 color 从 accent 改成 ''(与任务面板一致)

② 字段布局:横向 → 上下两行
   改前:`标签(44vp 浅灰小字) + 控件` 挤在一行
   改后:每个字段 = Column(space 6){ fieldLb(标签) ; 控件 }
         控件整行宽 / 40 高 / inputBg / radiusS,与任务面板逐项一致
   新增 fieldLb():fontSmall(13) + Bold + 主题色 + letterSpacing 0.6
   (与 FbTaskPanel.fieldLb 逐项相同)

   六个字段全部改了:叫什么 / 按什么重复 / 日期 / 分类 / 关联人 / 备注

③ 删除按钮挪到滚动内容末尾
   改前:和保存并排钉在底栏(红底白字)
   改后:最底部一行小字「删除这个纪念日」,要滚到底才看得到
         二次确认改成「删了就找不回来了,确定吗?」+ [确定删掉] [取消]
   —— 与任务面板 dangerZone 同一做法。
   理由(同任务面板):删除不可恢复,不该和"保存"这种高频操作并排常驻。

④ 底栏只留整行「保存」
   改前:「删除」+ 「记下来 / 保存修改」并排
   改后:一颗全宽「保存」,高 42(原来 44),圆角 radiusS
   文案统一叫「保存」—— 原来分「记下来」「保存修改」两个说法,
   与任务面板不一致。

⚠️ 字段**顺序**没有照抄任务面板(名称→重复→日期→分类→关联人→备注):
   两个框的字段集合不同,这几项之间的因果关系是"先起名、再定哪天",
   照抄顺序反而乱。用户说的是"布局和颜色"一致。
⚠️ fieldLb 在两端各有一份实现(FbTaskPanel 与 FbDayEditSheet 各自独立)——
   以后调字号/字重两处都得改,已在注释里写明。

编译通过,已装真机。
This commit is contained in:
2026-11-05 20:47:06 +08:00
parent cebfbde887
commit 93d0e886fb
+161 -74
View File
@@ -122,6 +122,28 @@ export struct FbDayEditSheet {
return out; return out;
} }
/**
* 字段标签(#90)。
*
* 与任务面板 `FbTaskPanel.fieldLb` **逐项一致**:
* fontSmall(13) + Bold + 主题色 + 字距 0.6
*
* 🔴 用户 2026-11-05:「这个做法和那个任务的做法是一样的,包括它的布局、
* 颜色,你都按照那个编辑,按那个方式去修改。」
* ⚠️ 与任务面板那边是两份实现(两个组件各自独立)——
* 以后要调字号/字重,**两处都得改**,别只改一处(本项目踩过多次)。
*/
@Builder
fieldLb(t: string) {
Text(t)
.fontSize(FbMetric.fontSmall)
.fontWeight(FontWeight.Bold)
.fontColor(this.accent)
.letterSpacing(0.6)
.width('100%')
.textAlign(TextAlign.Start)
}
build() { build() {
/* 🔴🔴 根必须 `Stack`:遮罩与卡片要"叠",不能当 `Column` 子项"排" /* 🔴🔴 根必须 `Stack`:遮罩与卡片要"叠",不能当 `Column` 子项"排"
(排会把卡片挤出屏幕 —— 2026-10-20 真机事故,见 pitfalls.md) */ (排会把卡片挤出屏幕 —— 2026-10-20 真机事故,见 pitfalls.md) */
@@ -137,17 +159,26 @@ export struct FbDayEditSheet {
Column() { Column() {
FbSheetRing({ radius: FbMetric.radius, ringColor: this.accent }) { FbSheetRing({ radius: FbMetric.radius, ringColor: this.accent }) {
Column({ space: 12 }) { Column({ space: 12 }) {
// ---- 标题栏 ---- /* ---- 标题栏(#90:与 FbTaskPanel.headBar 同一版式)----
Row({ space: 8 }) { 🔴 用户:「这个做法和那个任务的做法是一样的…你都按照那个编辑。」
与任务面板一致的三点:
· 标题 `fontBody`(15) + **Bold** + **主题色**(原来 fontTitle 墨色 Medium)
· 下面一行 `fontTiny` + faint 的说明(任务是「属于父任务」,
这里是「只记几月几号,每年自动提醒」)
· 右上角关闭按钮
⚠️ 原来是 `fontTitle`(17) + Medium + 墨色 —— 比任务面板那行大一号、
也没有主题色,两个框并排看不像一套东西。 */
Row({ space: 10 }) {
Column({ space: 2 }) { Column({ space: 2 }) {
Text(this.editingId > 0 ? '编辑纪念日' : '新建纪念日') Text(this.editingId > 0 ? '编辑纪念日' : '新建纪念日')
.fontSize(FbMetric.fontTitle) .fontSize(FbMetric.fontBody)
.fontWeight(FontWeight.Medium) .fontWeight(FontWeight.Bold)
.fontColor(FbColors.ink) .fontColor(this.accent)
.maxLines(1) .maxLines(1)
Text('只记几月几号,每年自动提醒') Text('只记几月几号,每年自动提醒')
.fontSize(FbMetric.fontTiny) .fontSize(FbMetric.fontTiny)
.fontColor(this.accent) .fontColor(FbColors.faint)
.maxLines(1) .maxLines(1)
} }
.alignItems(HorizontalAlign.Start) .alignItems(HorizontalAlign.Start)
@@ -158,43 +189,49 @@ export struct FbDayEditSheet {
onClose: (): void => { onClose: (): void => {
this.onClose(); this.onClose();
}, },
color: this.accent color: ''
}) })
} }
.width('100%') .width('100%')
.alignItems(VerticalAlign.Center) .alignItems(VerticalAlign.Center)
/* ---- 内容区(#90:全部改成「标签一行 + 控件一行」)----
🔴 用户:「包括它的布局…你都按照那个编辑。」
改前是「标签(44vp) 左 + 控件右」的横向排法,与任务面板的
上下两行完全不同。现在逐个对齐任务面板:
· 标签走 `fieldLb()`(fontSmall + Bold + 主题色 + 字距)
· 控件整行宽、40 高、inputBg 底、radiusS 圆角
· 字段之间 space 14(任务面板就是 14)
⚠️ 顺序沿用原来的业务顺序(名称 → 重复 → 日期 → 分类 → 关联人 → 备注),
因为这几项之间的因果关系是"先起名、再定哪天",
与任务面板的字段集合不同,不能照抄顺序。 */
Scroll() { Scroll() {
Column({ space: 12 }) { Column({ space: 14 }) {
// ---- 名称 ---- // ---- 名称 ----
Row({ space: 8 }) { Column({ space: 6 }) {
Text('叫什么') this.fieldLb('叫什么')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
.width(44)
TextInput({ text: this.title, placeholder: '如:结婚纪念日' }) TextInput({ text: this.title, placeholder: '如:结婚纪念日' })
.placeholderColor(FbColors.faint) .placeholderColor(FbColors.faint)
.placeholderFont({ size: FbMetric.fontTiny }) .placeholderFont({ size: FbMetric.fontSmall })
.fontSize(FbMetric.fontSmall) .fontSize(FbMetric.fontSmall)
.fontColor(FbColors.ink) .fontColor(FbColors.ink)
.backgroundColor(FbColors.inputBg) .backgroundColor(FbColors.inputBg)
.borderRadius(FbMetric.radiusS) .borderRadius(FbMetric.radiusS)
.height(42) .width('100%')
.layoutWeight(1) .height(40)
.padding({ left: 10, right: 10 }) .padding({ left: 12, right: 12 })
.onChange((v: string): void => { .onChange((v: string): void => {
this.title = v; this.title = v;
this.note2 = ''; this.note2 = '';
}) })
} }
.width('100%') .width('100%')
.alignItems(VerticalAlign.Center) .alignItems(HorizontalAlign.Start)
// ---- 重复方式 ---- // ---- 重复方式 ----
Column({ space: 6 }) { Column({ space: 6 }) {
Text('按什么重复') this.fieldLb('按什么重复')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
Row({ space: 8 }) { Row({ space: 8 }) {
ForEach(REPEAT_KEYS, (k: string, idx: number) => { ForEach(REPEAT_KEYS, (k: string, idx: number) => {
Text(this.repeatLabel(idx)) Text(this.repeatLabel(idx))
@@ -208,13 +245,16 @@ export struct FbDayEditSheet {
}) })
}, (k: string): string => 'rp_' + k) }, (k: string): string => 'rp_' + k)
} }
.width('100%')
} }
.width('100%') .width('100%')
.alignItems(HorizontalAlign.Start) .alignItems(HorizontalAlign.Start)
// ---- 日期(月 + 日)---- // ---- 日期 ----
Column({ space: 6 }) {
this.fieldLb('日期')
FbDateTimeRow({ FbDateTimeRow({
label: '日期', label: '',
date: this.pickDate, date: this.pickDate,
allDay: true, allDay: true,
accent: this.accent, accent: this.accent,
@@ -222,12 +262,13 @@ export struct FbDayEditSheet {
this.pickOpen = true; this.pickOpen = true;
} }
}) })
}
.width('100%')
.alignItems(HorizontalAlign.Start)
// ---- 分类 ---- // ---- 分类 ----
Column({ space: 6 }) { Column({ space: 6 }) {
Text('分类') this.fieldLb('分类')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
Scroll() { Scroll() {
Row({ space: 8 }) { Row({ space: 8 }) {
ForEach(this.kinds(), (k: string) => { ForEach(this.kinds(), (k: string) => {
@@ -253,18 +294,15 @@ export struct FbDayEditSheet {
.alignItems(HorizontalAlign.Start) .alignItems(HorizontalAlign.Start)
// ---- 关联人 ---- // ---- 关联人 ----
Row({ space: 8 }) { Column({ space: 6 }) {
Text('关联人') this.fieldLb('关联人')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
.width(44)
Text(this.peopleText()) Text(this.peopleText())
.fontSize(FbMetric.fontSmall) .fontSize(FbMetric.fontSmall)
.fontColor(this.personIds.length > 0 ? FbColors.ink : FbColors.muted) .fontColor(this.personIds.length > 0 ? FbColors.ink : FbColors.muted)
.maxLines(1) .maxLines(1)
.textOverflow({ overflow: TextOverflow.Ellipsis }) .textOverflow({ overflow: TextOverflow.Ellipsis })
.layoutWeight(1) .width('100%')
.height(42) .height(40)
.padding({ left: 12, right: 12 }) .padding({ left: 12, right: 12 })
.backgroundColor(FbColors.inputBg) .backgroundColor(FbColors.inputBg)
.borderRadius(FbMetric.radiusS) .borderRadius(FbMetric.radiusS)
@@ -273,30 +311,91 @@ export struct FbDayEditSheet {
}) })
} }
.width('100%') .width('100%')
.alignItems(VerticalAlign.Center) .alignItems(HorizontalAlign.Start)
// ---- 备注 ---- // ---- 备注 ----
Row({ space: 8 }) { Column({ space: 6 }) {
Text('备注') this.fieldLb('备注')
.fontSize(FbMetric.fontTiny)
.fontColor(FbColors.faint)
.width(44)
TextArea({ text: this.note, placeholder: '想记的细节(可空)' }) TextArea({ text: this.note, placeholder: '想记的细节(可空)' })
.placeholderColor(FbColors.faint) .placeholderColor(FbColors.faint)
.placeholderFont({ size: FbMetric.fontTiny }) .placeholderFont({ size: FbMetric.fontSmall })
.fontSize(FbMetric.fontSmall) .fontSize(FbMetric.fontSmall)
.fontColor(FbColors.ink) .fontColor(FbColors.ink)
.backgroundColor(FbColors.inputBg) .backgroundColor(FbColors.inputBg)
.borderRadius(FbMetric.radiusS) .borderRadius(FbMetric.radiusS)
.height(72) .width('100%')
.layoutWeight(1) .height(84)
.padding({ left: 10, right: 10, top: 8, bottom: 8 }) .padding({ left: 12, right: 12, top: 10, bottom: 10 })
.onChange((v: string): void => { .onChange((v: string): void => {
this.note = v; this.note = v;
}) })
} }
.width('100%') .width('100%')
.alignItems(VerticalAlign.Top) .alignItems(HorizontalAlign.Start)
/* ---- 危险操作区(#90:与任务面板 dangerZone 同一做法)----
🔴 用户:「包括删除按钮和保存按钮怎么放,也都完全按照那个来做。」
任务面板那边是:
· 底栏只留**整行「保存」**
· 删除挪到**滚动内容最末尾**,一行小字,要滚到底才看得到
(理由是"删除不可恢复,不该和保存并排常驻")
这里照做。
⚠️ 分隔线 + 上面留 18vp:与任务面板的间距一致。 */
if (this.editingId > 0) {
Column({ space: 0 }) {
Divider()
.color(FbColors.line)
.margin({ top: 10, bottom: 14 })
if (this.confirmingDelete) {
Text('删了就找不回来了,确定吗?')
.fontSize(FbMetric.fontTiny)
.fontColor('#C0533F')
.width('100%')
.margin({ bottom: 8 })
Row({ space: 10 }) {
Text('确定删掉')
.fontSize(FbMetric.fontSmall)
.fontColor('#FFFFFF')
.textAlign(TextAlign.Center)
.layoutWeight(1)
.height(40)
.backgroundColor('#C0533F')
.borderRadius(FbMetric.radiusS)
.onClick((): void => {
this.doDelete();
})
Text('取消')
.fontSize(FbMetric.fontSmall)
.fontColor(FbColors.muted)
.textAlign(TextAlign.Center)
.layoutWeight(1)
.height(40)
.backgroundColor(FbColors.inputBg)
.borderRadius(FbMetric.radiusS)
.onClick((): void => {
this.confirmingDelete = false;
this.note2 = '';
})
}
.width('100%')
} else {
Text('删除这个纪念日')
.fontSize(FbMetric.fontTiny)
.fontColor('#C0533F')
.textAlign(TextAlign.Center)
.width('100%')
.padding({ top: 10, bottom: 10 })
.onClick((): void => {
this.confirmingDelete = true;
})
}
}
.width('100%')
}
} }
.width('100%') .width('100%')
.alignItems(HorizontalAlign.Start) .alignItems(HorizontalAlign.Start)
@@ -314,44 +413,32 @@ export struct FbDayEditSheet {
.maxLines(3) .maxLines(3)
} }
// ---- 底部:删除(左)+ 保存 ---- /* ---- 底栏:只留**整行「保存」**(#90)----
Row({ space: 10 }) { 🔴 用户:「包括删除按钮和保存按钮怎么放,也都完全按照那个来做。」
if (this.editingId > 0) {
Text(this.confirmingDelete ? '真的删掉?' : '删除') 任务面板的底栏就是一颗全宽的「保存」—— 它是"确认改动"的位置,
.fontSize(FbMetric.fontBody) 不该混进"毁掉数据"的入口。删除已挪到滚动内容最末尾
.fontWeight(FontWeight.Medium) (见上面 dangerZone 那段)。
.fontColor('#FFFFFF') ⚠️ 文案统一叫「保存」:任务的按扭也叫「保存」。
原来这里分「记下来」/「保存修改」两个说法,与任务面板不一致。
⚠️ 高度 42(任务是 42,这里原来 44)—— 统一成 42。 */
Text(this.saving ? '保存中…' : '保存')
.fontSize(FbMetric.fontSmall)
.fontColor(Color.White)
.textAlign(TextAlign.Center) .textAlign(TextAlign.Center)
.height(44) .width('100%')
.padding({ left: 16, right: 16 }) .height(42)
.backgroundColor(this.saving ? '#C9CDD2' : this.accent)
.borderRadius(FbMetric.radiusS) .borderRadius(FbMetric.radiusS)
/* 🔴 v61:删除按钮统一红底白字。红值取自 color.json 的 `red` */ .margin({ top: 12 })
.backgroundColor(this.confirmingDelete ? '#C0533F' : fbAlpha('#C0533F', 0.86))
.onClick((): void => { .onClick((): void => {
if (this.confirmingDelete) { if (this.saving) {
this.doDelete(); return;
} else {
this.confirmingDelete = true;
} }
})
}
Text(this.saving ? '保存中…' : (this.editingId > 0 ? '保存修改' : '记下来'))
.fontSize(FbMetric.fontBody)
.fontWeight(FontWeight.Medium)
.fontColor(this.saving ? FbColors.faint : '#FFFFFF')
.textAlign(TextAlign.Center)
.layoutWeight(1)
.height(44)
.borderRadius(FbMetric.radiusS)
.backgroundColor(fbAlpha(this.accent, this.saving ? 0.35 : 0.98))
.onClick((): void => {
this.save(); this.save();
}) })
} }
.width('100%') .width('100%')
.alignItems(VerticalAlign.Center)
}
.width('100%')
.padding({ left: 18, right: 18, top: 18, bottom: 18 }) .padding({ left: 18, right: 18, top: 18, bottom: 18 })
.alignItems(HorizontalAlign.Start) .alignItems(HorizontalAlign.Start)
} }