From 3b7238a4189db9301c4a13ee7d9c5b1fc6670ee9 Mon Sep 17 00:00:00 2001 From: laoyang Date: Tue, 20 Oct 2026 08:55:27 +0800 Subject: [PATCH] =?UTF-8?q?v64b=EF=BC=9A=E4=BF=AE=E7=9C=9F=E6=9C=BA?= =?UTF-8?q?=E5=BC=B9=E5=B1=82"=E7=82=B9=E4=BA=86=E6=B2=A1=E5=8F=8D?= =?UTF-8?q?=E5=BA=94"=EF=BC=88=E6=A0=B9=E5=AE=B9=E5=99=A8=20Column=20?= =?UTF-8?q?=E2=86=92=20Stack=EF=BC=89+=20=E6=97=A5=E6=9C=9F=E8=A1=8C?= =?UTF-8?q?=E7=83=AD=E5=8C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 四个日期/选择类浮层在真机上**完全打不开**:编译无告警、`aboutToAppear` 照常调用、 `dumpLayout` 里连弹层一个节点都看不到、点它会"穿透"到底下的列表。 根因(逐层二分定位):根容器写成 `Column` 且里面**先排一个整高遮罩** (`Column().width('100%').height('100%').backgroundColor(FB_MASK)`)再排卡片。 `Column` 是**线性**布局 ⇒ 遮罩占满整高后,卡片被排到屏幕**外面**。 ⇒ 全屏遮罩与卡片要"叠"(`Stack`),不能"排"(`Column`)。 改动: - FbDateTimeField / FbCinemaPickSheet / FbPersonPickSheet:根容器改 `Stack({ alignContent: Alignment.Center })`,遮罩与卡片作并列子项叠放; 去掉原先用于"居中卡片"的 `justifyContent(FlexAlign.Center)`(Stack 已对齐)。 - FbDateTimeField:「日期行」的 `.onClick` 由内层 `layoutWeight(1)` 的 Row 挪到**根 Row** —— 挂内层时那一行会被表单所在的**两列容器**盖住, 点击穿透到底下的观影列表(表现为"点日期行,列表反而响应了")。 - FbSheetClose:`onClose` 由 `@Param` 改 `@Event`(语义归位;实测 `@Param` 声明回调**并不会失效**,✕ 一直是能点的 —— 这不是本轮 bug 的根因,别混为一谈)。 验证: - 构建 BUILD SUCCESSFUL; - 静态守卫 644/0(新增 8 条:三个组件的 Stack 叠放 + 整高遮罩非空转 + 全项目无"根 Column 先排整高遮罩"坏形态 + 日期行热区在根 Row); - 守卫反向验证 92/0(新增 6 条注入,含把根 Stack 改回 Column、删遮罩、 热区挪回内层,逐条证明断言真会红)。 --- .../main/ets/components/FbCinemaPickSheet.ets | 9 +++-- .../main/ets/components/FbDateTimeField.ets | 40 +++++++++++++++---- .../main/ets/components/FbPersonPickSheet.ets | 7 +++- .../src/main/ets/components/FbSheetClose.ets | 13 ++++-- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/entry/src/main/ets/components/FbCinemaPickSheet.ets b/entry/src/main/ets/components/FbCinemaPickSheet.ets index e30d325..d737bb6 100644 --- a/entry/src/main/ets/components/FbCinemaPickSheet.ets +++ b/entry/src/main/ets/components/FbCinemaPickSheet.ets @@ -80,8 +80,12 @@ export struct FbCinemaPickSheet { } build() { - // 整屏遮罩 + 居中卡片(与全应用浮层同一形态) - Column() { + /* 🔴🔴 必须是 `Stack`,**不能**是 `Column`(2026-10-20 真机实测的真 bug)。 + `Column` 是**线性**布局:全屏遮罩(100% 高)会占满整高, + 卡片被排到它**下面** ⇒ 落到屏幕之外 ⇒ 弹层"点了没反应"。 + 症状:编译无告警、dumpLayout 里看不到弹层任何节点、点击会穿透到下层。 + ⇒ **全屏遮罩与卡片要"叠"(Stack),不能"排"(Column)**。 */ + Stack({ alignContent: Alignment.Center }) { Column() .width('100%') .height('100%') @@ -181,7 +185,6 @@ export struct FbCinemaPickSheet { } .width('100%') .height('100%') - .justifyContent(FlexAlign.Center) .hitTestBehavior(HitTestMode.Transparent) } diff --git a/entry/src/main/ets/components/FbDateTimeField.ets b/entry/src/main/ets/components/FbDateTimeField.ets index fee0432..7b0b63d 100644 --- a/entry/src/main/ets/components/FbDateTimeField.ets +++ b/entry/src/main/ets/components/FbDateTimeField.ets @@ -131,13 +131,21 @@ export struct FbDateTimeRow { }; build() { + /* + * ⚠️ `.onClick` 挂在**根 `Row`** 上(整行可点),不是挂在里面那个 + * `layoutWeight(1)` 的 `Row` 上 —— 2026-10-20 真机实测: + * 挂内层时,那一行会被表单所在的**两列容器**(dump 里两个 + * `x1=50..521 / 559..1030、y1=602..1500` 的可点节点)盖住, + * 点击**穿透**到底下的观影列表(表现为"点日期行,列表反而响应了")。 + * 根 `Row`(`.width('100%')`)与 `FbCalOptionRow` 同一形态,热区完整。 + */ Row({ space: 10 }) { Text(this.label) .fontSize(FbMetric.fontTiny) .fontColor(FbColors.faint) .width(28) - // 整块可点:日期与时间在**同一个控件**里,中间不再分两块 + // 日期与时间在**同一个控件**里,中间不再分两块 Row() { Text(fbCnDate(this.date)) .fontSize(FbMetric.fontSmall) @@ -155,9 +163,6 @@ export struct FbDateTimeRow { .backgroundColor(FbColors.inputBg) .borderRadius(FbMetric.radiusS) .alignItems(VerticalAlign.Center) - .onClick((): void => { - this.onTap(); - }) // 右侧小箭头:暗示"点开会选" Text('›') @@ -166,6 +171,9 @@ export struct FbDateTimeRow { } .width('100%') .alignItems(VerticalAlign.Center) + .onClick((): void => { + this.onTap(); + }) } } @@ -209,7 +217,27 @@ export struct FbDateTimePicker { } build() { - Column() { + /* + * 🔴🔴 必须是 `Stack`,**不能**是 `Column`(2026-10-20 真机实测抓到的真 bug)。 + * + * 错误形态(原先): + * Column() { // 根:线性布局 + * Column().width('100%').height('100%') // ← 全屏遮罩 + * Column() { ...卡片... } // ← 被挤到屏幕外 + * } + * `Column` 是**线性**布局:遮罩占满整高之后,卡片只能排在它**下面**, + * 于是落到屏幕之外 —— 弹层"点了没反应"。 + * + * 症状极具误导性(本轮排查花了很久,逐条记下): + * · 编译通过、无告警;`aboutToAppear` **确实被调用**(组件实例化了); + * · `dumpLayout` 里**完全看不到**弹层的任何节点(连插桩的 30 号红字都没有); + * · 点日期行会"穿透"到底下的观影列表(因为卡片不在屏幕内,点到的其实是列表); + * · 同文件的 `FbDateTimeRow`(没有遮罩)一直正常 —— 差异只在遮罩这一层。 + * ⇒ 教训:**全屏遮罩与卡片要"叠"(Stack),不能"排"(Column)**。 + * 项目里能用的浮层(`FbMovieInsightSheet`、`FbMovieDetailSheet`)都是 + * `Column{ 卡片 }` 或 `Stack{ ... }`,**没有**把全屏遮罩当 Column 子项排的。 + */ + Stack({ alignContent: Alignment.Center }) { // 遮罩:整屏铺一层,点它 = 取消。 // ⚠️ 必须**有**遮罩:没有的话,点弹层外面会直接点到下面那张编辑卡片上 // (真机上表现为"随手一点,表单被改了")。 @@ -302,8 +330,6 @@ export struct FbDateTimePicker { } .width('100%') .height('100%') - .justifyContent(FlexAlign.Center) - // ⚠️ 透明命中:让点击"卡片以外的区域"落到上面那层遮罩上(点遮罩关掉) .hitTestBehavior(HitTestMode.Transparent) } diff --git a/entry/src/main/ets/components/FbPersonPickSheet.ets b/entry/src/main/ets/components/FbPersonPickSheet.ets index 6daf08d..035a72c 100644 --- a/entry/src/main/ets/components/FbPersonPickSheet.ets +++ b/entry/src/main/ets/components/FbPersonPickSheet.ets @@ -144,7 +144,11 @@ export struct FbPersonPickSheet { } build() { - Column() { + /* 🔴🔴 必须是 `Stack`,**不能**是 `Column`(2026-10-20 真机实测的真 bug)。 + 原因与 `FbCinemaPickSheet` 那段完全相同:`Column` 是线性布局, + 全屏遮罩会占满整高、把卡片挤到屏幕外 ⇒ 弹层"点了没反应"。 + ⇒ **全屏遮罩与卡片要"叠"(Stack),不能"排"(Column)**。 */ + Stack({ alignContent: Alignment.Center }) { Column() .width('100%') .height('100%') @@ -350,7 +354,6 @@ export struct FbPersonPickSheet { } .width('100%') .height('100%') - .justifyContent(FlexAlign.Center) .hitTestBehavior(HitTestMode.Transparent) } } diff --git a/entry/src/main/ets/components/FbSheetClose.ets b/entry/src/main/ets/components/FbSheetClose.ets index 4fc66c4..a6fabd3 100644 --- a/entry/src/main/ets/components/FbSheetClose.ets +++ b/entry/src/main/ets/components/FbSheetClose.ets @@ -31,10 +31,14 @@ export struct FbSheetClose { /** * 关掉浮层。 * - * ⚠️ 必传:`@Param` 给不了函数默认值(ArkTS 里函数类型不能用常量表达式初始化), - * 所以这里用必填 + 各调用点都显式给。 + * 用 `@Event`:`@ComponentV2` 里回调**一律**用 `@Event`(数据入参才用 `@Param`, + * 见 `FbCalOptionRow.onPick` 等)。原先写的是 `@Param` —— + * ⚠️ 实测(2026-10-20 真机)`@Param` 声明回调**并不会失效**(✕ 是能点的), + * 所以这不是 bug;改过来只是**把语义摆正**,别让下一个人以为它会失效。 + * 本轮真正导致"弹层点了没反应"的是**根容器 `Column` → `Stack`** + * (线性布局把卡片挤出屏幕),与本文件无关,别混为一谈。 */ - @Param onClose: () => void = (): void => {}; + @Event onClose: () => void = (): void => {}; /** * 图标的颜色。 @@ -92,7 +96,8 @@ export struct FbSheetTitleBar { @Param confirmText: string = ''; /** 主题色(标题下的副标题、确认文字用它) */ @Param accent: string = ''; - @Param onClose: () => void = (): void => {}; + /** 同上:回调统一 `@Event`(`@Param` 实测也能用,但语义不对) */ + @Event onClose: () => void = (): void => {}; build() { Row({ space: 8 }) {