观影 4x4/4x6 海报只配 6 张:划到第 7 格起变成淡紫占位块 #2

Closed
opened 2026-10-27 14:58:08 +00:00 by laoyang · 3 comments
Owner

现象(用户原话)

「观影4x4和4x6,只有六张图,划到第七张,就没图片了」

设备 5NC0225B27004718,当前版本 v95(b84ea06)。
实测确认:观影 4x4 / 6x4 卡的海报墙是两列可滚动列表,前 6 格有海报,第 7 格起全是淡紫占位块(只有片名文字)。

根因(已定位,不是渲染问题)

entry/src/main/ets/data/FbCardMediaData.ets:

位置 代码 说明
L262 const CARD_IMG_MAX: number = 6; 每次推送只给 6 张图
L220 起 rows.length < 30 但列表给了 30 条
L273-284 keys.length < CARD_IMG_MAX 收集海报键时到 6 就停
L299-311 只给 map 里命中的行写 img 第 7 条起 img === ''

卡片侧 FbMovieCard4x4.ets:82-104:img === '' 时走 else 分支画淡紫底 + 片名。
⇒ 数据侧只配 6 张图,却让卡片渲染 30 格,多出来的格子必然空。
渲染逻辑本身没错,是「配图数量」和「列表长度」两个上限不一致。

官方规格(决定了最多能给多少张)

华为 Form Kit FAQ(faqs-technology-54)原文:

从 API version 20 开始,图片文件数量上限为 20 张,所有图片总内存大小不超过 10MB,
超出限制的图片会显示异常,API version 19 及之前的版本,图片文件数量上限为 5 张,每张限制内存 2MB。

本机 const.ohos.apiversion = 26 ⇒ 走 20 张 / 10MB 这一档。
现有缩图 THUMB_W=240 / THUMB_H=360,解码后每张 240×360×4 = 0.33 MB:

  • 6 张 = 1.98 MB(现状)
  • 20 张 = 6.59 MB ← 仍在 10MB 以内,有余量

修复方案

让「配图数量」和「列表长度」用同一个常量,不再各写一个数:

  1. 把 CARD_IMG_MAX 从 6 提到 20(官方上限,内存 6.59MB 安全)。
  2. 列表上限 30 收敛到同一个常量 ⇒ 列表长度 = 图数量,结构上不可能再出现空网格。
  3. 缓存目录 FbCardImages.ets 的 MAX_FILES = 24 要 ≥ 新上限(20),目前够用,但写进注释绑定关系。
  4. 单张失败仍只让那一行留空(不中断整体推送),但不能让失败后的空行留在列表里:
    列表按「实际拿到图的行数」收敛(map.size),否则某个海报 404 时又会出现空格。

验收标准

  • 观影 4x4 卡:滚动到列表底部,最后一个可见格子有海报(无淡紫占位块)
  • 观影 6x4 卡:同上
  • 每格 img 非空(真机 dump 确认 Image 节点存在,不是占位 Column)
  • 列表长度 == 配图数量(代码层面同一常量,静态守卫断言)
  • 图片总量 ≤ 20 张且解码内存 ≤ 10MB(按 THUMB_W×THUMB_H×4×N 断言)
  • 2x4 卡既有行为不回退(右侧列表仍可滑动,v95 的验收项 ②③ 继续通过)

关联

  • 同卡片区域的上一批改动见 #1(「今」按钮 / 2x4 滑动 / 4x4&6x4 两列间隙),本单是 v95 之后新发现的缺陷。
