v89 修复服务卡片翻页后时间轴不重绘:ForEach key 加 version 前缀(key 撞车复用旧组件)

This commit is contained in:
2026-10-24 21:53:13 +08:00
parent d69beb629f
commit 7ebe18b2d1
4 changed files with 35 additions and 15 deletions
+12
View File
@@ -141,6 +141,15 @@ export class FbCardData {
nowRatio: number = -1;
/** `15:40` */
nowLabel: string = '';
/** 🔴 v89:本次推送的唯一版本号(`Date.now()`)。
* ⚠️ 卡片 ForEach 的 key **必须**带上前缀:时间轴的冲突组号/空白 key
* (`g0`、`gap0`)每份数据都从 0 重新编号 —— 翻到下一天时 key 一模一样,
* ArkUI ForEach 认为"没变"直接复用旧组件 ⇒ 色块/空白高度全是旧一天的
* (真机实测:10/25、10/26 一直显示 10/24 的「工程管理硕士开题」)。
* 日期头、全天区能更新是因为它们的 key(事件 id)确实变了。
* ⚠️ 用 `Date.now()` 而不是 dayOffset:同一天也可能被定时刷新推新数据
* (日程改了),version 必须每次推送都不同才能逼 ForEach 全量重建。 */
version: string = '';
}
/** 两位补零 */
@@ -327,6 +336,9 @@ export async function fbCardBuild(ctx: common.Context, dayOffset: number): Promi
out.updatedAt = clockText();
out.nowLabel = out.updatedAt;
out.dayOffset = dayOffset;
/* 🔴 v89:每次推送一个新版本号,卡片侧 ForEach key 全部带上前缀 ——
不带的话翻页/刷新时 key 撞车,时间轴整层不重绘(文件头 version 注释)。 */
out.version = Date.now().toString();
out.isToday = dayOffset === 0;
out.nowRatio = out.isToday ? (now.getHours() * 60 + now.getMinutes()) / 1440 : -1;
+3 -1
View File
@@ -32,6 +32,8 @@ struct FbCard2x4 {
@LocalStorageProp('lunarText') lunarText: string = '';
@LocalStorageProp('dayCount') dayCount: number = 0;
@LocalStorageProp('upcomingJson') upcomingJson: string = '[]';
/* 🔴 v89:推送版本号 —— ForEach key 要带前缀(原因见 FbCardData.version)。 */
@LocalStorageProp('version') version: string = '';
@LocalStorageProp('selectedDate') selectedDate: number = 0;
/** 副标题:`星期二 九月初一` */
@@ -206,7 +208,7 @@ struct FbCard2x4 {
Column({ space: 6 }) {
ForEach(this.upcoming(), (item: FbCardUp, idx: number) => {
this.upcomingRow(item)
}, (item: FbCardUp, idx: number) => `${idx}_${item.time}_${item.title}`)
}, (item: FbCardUp, idx: number) => `up_${this.version}_${idx}_${item.time}_${item.title}`)
}
.width('100%')
.layoutWeight(1)
+11 -7
View File
@@ -54,6 +54,10 @@ struct FbCard4x4 {
@LocalStorageProp('viewStartHour') viewStartHour: number = 8;
@LocalStorageProp('viewEndHour') viewEndHour: number = 18;
@LocalStorageProp('nowRatio') nowRatio: number = -1;
/* 🔴 v89:推送版本号 —— 所有 ForEach 的 key 必须带前缀(原因见 FbCardData.version)。
不带的话翻到下一天时 `gap0/g0` 这些 key 一模一样,ArkUI ForEach 复用旧组件,
时间轴整层显示旧一天的色块和空白(真机实测踩到)。 */
@LocalStorageProp('version') version: string = '';
/** 小时刻度(含起点不含终点) */
private hours(): number[] {
@@ -239,7 +243,7 @@ struct FbCard4x4 {
.padding({ left: 5, right: 5 })
.borderRadius(5)
.backgroundColor(a.color)
}, (a: FbCardListRow, idx: number) => `ad_${idx}_${a.key}`)
}, (a: FbCardListRow, idx: number) => `ad_${this.version}_${idx}_${a.key}`)
}
.width('100%')
.padding({ bottom: 3 })
@@ -255,7 +259,7 @@ struct FbCard4x4 {
.height(HOUR_VP)
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
.hitTestBehavior(HitTestMode.None)
}, (h: number) => `gd${h}`)
}, (h: number) => `gd_${this.version}_${h}`)
}
.width('100%')
.height('100%')
@@ -302,19 +306,19 @@ struct FbCard4x4 {
.clip(true)
.width('100%')
.height(b.heightVp < MIN_BLOCK_VP ? MIN_BLOCK_VP : b.heightVp)
}, (b: FbCardTlBlock, bi: number) => `b_${b.key}_${bi}`)
}, (b: FbCardTlBlock, bi: number) => `b_${this.version}_${b.key}_${bi}`)
}
.layoutWeight(1)
.height('100%')
.padding({ right: 2 })
.clip(true)
}, (lane: FbCardTlBlock[], li: number) => `ln_${ln.key}_${li}`)
}, (lane: FbCardTlBlock[], li: number) => `ln_${this.version}_${ln.key}_${li}`)
}
.width('100%')
.height(this.groupH(ln))
.alignItems(VerticalAlign.Top)
}
}, (ln: FbCardTlLine) => ln.key)
}, (ln: FbCardTlLine) => `${this.version}_${ln.key}`)
}
.width('100%')
.height('100%')
@@ -371,7 +375,7 @@ struct FbCard4x4 {
.textAlign(TextAlign.End)
.padding({ right: 3 })
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
}, (h: number) => `h${h}`)
}, (h: number) => `h_${this.version}_${h}`)
}
.width(GUTTER_VP)
.height(this.contentH())
@@ -486,7 +490,7 @@ struct FbCard4x4 {
this.listRow(item)
}
.width('100%')
}, (item: FbCardListRow) => item.key)
}, (item: FbCardListRow) => `row_${this.version}_${item.key}`)
}
.width('100%')
.layoutWeight(1)
+9 -7
View File
@@ -51,6 +51,8 @@ struct FbCard6x4 {
@LocalStorageProp('viewStartHour') viewStartHour: number = 8;
@LocalStorageProp('viewEndHour') viewEndHour: number = 18;
@LocalStorageProp('nowRatio') nowRatio: number = -1;
/* 🔴 v89:推送版本号 —— 所有 ForEach 的 key 必须带前缀(原因见 FbCardData.version)。 */
@LocalStorageProp('version') version: string = '';
/** 小时刻度(含起点不含终点) */
private hours(): number[] {
@@ -236,7 +238,7 @@ struct FbCard6x4 {
.padding({ left: 5, right: 5 })
.borderRadius(5)
.backgroundColor(a.color)
}, (a: FbCardListRow, idx: number) => `ad_${idx}_${a.key}`)
}, (a: FbCardListRow, idx: number) => `ad_${this.version}_${idx}_${a.key}`)
}
.width('100%')
.padding({ bottom: 3 })
@@ -252,7 +254,7 @@ struct FbCard6x4 {
.height(HOUR_VP)
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
.hitTestBehavior(HitTestMode.None)
}, (h: number) => `gd${h}`)
}, (h: number) => `gd_${this.version}_${h}`)
}
.width('100%')
.height('100%')
@@ -299,19 +301,19 @@ struct FbCard6x4 {
.clip(true)
.width('100%')
.height(b.heightVp < MIN_BLOCK_VP ? MIN_BLOCK_VP : b.heightVp)
}, (b: FbCardTlBlock, bi: number) => `b_${b.key}_${bi}`)
}, (b: FbCardTlBlock, bi: number) => `b_${this.version}_${b.key}_${bi}`)
}
.layoutWeight(1)
.height('100%')
.padding({ right: 2 })
.clip(true)
}, (lane: FbCardTlBlock[], li: number) => `ln_${ln.key}_${li}`)
}, (lane: FbCardTlBlock[], li: number) => `ln_${this.version}_${ln.key}_${li}`)
}
.width('100%')
.height(this.groupH(ln))
.alignItems(VerticalAlign.Top)
}
}, (ln: FbCardTlLine) => ln.key)
}, (ln: FbCardTlLine) => `${this.version}_${ln.key}`)
}
.width('100%')
.height('100%')
@@ -368,7 +370,7 @@ struct FbCard6x4 {
.textAlign(TextAlign.End)
.padding({ right: 3 })
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
}, (h: number) => `h${h}`)
}, (h: number) => `h_${this.version}_${h}`)
}
.width(GUTTER_VP)
.height(this.contentH())
@@ -483,7 +485,7 @@ struct FbCard6x4 {
this.listRow(item)
}
.width('100%')
}, (item: FbCardListRow) => item.key)
}, (item: FbCardListRow) => `row_${this.version}_${item.key}`)
}
.width('100%')
.layoutWeight(1)