首页最近观影补真海报(v88)

用户:首页最近观影没有图片呢,左侧都是占位符。

v86 建这张卡时为“首页少打几个请求”,把海报刻意砍成 34x34 的 emoji 色块,
所以左侧不是加载失败的兜底,而是本来就只有占位符。网页端 _card_movies.php
一直是真海报,两端由此不一致。

改法:
- 海报位 34x46(2:3,与网页端 .hc-mv-poster 同口径),Image(fbImageSrc(...))
  先查本地附件缓存,命中零请求;
- 加 mvPosterFailIds + onError:取不到退回 emoji 色块,不留半张白图
  (与电影页同一手法,整体换新数组才刷新);
- 不加 ?w= 压缩档位:media.php 只留 1600 一档,对缩略图无意义。

验证:hvigorw assembleHap BUILD SUCCESSFUL;线上库实测 poster_key/文件/代理地址三者一致。
This commit is contained in:
2026-11-05 21:14:44 +08:00
parent 06e6e3798a
commit 4e3038a0aa
+68 -12
View File
@@ -71,6 +71,7 @@ import { FbPersonEditSheet } from '../../components/FbPersonEditSheet';
import { FbMovieRepo, FbMovieListItem, FbCinemaItem, FbMovieDetail } from '../../data/FbMovieRepo';
import { FbMovieDetailSheet } from '../../components/FbMovieDetailSheet';
import { FbPersonRepo, FbRosterPerson } from '../../data/FbPersonRepo';
import { fbImageSrc } from '../../data/FbAttachQueue';
import { FB_DOCK_RESERVE } from '../../components/FloatDock';
import { fbOnScroll, fbOnTouch } from '../../common/FbScroll';
import { fbMaskTransition, fbSheetTransition } from '../../common/FbAnim';
@@ -309,6 +310,18 @@ export struct FbHomePage {
@Local mvCreating: boolean = false;
/** 观影卡要显示的最近几条(本地库) */
@Local mvRecent: FbMovieListItem[] = [];
/**
* 海报加载失败的电影 id。
*
* 🔴 用户 2026-11-05:「首页最近观影没有图片呢,左侧都是占位符。」
* v86 当初为了"省网络请求"刻意用 🎬 色块占位,网页端 `_card_movies.php`
* 一直是真海报 ⇒ 端上补回真图。
*
* ⚠️ 海报是网络图,取不到是常态(没网、令牌失效、图被删)⇒ 必须记下失败,
* 那张卡退回 🎬 色块(与"本来就没海报"同观感),否则会一直挂半张白图。
* ⚠️ 与电影页同一个手法:`@Local` 只代理第一层,**整体换新数组**才刷新。
*/
@Local mvPosterFailIds: number[] = [];
/** 影院列表(`FbMovieNewSheet` 的必填项之一,懒拉) */
@Local mvCinemas: FbCinemaItem[] = [];
@Local mvLoading: boolean = false;
@@ -2465,11 +2478,17 @@ export struct FbHomePage {
}
/**
* 「最近观影」里的一行(v86)。
* 「最近观影」里的一行(v86,v88 补海报)。
*
* 形态照网页端 `_card_movies.php`:**片名**(主)+ 日期 · 影院(次)。
* ⚠️ 不放海报:卡片上放图要么挤成小方块看不清、要么整行高度被拉起来,
* 而且每行拉一张图 = 首页多几个请求。看海报请进电影页。
* 形态照网页端 `_card_movies.php`:**海报**(左)+ 片名(主)+ 日期 · 影院(次)。
*
* 🔴 用户 2026-11-05:「首页最近观影没有图片呢,左侧都是占位符。」
* v86 当初为了"首页少打几个请求"把海报砍成 🎬 色块,网页端一直是真图
* ⇒ 这里补回真海报。三条约束:
* ① 卡片上只放 **5 条**(`loadSideCards` 的 limit),5 张缩略图可接受;
* ② 走 `fbImageSrc` —— 本地库里已缓存的直接用本地明文,命中缓存时零请求;
* ③ **不加 `?w=` 压缩档位**:`media.php` 只留 1600 一档(#56),
* 对 34×46 的缩略图没意义,白付一次 OSS 处理费。
* ⚠️ 又是**两参数 @Builder**(`isLast` 只为画分隔线)——
* 与 `memoryRow` / `recentDayRow` 同一个安全前提:整块由 ForEach 按 key 重建。
*/
@@ -2477,19 +2496,37 @@ export struct FbHomePage {
movieRow(m: FbMovieListItem, isLast: boolean) {
Column({ space: 0 }) {
Row({ space: 10 }) {
/* 小圆角色块代替海报:用影院色(`cinemaColor`)
—— 既区分了影院、又不吃网络请求。
⚠️ 影院色可能是空串(没设影院的老数据)⇒ 兜底一个中性灰。 */
/* 左侧海报位(2:3 竖版,34×46 —— 与网页端 `.hc-mv-poster` 同尺寸口径)。
有海报放真图,没有 / 加载失败退回 🎬 色块。 */
Stack({ alignContent: Alignment.Center }) {
if (m.posterKey !== '' && !this.mvPosterFailed(m.id)) {
Image(fbImageSrc(m.posterKey, FB_TOKEN_STORE.get()))
.width('100%')
.height('100%')
.objectFit(ImageFit.Cover)
// 底下垫一张图标:图还没回来时不会闪白块
.alt($r('app.media.fb_ic_movies'))
// 海报是大图,同步加载会卡住首页首屏
.onError((): void => {
this.markMvPosterFailed(m.id);
})
} else {
/* 没有海报 / 取不到:🎬 + 影院色底(影院色空串由 `movieTint` 兜底)。
这一层同时是上面 Image 的"底"—— 真图铺满后看不见。 */
Column() {
Text('🎬')
.fontSize(15)
}
.width(34)
.height(34)
.borderRadius(9)
.width('100%')
.height('100%')
.backgroundColor(this.movieTint(m.cinemaColor))
.justifyContent(FlexAlign.Center)
.alignItems(HorizontalAlign.Center)
}
}
.width(34)
.height(46)
.borderRadius(4)
.clip(true)
.backgroundColor(FbColors.inputBg)
Column({ space: 3 }) {
Text(m.title !== '' ? m.title : '(未命名)')
@@ -2529,6 +2566,25 @@ export struct FbHomePage {
})
}
/** 这张海报是不是已经确认取不到(取不到就退回 🎬 色块) */
private mvPosterFailed(id: number): boolean {
return this.mvPosterFailIds.indexOf(id) >= 0;
}
/**
* 记下"这张海报取不到"。
*
* ⚠️ 必须**换新数组**赋值(`concat`)—— `@Local` 不代理数组内部变化,
* `push` 进去界面不会刷新(现象:图还是白的,占位也没出现)。
* ⚠️ 已记过就不再重复加:`onError` 可能多次触发,重复加会让数组无限增长。
*/
private markMvPosterFailed(id: number): void {
if (this.mvPosterFailed(id)) {
return;
}
this.mvPosterFailIds = this.mvPosterFailIds.concat([id]);
}
/** 观影行的副标题:`2026-10-20 · 万达影城`(影院名空则只留日期) */
private movieSub(m: FbMovieListItem): string {
const d: string = this.memoryDate(m.startsAt);