## 现象(用户原话) > 「观影4x4和4x6,只有六张图,划到第七张,就没图片了」 设备 `5NC0225B27004718`,当前版本 v95(`b84ea06`)。 实测确认:观影 4x4 / 6x4 卡的海报墙是两列可滚动列表,**前 6 格有海报,第 7 格起全是淡紫占位块**(只有片名文字)。 ## 根因(已定位,不是渲染问题) `entry/src/main/ets/data/FbCardMediaData.ets`: | 位置 | 代码 | 说明 | |---|---|---| | L262 | `const CARD_IMG_MAX: number = 6;` | **每次推送只给 6 张图** | | L220 起 | `rows.length < 30` | 但列表给了 **30 条** | | L273-284 | `keys.length < CARD_IMG_MAX` | 收集海报键时到 6 就停 | | L299-311 | 只给 `map` 里命中的行写 `img` | 第 7 条起 `img === ''` | 卡片侧 `FbMovieCard4x4.ets:82-104`:`img === ''` 时走 `else` 分支画淡紫底 + 片名。 ⇒ **数据侧只配 6 张图,却让卡片渲染 30 格**,多出来的格子必然空。 渲染逻辑本身没错,是「配图数量」和「列表长度」两个上限不一致。 ## 官方规格(决定了最多能给多少张) 华为 Form Kit FAQ(`faqs-technology-54`)原文: > 从 API version 20 开始,图片文件数量上限为 **20 张**,所有图片总内存大小不超过 **10MB**, > 超出限制的图片会显示异常,API version 19 及之前的版本,图片文件数量上限为 5 张,每张限制内存 2MB。 本机 `const.ohos.apiversion = 26` ⇒ 走 20 张 / 10MB 这一档。 现有缩图 `THUMB_W=240 / THUMB_H=360`,解码后每张 `240×360×4 = 0.33 MB`: - 6 张 = 1.98 MB(现状) - 20 张 = **6.59 MB** ← 仍在 10MB 以内,有余量 ## 修复方案 让「配图数量」和「列表长度」用**同一个常量**,不再各写一个数: 1. 把 `CARD_IMG_MAX` 从 `6` 提到 **20**(官方上限,内存 6.59MB 安全)。 2. 列表上限 `30` 收敛到同一个常量 ⇒ 列表长度 = 图数量,**结构上不可能再出现空网格**。 3. 缓存目录 `FbCardImages.ets` 的 `MAX_FILES = 24` 要 ≥ 新上限(20),目前够用,但写进注释绑定关系。 4. 单张失败仍只让那一行留空(不中断整体推送),但**不能让失败后的空行留在列表里**: 列表按「实际拿到图的行数」收敛(`map.size`),否则某个海报 404 时又会出现空格。 ## 验收标准 - [ ] 观影 4x4 卡:滚动到列表底部,**最后一个可见格子有海报**(无淡紫占位块) - [ ] 观影 6x4 卡:同上 - [ ] 每格 `img` 非空(真机 dump 确认 `Image` 节点存在,不是占位 `Column`) - [ ] 列表长度 == 配图数量(代码层面同一常量,静态守卫断言) - [ ] 图片总量 ≤ 20 张且解码内存 ≤ 10MB(按 `THUMB_W×THUMB_H×4×N` 断言) - [ ] 2x4 卡既有行为不回退(右侧列表仍可滑动,v95 的验收项 ②③ 继续通过) ## 关联 - 同卡片区域的上一批改动见 #1(「今」按钮 / 2x4 滑动 / 4x4&6x4 两列间隙),本单是 v95 之后新发现的缺陷。
Author
Owner

进展:代码已改完、编译通过、静态验证全绿(真机待验)

