Files
SyncCalendar/entry/src/main/ets/pages/widget/Widget2x2.ets
T
laoyang c4dc27ef3a 0.0.8:卡片整卡可点 —— 点空白处也能进 App 并定位到当天
用户反馈:卡片的空白区域点了没反应,只有落在日程/文字上才跳转。
期望:点卡片**任何位置**都进入 App 并**定位到卡片当前显示的那一天**。

实现(4 张卡片:2x2 / 2x4 / 4x4 / 6x4 一致处理):
1. 根容器加 `.onClick(() => this.openApp())` → **整卡可点**(含留白);
2. `openApp()` 携带 `openDate` 深链参数,值为卡片数据里的 `selectedDate`
   (该字段早已在 CardData 中维护:CardDataService.ets:194 = 卡片当前显示日 0 点毫秒);
3. **传参必须转字符串**:`params: { openDate: `${this.selectedDate}` }`。
   ⚠️ 依据 4x4 原有注释:param 的数值按 **int32** 传递,13 位毫秒时间戳会溢出成
   2147483647(曾导致进 App 后定位到 1970)。2x2/4x2 原本传的是 number → 已修正为字符串。
4. **移除内部原有的 openApp 点击**(共 13 处:4x2 四、4x4 四、6x4 五),
   避免"子区域 + 根容器"双重触发同一动作。

关于事件冒泡(重要,避免误改):
- ArkUI 的 `onClick` 是**非冒泡**事件,父子组件同绑时**子组件优先**,同一时刻只有一个响应
  (华为官方论坛结论)。因此:
  · 根容器整卡可点**不会**抢走内部 ‹ › 今 + 按钮的点击;
  · **无需** `stopPropagation`(ClickEvent 上也**没有**这个方法——它只在
    MouseEvent / TouchEvent 上,实测编译报错已验证)。
- 内部原有的 4x4/6x4 注释写"兄弟节点布局不冒泡"是对的;本次统一补上说明。

验证:
- 编译通过(BUILD SUCCESSFUL)。
- 四卡一致性核验:每卡 openApp 点击点=1(仅根容器)、根容器=1、selectedDate 声明=1、
  openDate 字符串传参=1。
- 结构完整性:花括号配平(26/26、53/53、228/228、228/228),编译无语法错误。

⚠️ 未验证(待真机):实际点击留白是否跳转、是否正确定位到所显示的那一天;
以及点 ‹ › 今 + 是否**不会**连带打开 App(依赖上述"子组件优先"结论,需实测确认)。
2026-10-14 22:45:51 +08:00

108 lines
3.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// entry/src/main/ets/pages/widget/Widget2x2.ets
// 2x2 服务卡片:突出今天的日期(年月日 / 星期 / 农历)+ 今日日程条数;点击卡片打开 App,右上角 + 直接添加日程
let storage2x2 = new LocalStorage();
@Entry(storage2x2)
@Component
struct Widget2x2Card {
@LocalStorageProp('eventsJson') eventsJson: string = '[]';
@LocalStorageProp('dateText') dateText: string = '';
@LocalStorageProp('lunarText') lunarText: string = '';
@LocalStorageProp('dateMd') dateMd: string = '';
@LocalStorageProp('weekday') weekday: string = '';
@LocalStorageProp('todayCount') todayCount: number = 0;
/** 卡片当前显示的那一天 0 点毫秒 —— 点卡片进 App 时定位到这一天 */
@LocalStorageProp('selectedDate') selectedDate: number = 0;
/** 右上角添加按钮:拉起 App 直接进入新建日程页。
* ⭐ 无需阻止冒泡:ArkUI 的 `onClick` 是**非冒泡**事件,父子同绑时**子组件优先**,
* 故点 + 不会连带触发根容器的"打开首页"。 */
@Builder
addButton() {
Button() {
Text('+')
.fontSize(20)
.fontWeight(FontWeight.Medium)
.fontColor('#FFFFFF')
}
.width(30)
.height(30)
.borderRadius(15)
.padding(0)
.backgroundColor('#007DFF')
.onClick(() => {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { widgetAction: 'add' }
});
})
}
/** 打开 App 并**定位到卡片当前显示的那一天**(用户可能已翻到其他日期) */
private openApp(): void {
postCardAction(this, {
action: 'router',
abilityName: 'EntryAbility',
params: { openDate: `${this.selectedDate}` }
});
}
build() {
Column({ space: 6 }) {
// 顶部:大日期 + 添加按钮
Row({ space: 6 }) {
Column({ space: 2 }) {
Text(this.dateMd === '' ? this.dateText : this.dateMd)
.fontSize(15)
.fontWeight(FontWeight.Bold)
.fontColor('#1A1A1A')
.maxLines(1)
Text(`${this.weekday === '' ? '' : this.weekday + ' '}${this.lunarText}`)
.fontSize(11)
.fontColor('#8A8A8A')
.maxLines(1)
}
.layoutWeight(1)
.alignItems(HorizontalAlign.Start)
this.addButton()
}
.width('100%')
Divider()
.strokeWidth(0.5)
.color('#E5E5E5')
// 今日日程条数(占据剩余空间,垂直居中)
Row({ space: 8 }) {
Text(`${this.todayCount}`)
.fontSize(40)
.fontWeight(FontWeight.Bold)
.fontColor('#007DFF')
Column({ space: 2 }) {
Row({ space: 4 }) {
Text('今日日程')
.fontSize(12)
.fontColor('#1A1A1A')
}
Text(this.todayCount === 0 ? '点击添加' : '点击查看')
.fontSize(10)
.fontColor('#8A8A8A')
}
.alignItems(HorizontalAlign.Start)
}
.width('100%')
.layoutWeight(1)
.alignItems(VerticalAlign.Center)
}
.width('100%')
.height('100%')
.padding(14)
.backgroundColor('#FFFFFF')
.borderRadius(16)
// ⭐ 整卡可点:空白处也能进 App 并定位到当前显示日(原来只有日期区/条数区可点)
.onClick(() => this.openApp())
}
}