diff --git a/entry/src/main/ets/data/FbCardData.ets b/entry/src/main/ets/data/FbCardData.ets index 8600ba2..5eb0f01 100644 --- a/entry/src/main/ets/data/FbCardData.ets +++ b/entry/src/main/ets/data/FbCardData.ets @@ -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; diff --git a/entry/src/main/ets/pages/card/FbCard2x4.ets b/entry/src/main/ets/pages/card/FbCard2x4.ets index 3dc1335..ec0f148 100644 --- a/entry/src/main/ets/pages/card/FbCard2x4.ets +++ b/entry/src/main/ets/pages/card/FbCard2x4.ets @@ -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) diff --git a/entry/src/main/ets/pages/card/FbCard4x4.ets b/entry/src/main/ets/pages/card/FbCard4x4.ets index fbc81e0..c5ce61a 100644 --- a/entry/src/main/ets/pages/card/FbCard4x4.ets +++ b/entry/src/main/ets/pages/card/FbCard4x4.ets @@ -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) diff --git a/entry/src/main/ets/pages/card/FbCard6x4.ets b/entry/src/main/ets/pages/card/FbCard6x4.ets index 1bd721f..f9cb4bd 100644 --- a/entry/src/main/ets/pages/card/FbCard6x4.ets +++ b/entry/src/main/ets/pages/card/FbCard6x4.ets @@ -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)