提交:f0d0ab9(fix(card): 观影 4x4/6x4 海报墙「只有 6 张图」修复 #2)

改了什么(5 处,都在数据侧,卡片渲染一行没动)

文件 改动
data/FbCardMediaData.ets CARD_IMG_MAX 6 → 20
同上 拆出 CARD_ROW_MAX = 30(命名常量),专给不画图的 2x2/2x4 纯文本行
同上 新增 list:只保留 img !== '' 的行 ⇒ 格子数与图数结构上永远相等
同上 fbAttachPosters 签名 (recent, list) → (rows);任务卡同样的写死一并统一
data/FbCardImages.ets 新增 fbCardImagePaths 并发窗口(MAX_PARALLEL = 4);MAX_FILES 24

为什么不是「6 改成 20」就完事

单纯把 6 调大,下次谁再把列表上限改回去,同样的 bug 会原地复活。
所以真正的修法是让格子数由图数量决定:list 只收配到图的行,
长度天然 ≤ CARD_IMG_MAX。这样哪怕某张海报 404、或某条本来就没 poster_key,
也只是少一格,不会冒出一个淡紫占位块。

同时把两个数字都命名成常量(原来是裸字面量 30),
任何一处改动都必须显式写出来,不再是"两个各写各的"。

并发这件事为什么必须做

20 张图如果还用 for + await 串行,就是 20 次网络往返。
单张 connectTimeout 6000 + readTimeout 10000,实测会拖到 10~17 秒,
而卡片刷新的窗口根本撑不住这么久 —— 表现会是"刷新一半,图只出来几张"。
⇒ 走固定并发窗口,MAX_PARALLEL = 4:20 张压到 5 轮,又不会一次开 20 个连接。

内存核算(按解码后算,不是按 jpg 体积)

240 × 360 × 4 = 0.33MB 每张 × 20 张 = 6.59MB < 10MB,留 3.4MB 余量。

⚠️ 别为了"更清晰"去调大 THUMB_W/H:涨到 360×540 就是 0.74MB/张,
20 张 14.8MB 直接超限,表现是「部分图片显示异常 / 整卡白掉」,而且不报错。

验证结果

① 静态守卫:1317 通过 / 0 失败(新增 groupV96() 15 条断言)

② 反向验证:15 通过 / 0 失败 —— 7 条注入,每条都恰好命中自己的目标断言:

注入 内容 结果
A CARD_IMG_MAX 改回 6(bug 本体) ✅ 红 1 条
B 列表上限写回裸 30 ✅ 红 1 条
C 去掉 img !== '' 过滤 ✅ 红 1 条
D THUMB 放大到 480×720(26MB) ✅ 红 1 条
E MAX_FILES 降到 8(小于 20) ✅ 红 1 条
F 配图改回 for + await 串行 ✅ 红 1 条
G 把过滤挪到配图之前 ✅ 红 1 条

③ 编译:BUILD SUCCESSFUL in 13s,产物 entry-default-signed.hap 6.2M

🔴 反向验证抓出我自己的一个假绿断言(值得记一笔)

第一版断言写的是 CARD_IMG_MAX >= 4。而 bug 的原始值正好就是 6,
6 >= 4 恒真 ⇒ 把 6 注回去,守卫照样全绿,这条断言什么都没守。

已在第二版改成 > 6,理由直接来自用户原话「划到第七张就没图片了」:
第 7 格必须有图,图数就不可能停在 6。

教训:判据必须穿过 bug 值本身。写「≥ 某个看着合理的下限」时,
先问一句「bug 值本身能通过吗」—— 能通过,这条断言就是假的。

待办

  • ⏸ 真机未验:hdc list targets 当前为空(只有 COM3/COM4 两个 UART 口),
    手机没连上。等接入后装机实测「滚到底最后一格有海报」。
  • ⏸ 4x4 卡还需用户手动添加到桌面才能验(本机桌面现有 8 个家书 form 实例,没有 FbCard4x4)。
## 进展:代码已改完、编译通过、静态验证全绿(真机待验) 提交:`f0d0ab9`(`fix(card): 观影 4x4/6x4 海报墙「只有 6 张图」修复 #2`) ### 改了什么(5 处,都在数据侧,卡片渲染一行没动) | 文件 | 改动 | |---|---| | `data/FbCardMediaData.ets` | `CARD_IMG_MAX` 6 → **20** | | 同上 | 拆出 `CARD_ROW_MAX = 30`(命名常量),专给不画图的 2x2/2x4 纯文本行 | | 同上 | 新增 `list`:只保留 `img !== ''` 的行 ⇒ 格子数与图数**结构上**永远相等 | | 同上 | `fbAttachPosters` 签名 `(recent, list)` → `(rows)`;任务卡同样的写死一并统一 | | `data/FbCardImages.ets` | 新增 `fbCardImagePaths` 并发窗口(`MAX_PARALLEL = 4`);`MAX_FILES` 24 | ### 为什么不是「6 改成 20」就完事 单纯把 6 调大,下次谁再把列表上限改回去,同样的 bug 会原地复活。 所以真正的修法是**让格子数由图数量决定**:`list` 只收配到图的行, 长度天然 ≤ `CARD_IMG_MAX`。这样哪怕某张海报 404、或某条本来就没 `poster_key`, 也只是少一格,**不会冒出一个淡紫占位块**。 同时把两个数字都命名成常量(原来是裸字面量 `30`), 任何一处改动都必须显式写出来,不再是"两个各写各的"。 ### 并发这件事为什么必须做 20 张图如果还用 `for + await` 串行,就是 20 次网络往返。 单张 `connectTimeout 6000 + readTimeout 10000`,实测会拖到 **10~17 秒**, 而卡片刷新的窗口根本撑不住这么久 —— 表现会是"刷新一半,图只出来几张"。 ⇒ 走固定并发窗口,`MAX_PARALLEL = 4`:20 张压到 5 轮,又不会一次开 20 个连接。 ### 内存核算(按解码后算,不是按 jpg 体积) `240 × 360 × 4 = 0.33MB` 每张 × 20 张 = **6.59MB** < 10MB,留 3.4MB 余量。 ⚠️ 别为了"更清晰"去调大 `THUMB_W/H`:涨到 360×540 就是 0.74MB/张, 20 张 **14.8MB 直接超限**,表现是「部分图片显示异常 / 整卡白掉」,**而且不报错**。 ### 验证结果 **① 静态守卫**:`1317 通过 / 0 失败`(新增 `groupV96()` 15 条断言) **② 反向验证**:`15 通过 / 0 失败` —— 7 条注入,每条都**恰好**命中自己的目标断言: | 注入 | 内容 | 结果 | |---|---|---| | A | `CARD_IMG_MAX` 改回 6(bug 本体) | ✅ 红 1 条 | | B | 列表上限写回裸 `30` | ✅ 红 1 条 | | C | 去掉 `img !== ''` 过滤 | ✅ 红 1 条 | | D | `THUMB` 放大到 480×720(26MB) | ✅ 红 1 条 | | E | `MAX_FILES` 降到 8(小于 20) | ✅ 红 1 条 | | F | 配图改回 `for + await` 串行 | ✅ 红 1 条 | | G | 把过滤挪到配图之前 | ✅ 红 1 条 | **③ 编译**:`BUILD SUCCESSFUL in 13s`,产物 `entry-default-signed.hap` 6.2M ### 🔴 反向验证抓出我自己的一个假绿断言(值得记一笔) 第一版断言写的是 `CARD_IMG_MAX >= 4`。而 **bug 的原始值正好就是 6**, `6 >= 4` 恒真 ⇒ 把 6 注回去,守卫**照样全绿**,这条断言什么都没守。 已在第二版改成 `> 6`,理由直接来自用户原话「划到第七张就没图片了」: 第 7 格必须有图,图数就不可能停在 6。 > 教训:判据必须**穿过** bug 值本身。写「≥ 某个看着合理的下限」时, > 先问一句「bug 值本身能通过吗」—— 能通过,这条断言就是假的。 ### 待办 - ⏸ **真机未验**:`hdc list targets` 当前为空(只有 COM3/COM4 两个 UART 口), 手机没连上。等接入后装机实测「滚到底最后一格有海报」。 - ⏸ 4x4 卡还需用户手动添加到桌面才能验(本机桌面现有 8 个家书 form 实例,没有 `FbCard4x4`)。
Author
Owner

真机验收结果:已修复,4×4 与 6×4 两张都验过

设备 5NC0225B27004718,装机版本 f0d0ab9(v96)。

验证方法

这个 bug 编译不报错、运行也不报错,静态守卫只能守"代码里的数字关系",
守不住"第 7 格真的出图了"。所以必须滚一遍、数 Image 节点。

判据不是看颜色(我看不了图),而是靠真机节点树里两种形态的结构差异:

有图   Stack > [Image, Column(黑条: 片名 + 日期)]
无图   Stack > [Column(淡紫底: 片名), Column(黑条: 片名 + 日期)]

⇒ 判据 = Stack 的直接子节点里有 type == 'Image'。

结果

两张卡都是逐屏滚到底扫过来的(不是只看底部一屏 —— 只看底部可能只覆盖第 15~18 格,
而 bug 恰恰在第 7 格):

观影 4×4(967×1025 px)

逐屏扫过 18 格:
神探之痕迹 / 重生2 / 欢迎来龙餐馆 / 八仙! / 火遮眼 / 给阿嬷的情书 /
挽救计划 / 镖人:风起大漠 / 夜王 / 熊出没·年年有熊 / 飞驰人生3 /
东北警察故事3 / 寻秦记 / 用武之地 / 疯狂动物城2 / 青蛇 / 捕风追影 / 浪浪山小妖怪

✅ 18 格 > 6(6 是 bug 原值,必须超过它)
✅ 全部 18 格都有 Image(无图格:无)
✅ 同一格跨屏观测一致
✅ 确实滚动过

观影 6×4(967×1600 px):同样 18 格,同样全部有图。

关键断言为什么是「> 6」

6 就是 CARD_IMG_MAX 的旧值、也就是这个 bug 的本体。闸值定成「≥ 4」这种
"看着合理的下限"时,6 >= 4 恒真 ⇒ 把 6 注回去守卫照样全绿,等于没守。
所以闸值必须穿过 bug 值本身,理由直接来自用户原话:
「划到第七张就没图片了」⇒ 第 7 格必须有图 ⇒ 有图的格数不可能停在 6。

回归(改了共用代码,必须回头验)

v96 动的是 FbCardMediaData.ets 里两张卡共用的数据装配,所以一并验了:

卡 结果
观影 2×4 ✅ 可滑动(神探之痕迹/重生2/欢迎来龙餐馆 → 7月22日/火遮眼/给阿嬷的情书),v95 的改动没被破坏
任务 2×4 ✅ 正常渲染「待办 9 条」+ 列表
任务 4×4 / 6×4 ✅ 正常渲染
日程 6×4 ✅ 正常渲染(今天 10月28日 周三 / 十九)

顺带修掉的两个验收脚本自身的坑(不是产品问题,但会误导结论)

  1. 卡片高度阈值把 4×4 漏了:本机三种观影卡高度是
    2×4 = 450px、4×4 = 1025px、6×4 = 1600px。阈值最初写 > 1200,
    只命中 6×4,4×4 被静默跳过 —— 而用户原话是「4x4 和 4x6」两张。
    现改为 > 900 + 按高度分类,两张分别验。

  2. 「?? 格」其实是滚动中间态,不是无图:滚动动画中途,
    ListItem 会先建出 Stack > Image,底部信息条 Column 还没建出来,
    于是 texts() 为空、高度只有 496(正常 636)。
    这类格子混进统计会变成假标题 '?'(多个不同格子撞同一个 key),
    偶尔连 Image 都还没建 ⇒ 误报"无图"。
    现改为「有底部信息条且有文本」才算渲染完成才参与判定;
    真 bug 的格子是 Column(淡紫底+片名) + Column(黑条)、有文本,不会被漏掉。

这两条与 pitfalls #462(判据闸值放过了 bug 值)、#463(副本层级不对致基线就红)
同族:都属"看着全绿、其实没守住"。已一并记入。

收尾

  • 代码提交:f0d0ab9(带 #2)
  • 静态守卫 1317/0 · 反向验证 15/0(7 条注入各自命中目标断言)
  • 真机验收 11/0(两张卡各 5 项 + 两卡都在)
  • 无待办,可以关单
## 真机验收结果:已修复,4×4 与 6×4 两张都验过 设备 `5NC0225B27004718`,装机版本 `f0d0ab9`(v96)。 ### 验证方法 这个 bug **编译不报错、运行也不报错**,静态守卫只能守"代码里的数字关系", 守不住"第 7 格真的出图了"。所以必须滚一遍、数 Image 节点。 判据不是看颜色(我看不了图),而是靠真机节点树里两种形态的**结构差异**: ``` 有图 Stack > [Image, Column(黑条: 片名 + 日期)] 无图 Stack > [Column(淡紫底: 片名), Column(黑条: 片名 + 日期)] ``` ⇒ 判据 = `Stack` 的**直接子节点**里有 `type == 'Image'`。 ### 结果 两张卡都是**逐屏滚到底**扫过来的(不是只看底部一屏 —— 只看底部可能只覆盖第 15~18 格, 而 bug 恰恰在第 7 格): **观影 4×4(967×1025 px)** ``` 逐屏扫过 18 格: 神探之痕迹 / 重生2 / 欢迎来龙餐馆 / 八仙! / 火遮眼 / 给阿嬷的情书 / 挽救计划 / 镖人:风起大漠 / 夜王 / 熊出没·年年有熊 / 飞驰人生3 / 东北警察故事3 / 寻秦记 / 用武之地 / 疯狂动物城2 / 青蛇 / 捕风追影 / 浪浪山小妖怪 ✅ 18 格 > 6(6 是 bug 原值,必须超过它) ✅ 全部 18 格都有 Image(无图格:无) ✅ 同一格跨屏观测一致 ✅ 确实滚动过 ``` **观影 6×4(967×1600 px)**:同样 18 格,同样全部有图。 ### 关键断言为什么是「> 6」 `6` 就是 `CARD_IMG_MAX` 的旧值、也就是这个 bug 的本体。闸值定成「≥ 4」这种 "看着合理的下限"时,`6 >= 4` 恒真 ⇒ 把 6 注回去守卫照样全绿,等于没守。 所以闸值必须**穿过 bug 值本身**,理由直接来自用户原话: 「划到第七张就没图片了」⇒ 第 7 格必须有图 ⇒ 有图的格数不可能停在 6。 ### 回归(改了共用代码,必须回头验) v96 动的是 `FbCardMediaData.ets` 里**两张卡共用**的数据装配,所以一并验了: | 卡 | 结果 | |---|---| | **观影 2×4** | ✅ 可滑动(`神探之痕迹/重生2/欢迎来龙餐馆` → `7月22日/火遮眼/给阿嬷的情书`),v95 的改动没被破坏 | | **任务 2×4** | ✅ 正常渲染「待办 9 条」+ 列表 | | **任务 4×4 / 6×4** | ✅ 正常渲染 | | **日程 6×4** | ✅ 正常渲染(`今天 10月28日 周三` / `十九`) | ### 顺带修掉的两个**验收脚本**自身的坑(不是产品问题,但会误导结论) 1. **卡片高度阈值把 4×4 漏了**:本机三种观影卡高度是 `2×4 = 450px`、`4×4 = 1025px`、`6×4 = 1600px`。阈值最初写 `> 1200`, 只命中 6×4,4×4 被**静默跳过** —— 而用户原话是「4x4 和 4x6」两张。 现改为 `> 900` + 按高度分类,两张分别验。 2. **「?? 格」其实是滚动中间态,不是无图**:滚动动画中途, `ListItem` 会先建出 `Stack > Image`,底部信息条 `Column` 还没建出来, 于是 `texts()` 为空、高度只有 496(正常 636)。 这类格子混进统计会变成假标题 `'?'`(多个不同格子撞同一个 key), 偶尔连 Image 都还没建 ⇒ 误报"无图"。 现改为「有底部信息条且有文本」才算渲染完成才参与判定; 真 bug 的格子是 `Column(淡紫底+片名) + Column(黑条)`、**有文本**,不会被漏掉。 > 这两条与 `pitfalls #462`(判据闸值放过了 bug 值)、`#463`(副本层级不对致基线就红) > 同族:**都属"看着全绿、其实没守住"**。已一并记入。 ### 收尾 - 代码提交:`f0d0ab9`(带 `#2`) - 静态守卫 1317/0 · 反向验证 15/0(7 条注入各自命中目标断言) - 真机验收 11/0(两张卡各 5 项 + 两卡都在) - 无待办,可以关单
Author
Owner

收尾:已修复并真机验收通过,关单

提交:f0d0ab9(已推送到 main,b84ea06..f0d0ab9)

改了什么

entry/src/main/ets/data/FbCardMediaData.ets + FbCardImages.ets

  • CARD_IMG_MAX 6 → 20(华为 Form Kit FAQ:API 20+ 上限 20 张 / 10MB,
    本机 apiversion = 26 走这一档;内存按解码后算 240×360×4×20 = 6.59MB)
  • 拆出 CARD_ROW_MAX = 30(命名常量),专给不画图的 2×2/2×4 纯文本行
  • 新增海报墙专用 list:只保留 img !== '' 的行 ⇒ 格子数与图数在结构上永远相等
  • fbAttachPosters 签名 (recent, list) → (rows)(两个数组各写一遍循环,必只改一处)
  • 新增 fbCardImagePaths 并发取图(MAX_PARALLEL = 4):20 张串行实测 10~17s,
    卡片刷新窗口撑不住

核心思路不是"把 6 改成 20 就完事",而是让格子数由图数量决定:
这样哪怕某张海报 404、或某条本来就没 poster_key,也只是少一格,
不会冒出一个淡紫占位块。

验证

项 结果
静态守卫 groupV96() 1317 通过 / 0 失败
反向验证(7 条注入) 15 通过 / 0 失败
编译 BUILD SUCCESSFUL
真机 · 观影 4×4 18 格全部有图
真机 · 观影 6×4 18 格全部有图
真机 · 回归(2×4 / 任务卡 / 日程卡) 全部正常

反向验证抓出的两个真问题(都已修)

  1. 假绿断言:闸值原写 CARD_IMG_MAX >= 4,而 bug 原值正好是 6,
    6 >= 4 恒真 ⇒ 把 6 注回去守卫照样全绿。已改成 > 6。
  2. 副本层级:反向验证最初只拷 2 个 ets 文件,守卫遍历全树 ⇒ 基线就红,
    7 条注入全部"红了 0 条"(看着像注入没生效)。已改成复制整个 entry/src/main。

两条都已记入跨项目踩坑库(#462 / #463),避免同类问题再犯。

## 收尾:已修复并真机验收通过,关单 **提交**:`f0d0ab9`(已推送到 `main`,`b84ea06..f0d0ab9`) ### 改了什么 `entry/src/main/ets/data/FbCardMediaData.ets` + `FbCardImages.ets` - `CARD_IMG_MAX` 6 → **20**(华为 Form Kit FAQ:API 20+ 上限 20 张 / 10MB, 本机 `apiversion = 26` 走这一档;内存按解码后算 `240×360×4×20 = 6.59MB`) - 拆出 `CARD_ROW_MAX = 30`(命名常量),专给**不画图**的 2×2/2×4 纯文本行 - 新增海报墙专用 `list`:只保留 `img !== ''` 的行 ⇒ **格子数与图数在结构上永远相等** - `fbAttachPosters` 签名 `(recent, list)` → `(rows)`(两个数组各写一遍循环,必只改一处) - 新增 `fbCardImagePaths` 并发取图(`MAX_PARALLEL = 4`):20 张串行实测 10~17s, 卡片刷新窗口撑不住 核心思路不是"把 6 改成 20 就完事",而是**让格子数由图数量决定**: 这样哪怕某张海报 404、或某条本来就没 `poster_key`,也只是少一格, **不会冒出一个淡紫占位块**。 ### 验证 | 项 | 结果 | |---|---| | 静态守卫 `groupV96()` | 1317 通过 / 0 失败 | | 反向验证(7 条注入) | 15 通过 / 0 失败 | | 编译 | BUILD SUCCESSFUL | | 真机 · 观影 4×4 | 18 格全部有图 | | 真机 · 观影 6×4 | 18 格全部有图 | | 真机 · 回归(2×4 / 任务卡 / 日程卡) | 全部正常 | ### 反向验证抓出的两个真问题(都已修) 1. **假绿断言**:闸值原写 `CARD_IMG_MAX >= 4`,而 bug 原值正好是 6, `6 >= 4` 恒真 ⇒ 把 6 注回去守卫照样全绿。已改成 `> 6`。 2. **副本层级**:反向验证最初只拷 2 个 ets 文件,守卫遍历全树 ⇒ 基线就红, 7 条注入全部"红了 0 条"(看着像注入没生效)。已改成复制整个 `entry/src/main`。 两条都已记入跨项目踩坑库(#462 / #463),避免同类问题再犯。
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/FamilyBook_harmonyos#2