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; nowRatio: number = -1;
/** `15:40` */ /** `15:40` */
nowLabel: string = ''; 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.updatedAt = clockText();
out.nowLabel = out.updatedAt; out.nowLabel = out.updatedAt;
out.dayOffset = dayOffset; out.dayOffset = dayOffset;
/* 🔴 v89:每次推送一个新版本号,卡片侧 ForEach key 全部带上前缀 ——
不带的话翻页/刷新时 key 撞车,时间轴整层不重绘(文件头 version 注释)。 */
out.version = Date.now().toString();
out.isToday = dayOffset === 0; out.isToday = dayOffset === 0;
out.nowRatio = out.isToday ? (now.getHours() * 60 + now.getMinutes()) / 1440 : -1; 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('lunarText') lunarText: string = '';
@LocalStorageProp('dayCount') dayCount: number = 0; @LocalStorageProp('dayCount') dayCount: number = 0;
@LocalStorageProp('upcomingJson') upcomingJson: string = '[]'; @LocalStorageProp('upcomingJson') upcomingJson: string = '[]';
/* 🔴 v89:推送版本号 —— ForEach key 要带前缀(原因见 FbCardData.version)。 */
@LocalStorageProp('version') version: string = '';
@LocalStorageProp('selectedDate') selectedDate: number = 0; @LocalStorageProp('selectedDate') selectedDate: number = 0;
/** 副标题:`星期二 九月初一` */ /** 副标题:`星期二 九月初一` */
@@ -206,7 +208,7 @@ struct FbCard2x4 {
Column({ space: 6 }) { Column({ space: 6 }) {
ForEach(this.upcoming(), (item: FbCardUp, idx: number) => { ForEach(this.upcoming(), (item: FbCardUp, idx: number) => {
this.upcomingRow(item) 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%') .width('100%')
.layoutWeight(1) .layoutWeight(1)
+11 -7
View File
@@ -54,6 +54,10 @@ struct FbCard4x4 {
@LocalStorageProp('viewStartHour') viewStartHour: number = 8; @LocalStorageProp('viewStartHour') viewStartHour: number = 8;
@LocalStorageProp('viewEndHour') viewEndHour: number = 18; @LocalStorageProp('viewEndHour') viewEndHour: number = 18;
@LocalStorageProp('nowRatio') nowRatio: number = -1; @LocalStorageProp('nowRatio') nowRatio: number = -1;
/* 🔴 v89:推送版本号 —— 所有 ForEach 的 key 必须带前缀(原因见 FbCardData.version)。
不带的话翻到下一天时 `gap0/g0` 这些 key 一模一样,ArkUI ForEach 复用旧组件,
时间轴整层显示旧一天的色块和空白(真机实测踩到)。 */
@LocalStorageProp('version') version: string = '';
/** 小时刻度(含起点不含终点) */ /** 小时刻度(含起点不含终点) */
private hours(): number[] { private hours(): number[] {
@@ -239,7 +243,7 @@ struct FbCard4x4 {
.padding({ left: 5, right: 5 }) .padding({ left: 5, right: 5 })
.borderRadius(5) .borderRadius(5)
.backgroundColor(a.color) .backgroundColor(a.color)
}, (a: FbCardListRow, idx: number) => `ad_${idx}_${a.key}`) }, (a: FbCardListRow, idx: number) => `ad_${this.version}_${idx}_${a.key}`)
} }
.width('100%') .width('100%')
.padding({ bottom: 3 }) .padding({ bottom: 3 })
@@ -255,7 +259,7 @@ struct FbCard4x4 {
.height(HOUR_VP) .height(HOUR_VP)
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } }) .border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
.hitTestBehavior(HitTestMode.None) .hitTestBehavior(HitTestMode.None)
}, (h: number) => `gd${h}`) }, (h: number) => `gd_${this.version}_${h}`)
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
@@ -302,19 +306,19 @@ struct FbCard4x4 {
.clip(true) .clip(true)
.width('100%') .width('100%')
.height(b.heightVp < MIN_BLOCK_VP ? MIN_BLOCK_VP : b.heightVp) .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) .layoutWeight(1)
.height('100%') .height('100%')
.padding({ right: 2 }) .padding({ right: 2 })
.clip(true) .clip(true)
}, (lane: FbCardTlBlock[], li: number) => `ln_${ln.key}_${li}`) }, (lane: FbCardTlBlock[], li: number) => `ln_${this.version}_${ln.key}_${li}`)
} }
.width('100%') .width('100%')
.height(this.groupH(ln)) .height(this.groupH(ln))
.alignItems(VerticalAlign.Top) .alignItems(VerticalAlign.Top)
} }
}, (ln: FbCardTlLine) => ln.key) }, (ln: FbCardTlLine) => `${this.version}_${ln.key}`)
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
@@ -371,7 +375,7 @@ struct FbCard4x4 {
.textAlign(TextAlign.End) .textAlign(TextAlign.End)
.padding({ right: 3 }) .padding({ right: 3 })
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } }) .border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
}, (h: number) => `h${h}`) }, (h: number) => `h_${this.version}_${h}`)
} }
.width(GUTTER_VP) .width(GUTTER_VP)
.height(this.contentH()) .height(this.contentH())
@@ -486,7 +490,7 @@ struct FbCard4x4 {
this.listRow(item) this.listRow(item)
} }
.width('100%') .width('100%')
}, (item: FbCardListRow) => item.key) }, (item: FbCardListRow) => `row_${this.version}_${item.key}`)
} }
.width('100%') .width('100%')
.layoutWeight(1) .layoutWeight(1)
+9 -7
View File
@@ -51,6 +51,8 @@ struct FbCard6x4 {
@LocalStorageProp('viewStartHour') viewStartHour: number = 8; @LocalStorageProp('viewStartHour') viewStartHour: number = 8;
@LocalStorageProp('viewEndHour') viewEndHour: number = 18; @LocalStorageProp('viewEndHour') viewEndHour: number = 18;
@LocalStorageProp('nowRatio') nowRatio: number = -1; @LocalStorageProp('nowRatio') nowRatio: number = -1;
/* 🔴 v89:推送版本号 —— 所有 ForEach 的 key 必须带前缀(原因见 FbCardData.version)。 */
@LocalStorageProp('version') version: string = '';
/** 小时刻度(含起点不含终点) */ /** 小时刻度(含起点不含终点) */
private hours(): number[] { private hours(): number[] {
@@ -236,7 +238,7 @@ struct FbCard6x4 {
.padding({ left: 5, right: 5 }) .padding({ left: 5, right: 5 })
.borderRadius(5) .borderRadius(5)
.backgroundColor(a.color) .backgroundColor(a.color)
}, (a: FbCardListRow, idx: number) => `ad_${idx}_${a.key}`) }, (a: FbCardListRow, idx: number) => `ad_${this.version}_${idx}_${a.key}`)
} }
.width('100%') .width('100%')
.padding({ bottom: 3 }) .padding({ bottom: 3 })
@@ -252,7 +254,7 @@ struct FbCard6x4 {
.height(HOUR_VP) .height(HOUR_VP)
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } }) .border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
.hitTestBehavior(HitTestMode.None) .hitTestBehavior(HitTestMode.None)
}, (h: number) => `gd${h}`) }, (h: number) => `gd_${this.version}_${h}`)
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
@@ -299,19 +301,19 @@ struct FbCard6x4 {
.clip(true) .clip(true)
.width('100%') .width('100%')
.height(b.heightVp < MIN_BLOCK_VP ? MIN_BLOCK_VP : b.heightVp) .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) .layoutWeight(1)
.height('100%') .height('100%')
.padding({ right: 2 }) .padding({ right: 2 })
.clip(true) .clip(true)
}, (lane: FbCardTlBlock[], li: number) => `ln_${ln.key}_${li}`) }, (lane: FbCardTlBlock[], li: number) => `ln_${this.version}_${ln.key}_${li}`)
} }
.width('100%') .width('100%')
.height(this.groupH(ln)) .height(this.groupH(ln))
.alignItems(VerticalAlign.Top) .alignItems(VerticalAlign.Top)
} }
}, (ln: FbCardTlLine) => ln.key) }, (ln: FbCardTlLine) => `${this.version}_${ln.key}`)
} }
.width('100%') .width('100%')
.height('100%') .height('100%')
@@ -368,7 +370,7 @@ struct FbCard6x4 {
.textAlign(TextAlign.End) .textAlign(TextAlign.End)
.padding({ right: 3 }) .padding({ right: 3 })
.border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } }) .border({ width: { bottom: 0.5 }, color: { bottom: '#14000000' } })
}, (h: number) => `h${h}`) }, (h: number) => `h_${this.version}_${h}`)
} }
.width(GUTTER_VP) .width(GUTTER_VP)
.height(this.contentH()) .height(this.contentH())
@@ -483,7 +485,7 @@ struct FbCard6x4 {
this.listRow(item) this.listRow(item)
} }
.width('100%') .width('100%')
}, (item: FbCardListRow) => item.key) }, (item: FbCardListRow) => `row_${this.version}_${item.key}`)
} }
.width('100%') .width('100%')
.layoutWeight(1) .layoutWeight(1)