v95 服务卡片四项:日程卡「今」按钮放大、观影/任务 2x4 列表可滑动、观影 4x4/6x4 补列间距且 6x4 改两列
#1 用户提四项(2026-10-26): 「日程的右上角那个今天的今,特别不好点,一不小心就到日程里面去了…… 是不是可以把按钮弄的大一点。」 「观影的卡片,2x4,右侧观影的列表,不能上下滑动,第三个被截断,很难看, 如果显示多个,就要能滑动,如果不能滑动,就显示两个。」 「任务的 2x4 卡片,也是一样的。」 「观影的 4x4 卡片,和 4x6 卡片,两列图片挤在一起,中间没有空隙,应该缩小一点, 这个大小,我感觉应该根据屏幕的大小来。4x6,宽度都是一样的,为啥要弄成三列?」 ① 日程卡「今」按钮 22x22 → 32x32 病根:22 的圆比最小建议点击区小一半,手指偏一点就落到卡片本体的 `.onClick(openApp)` 上 ⇒ 「想回今天」变成「进了日程详情」。 面积 484 → 1024(2.1 倍);同一份 sideBtn() 里的「+」一并放大, 翻页键 ‹ › 本来 32,现在四个按钮手感一致。 为什么是 32 不是 40:4x4 卡高度紧,顶栏与内容区竖向堆叠 (内容区 layoutWeight(1)),顶栏长高多少内容区就少多少。 必须改 width/height 本身 —— 卡片里这是 Button,可点区就是自己的宽高。 ②③ 观影/任务 2x4 右半 Column → List(可滚动) 病根不在条数而在容器:Column 根本不滚动 + 硬截 3 条, 3x(38+10=48) + 2x6 = 156vp 而可用仅 ≈130vp ⇒ 第三条被压扁/裁掉。 条数上限 3 → MR_2X4_MAX=12 / TK_2X4_MAX=30;滚动条 BarState.Auto (条目少时不露空滚动条)。数据侧 FbCardMediaData 两处 `rows.length < 4` 同步放到 30,否则卡上拿到的还是 4 条,改了容器也滑不出东西。 ④ 观影 4x4 / 6x4 补列间距 + 6x4 三列改两列 病根:`List({ space: 8 })` 的 space 在 lanes 多列模式下只管行间距, 列与列之间不会自动留缝;海报格 .width('100%') + .aspectRatio(0.68) 又贴着 lane 边排 ⇒ 两列严丝合缝贴死。 改法:.lanes(2) → .lanes(2, 8),第二个位置参数才是列间距 gutter。 ⚠️ gutter 是位置参数(SDK list.d.ts: lanes(value, gutter?: Dimension), Dimension = PX|VP|FP|LPX|Percentage|Resource)⇒ 传数字, 写成 { gutter: 8 } 是类型错误(中途踩到,编译期才炸)。 6x4 同时从 .lanes(3) 改成两列,与 4x4 一致;文件头那句 「这块卡更宽、一排放三张」已过时,已注明别再照着它改回去。 同批带上 v92 未提交的观影海报墙实现(此前只在工作树里,从未提交过): - 新增 data/FbCardImages.ets(下载 + desiredSize 缩图 + fd 管理) - FbCardMediaData / FbFormAbility / FbCardForms 里的 formImages 管道 - string.json 卡片名带尺寸(「家书 · 日程 4×4」/「家书 · 观影 4×4」) ⚠️ FbCardImages.ets 已被 FbCardMediaData import,不一起提交就编译不过。 验证: - 静态守卫 _fb_arkts_guard.js:1303 通过 / 0 失败 (新增 groupV95() 共 28 条,钉住按钮尺寸、List 容器、条数上限、 两列 + gutter>0、且不许写成 { gutter: N } 对象) - 反向验证 _fb_v59d_falsify.py:289 通过 / 0 失败 (新增 9 条注入,逐条证明上述断言真的会红) - 真编译 hvigorw assembleHap:BUILD SUCCESSFUL,HAP 产物已生成 ⚠️ 真机验收未做:hdc list targets 为空(设备未连/未解锁)。 这四项全是观感与手感,静态断言证明不了「点得着、滑得动、看着舒服」, 待设备连上后补真机探针(重点:真的点「今」、真的滑列表、量两列实际间距)。
This commit is contained in:
@@ -1,28 +1,35 @@
|
||||
/**
|
||||
* 家书 FamilyBook · 6×4 服务卡片(观影 · 上概述/新建,下滚动列表)
|
||||
* 家书 FamilyBook · 6×4 服务卡片(观影 · 上概述,下**两列海报墙**)—— v92 / v95
|
||||
*
|
||||
* 用户 2026-10-25:「观影卡片,加4x4,和4x6,上面概述,加新建按钮,
|
||||
* 下面瀑布流,就跟观影模块类似,可以滑下去看全部电影。」
|
||||
* ⇒ 上半:标题 + 更新时间 + 「+ 新建」(路由进 app 直开「记一场」);
|
||||
* 下半:`List`(卡片**不支持 Scroll、只支持 List**,见 FbCard4x4 的注释)
|
||||
* 装全部观影(数据侧倒序裁到 30 条),整卡可点进模块。
|
||||
* 用户 2026-10-25:「观影应该显示图片……实际上应该用大图的形式显示,
|
||||
* 就做成和观影模式一样,不行吗?」
|
||||
* ⇒ 与 4×4 同一套海报墙。
|
||||
*
|
||||
* ⚠️ 卡片不能自己发网络请求:只画 `fbMovieCardBuild()` 推过来的字段。
|
||||
* ⚠️ ForEach key 带 version 前缀(v89 教训,不重绘就是它的锅)。
|
||||
* 🔴 v95(用户 2026-10-26):「4x6,宽度都是一样的,为啥要弄成三列?」
|
||||
* ⇒ 列数从 3 改成 **2**(与 4×4 一致),并补上列间距 `gutter`。
|
||||
* ⚠️ 文件头原来写的是"这块卡更宽、一排放三张"——那句已经**过时**,
|
||||
* 别再照着它改回 `.lanes(3)`。
|
||||
*
|
||||
* 🔴 卡片里的图不能写 http 地址,只能 `Image('memory://' + img)`
|
||||
* (图由 `FbCardMediaData` 下载+缩图、以 `formImages` 的 fd 交过来)。
|
||||
* ⚠️ 卡片不支持 `Scroll`,只支持 `List` ⇒ 多列用 `List().lanes(n, gutter)`,别换成 Grid。
|
||||
* ⚠️ ForEach key 带 version 前缀(v89 教训)。
|
||||
*/
|
||||
|
||||
let storageMvB2 = new LocalStorage();
|
||||
let storageMvP6 = new LocalStorage();
|
||||
|
||||
/** 列表一行 */
|
||||
class FbMovieRow9b {
|
||||
/** 海报墙一格 */
|
||||
class FbMovieCell9b {
|
||||
key: string = '';
|
||||
title: string = '';
|
||||
dateText: string = '';
|
||||
cinema: string = '';
|
||||
rating: string = '';
|
||||
/** `memory://` 的内存键;空串 = 没图,画占位 */
|
||||
img: string = '';
|
||||
}
|
||||
|
||||
@Entry(storageMvB2)
|
||||
@Entry(storageMvP6)
|
||||
@Component
|
||||
struct FbMovieCard6x4 {
|
||||
@LocalStorageProp('state') state: string = 'loading';
|
||||
@@ -33,9 +40,9 @@ struct FbMovieCard6x4 {
|
||||
@LocalStorageProp('listJson') listJson: string = '[]';
|
||||
@LocalStorageProp('version') version: string = '';
|
||||
|
||||
private rows(): FbMovieRow9b[] {
|
||||
private rows(): FbMovieCell9b[] {
|
||||
try {
|
||||
const all: FbMovieRow9b[] = JSON.parse(this.listJson) as FbMovieRow9b[];
|
||||
const all: FbMovieCell9b[] = JSON.parse(this.listJson) as FbMovieCell9b[];
|
||||
return all;
|
||||
} catch (err) {
|
||||
return [];
|
||||
@@ -59,43 +66,67 @@ struct FbMovieCard6x4 {
|
||||
});
|
||||
}
|
||||
|
||||
/** 列表单行:日期 + 片名/影院(+评分) */
|
||||
/** 图下那行小字:`10月24日 · 万象城`(都空就不画) */
|
||||
private subText(item: FbMovieCell9b): string {
|
||||
let s: string = item.dateText;
|
||||
if (item.cinema !== '') {
|
||||
s = s !== '' ? s + ' · ' + item.cinema : item.cinema;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/** 一格格:大图 + 底部黑条上的片名/日期 */
|
||||
@Builder
|
||||
listRow(item: FbMovieRow9b) {
|
||||
Row({ space: 8 }) {
|
||||
Text(item.dateText !== '' ? item.dateText : '—')
|
||||
.fontSize(9)
|
||||
.fontColor('#A8988A')
|
||||
.width(46)
|
||||
.maxLines(1)
|
||||
Column({ space: 2 }) {
|
||||
posterCell(item: FbMovieCell9b) {
|
||||
Stack({ alignContent: Alignment.Bottom }) {
|
||||
if (item.img !== '') {
|
||||
// ⚠️ 只能 memory://(见文件头):写 http 地址在卡片里是一张空白
|
||||
Image('memory://' + item.img)
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.objectFit(ImageFit.Cover)
|
||||
.borderRadius(10)
|
||||
} else {
|
||||
Column() {
|
||||
Text(item.title)
|
||||
.fontSize(10)
|
||||
.fontColor('#7A4E8C')
|
||||
.maxLines(3)
|
||||
.textAlign(TextAlign.Center)
|
||||
.padding({ left: 4, right: 4 })
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.justifyContent(FlexAlign.Center)
|
||||
.backgroundColor('#EDE6F1')
|
||||
.borderRadius(10)
|
||||
}
|
||||
Column({ space: 1 }) {
|
||||
Text(item.title)
|
||||
.fontSize(13)
|
||||
.fontColor('#2C231D')
|
||||
.fontSize(10)
|
||||
.fontWeight(FontWeight.Medium)
|
||||
.fontColor('#FFFFFF')
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
if (item.cinema !== '') {
|
||||
Text(item.cinema)
|
||||
.fontSize(9)
|
||||
.fontColor('#A8988A')
|
||||
.width('100%')
|
||||
if (this.subText(item) !== '') {
|
||||
Text(this.subText(item))
|
||||
.fontSize(8)
|
||||
.fontColor('#FFFFFF')
|
||||
.opacity(0.8)
|
||||
.maxLines(1)
|
||||
.textOverflow({ overflow: TextOverflow.Ellipsis })
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
.layoutWeight(1)
|
||||
.alignItems(HorizontalAlign.Start)
|
||||
if (item.rating !== '') {
|
||||
Text(item.rating)
|
||||
.fontSize(10)
|
||||
.fontColor('#C08A3E')
|
||||
.maxLines(1)
|
||||
}
|
||||
.width('100%')
|
||||
.padding({ left: 6, right: 6, top: 3, bottom: 3 })
|
||||
.backgroundColor('#66000000')
|
||||
}
|
||||
.alignItems(VerticalAlign.Center)
|
||||
.width('100%')
|
||||
.padding({ left: 8, right: 8, top: 5, bottom: 5 })
|
||||
.borderRadius(8)
|
||||
.backgroundColor('#F6F2F7')
|
||||
.aspectRatio(0.68)
|
||||
.borderRadius(10)
|
||||
.clip(true)
|
||||
}
|
||||
|
||||
/** 空态 */
|
||||
@@ -127,7 +158,6 @@ struct FbMovieCard6x4 {
|
||||
.fontSize(9)
|
||||
.fontColor('#A8988A')
|
||||
.maxLines(1)
|
||||
/* ⭐ 新建按钮(子组件 onClick 优先于整卡,不会连带进 app) */
|
||||
Button('+')
|
||||
.fontSize(13)
|
||||
.fontColor('#FFFFFF')
|
||||
@@ -155,21 +185,33 @@ struct FbMovieCard6x4 {
|
||||
}
|
||||
.width('100%')
|
||||
|
||||
Divider()
|
||||
.strokeWidth(0.5)
|
||||
.color('#EFE6D8')
|
||||
|
||||
// ===== 全部观影(可滚动)=====
|
||||
// ===== 海报墙(三列,可滚动)=====
|
||||
if (this.rows().length === 0) {
|
||||
this.emptyHint()
|
||||
} else {
|
||||
List({ space: 5 }) {
|
||||
ForEach(this.rows(), (item: FbMovieRow9b) => {
|
||||
List({ space: 8 }) {
|
||||
ForEach(this.rows(), (item: FbMovieCell9b) => {
|
||||
ListItem() {
|
||||
this.listRow(item)
|
||||
this.posterCell(item)
|
||||
}
|
||||
}, (item: FbMovieRow9b): string => `ml_${this.version}_${item.key}`)
|
||||
}, (item: FbMovieCell9b): string => `mp_${this.version}_${item.key}`)
|
||||
}
|
||||
/* 🔴🔴 v95(用户 2026-10-26):「4x6,宽度都是一样的,为啥要弄成三列?」
|
||||
—— 原来是 `.lanes(3)`(文件头那句"这块卡更宽、一排放三张")。
|
||||
|
||||
⇒ 改成**两列**,与 4×4 一致:
|
||||
· 用户明确要求,且三列时每张海报明显更小、更挤,观感差;
|
||||
· 两列 + 更高的卡高 ⇒ 一屏能看到的行数更多,反而比三列看得多。
|
||||
|
||||
⚠️ 同时补 `gutter`:`List({ space: 8 })` 的 `space` 在 lanes 多列
|
||||
模式下只管**行间距**,列缝必须靠 `lanes(count, gutter)` 给,
|
||||
否则两列又会贴死(与 4×4 同一个坑,见 FbMovieCard4x4 里的详细说明)。
|
||||
`gutter` 是**位置参数**(`Dimension`),直接传数字,**不是** `{ gutter: 8 }`。
|
||||
|
||||
⚠️ 别再改回 `.lanes(3)`:列数一多,同一块卡里的海报就被压到
|
||||
看不清片名,而用户要的恰恰是"大图"。 */
|
||||
.lanes(2, 8)
|
||||
.alignListItem(ListItemAlign.Start)
|
||||
.width('100%')
|
||||
.layoutWeight(1)
|
||||
.scrollBar(BarState.Off)
|
||||
@@ -180,7 +222,6 @@ struct FbMovieCard6x4 {
|
||||
.padding(12)
|
||||
.backgroundColor('#FFFFFF')
|
||||
.borderRadius(16)
|
||||
// ⭐ 整卡可点
|
||||
.onClick((): void => this.openApp())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user