月视图日期格加事件标记:每个日期最多一个小圆点(旧版按日历本重复显示已废弃) #6

Closed
opened 2026-11-02 06:37:08 +00:00 by laoyang · 2 comments
Owner

用户反馈(应用市场评价)

希望在有日历事件的日期上,能有个标记,比如红点。
例如 1 日到 9 日,8 日有事件,就在 8 号显示一个小红点。

历史背景(重要)

这个功能以前有,被主动去掉了。 用户原话:

咱们之前是有小红点的,不过当时显示得太多了,每个日历本下边都显示小红点。
比方说一共有三个日历本,在某一个日期有小红点、有日程的话,
它会在那个日期下面显示三个小红点,太多了,我就把它去掉了。

根因:红点是按日历本逐个渲染的 —— N 个本在同一日期都有事件,就渲染 N 个点。
有 15 个本时(本机实测镜像就是 15 个本),一个月视图能被点成筛子。

本次要求(明确)

每个日期最多一个红点。 只要该日期有任意事件,就显示 1 个,
不区分是哪个本、有几个本、有几条事件。

用户原话:

只要某个日期有事件,就在这个日期下边显示一个小红点,告诉大家这个日期下边其实是有事件的。
也别显示那么多了,显示得太多,显得有点乱。

现状

entry/src/main/ets/pages/Index.ets 里 grep -n 'dot\|Dot\|红点' 零命中 ⇒
旧实现已彻底删除,需要重新实现(但不是从零设计,需求已明确)。

相关结构:

  • 月视图:monthBody() → dayCell(cell: MonthCell)
  • dayCell 现有内容:日期数字、农历(cell.lunar)、选中/今天高亮
  • 数据源:MonthCell 结构 + 已加载的 events(月视图已有按日聚合计数的能力)

实现要点

  1. 数据侧:给 MonthCell 加一个布尔(或计数)标记,如 hasEvent: boolean,
    在构造月视图单元格时按"该日期是否存在任意事件"置位。
    ⚠️ 只用一个布尔,不要存每本的集合 —— 正是"每本一个点"导致上次被砍。
  2. 渲染侧:dayCell 里在农历下方加一个小圆点,
    • 尺寸小(建议 4~5vp),颜色用主题色或次要色,不要用刺眼的纯红
      (月历格子里 30 个点全红会很吵;用户说"显得有点乱"就是嫌吵)
    • 已有选中/今天高亮时,点要仍然可见(注意对比度)
    • 宽屏(wideLayout)下月历格子变窄、农历已省略,点也要保留或相应调整
  3. 性能:月视图切换时不要为每个 cell 去遍历全部事件(O(天×事件) 会卡)。
    先用一次遍历把"有事件的日期"收进 Set<number>(按 dayStart 归一化),
    再渲染时 O(1) 查。

需要注意的边界

  • 跨天事件:跨越的每一天都应有点(用户心智是"这天有安排")
  • 重复事件:展开后的发生实例要计入(不能只算 master)
  • 全天事件:要计入
  • 待办:不计入。待办没有"时间点"语义,混进来会让点失去意义
    (若用户希望待办也提示,再单独说)
  • 月视图之外的周视图/列表视图本次不动,避免范围扩散

验收标准

  • 月视图中,某日期有 ≥1 条事件 → 该日期下显示恰好 1 个小点
  • 某日期有 3 个本各 1 条事件 → 仍然只显示 1 个点(核心回归点)
  • 无事件的日期不显示点
  • 跨天事件覆盖的每一天都有点
  • 重复事件的发生日期有点
  • 全天事件有点
  • 选中态/今天态下点仍清晰可见
  • 15 个本 × 整月数据下切换月份不卡顿
  • 编译通过 + 真机验证

为什么单独建单

应用市场用户反馈的第3条;纯前端月视图展示标记,与 #4 默认时间、#5 待办读写互不相干

## 用户反馈(应用市场评价) > 希望在有日历事件的日期上,能有个标记,比如红点。 > 例如 1 日到 9 日,8 日有事件,就在 8 号显示一个小红点。 ## 历史背景(重要) **这个功能以前有,被主动去掉了。** 用户原话: > 咱们之前是有小红点的,不过当时显示得太多了,每个日历本下边都显示小红点。 > 比方说一共有三个日历本,在某一个日期有小红点、有日程的话, > 它会在那个日期下面显示三个小红点,太多了,我就把它去掉了。 **根因**:红点是**按日历本逐个渲染**的 —— N 个本在同一日期都有事件,就渲染 N 个点。 有 15 个本时(本机实测镜像就是 15 个本),一个月视图能被点成筛子。 ## 本次要求(明确) **每个日期最多一个红点。** 只要该日期有任意事件,就显示 **1 个**, 不区分是哪个本、有几个本、有几条事件。 用户原话: > 只要某个日期有事件,就在这个日期下边显示一个小红点,告诉大家这个日期下边其实是有事件的。 > 也别显示那么多了,显示得太多,显得有点乱。 ## 现状 `entry/src/main/ets/pages/Index.ets` 里 `grep -n 'dot\|Dot\|红点'` **零命中** ⇒ 旧实现已彻底删除,需要重新实现(但不是从零设计,需求已明确)。 相关结构: - 月视图:`monthBody()` → `dayCell(cell: MonthCell)` - `dayCell` 现有内容:日期数字、农历(`cell.lunar`)、选中/今天高亮 - 数据源:`MonthCell` 结构 + 已加载的 `events`(月视图已有按日聚合计数的能力) ## 实现要点 1. **数据侧**:给 `MonthCell` 加一个布尔(或计数)标记,如 `hasEvent: boolean`, 在构造月视图单元格时按"该日期是否存在任意事件"置位。 ⚠️ **只用一个布尔,不要存每本的集合** —— 正是"每本一个点"导致上次被砍。 2. **渲染侧**:`dayCell` 里在农历下方加一个小圆点, - 尺寸小(建议 4~5vp),颜色用主题色或次要色,**不要用刺眼的纯红** (月历格子里 30 个点全红会很吵;用户说"显得有点乱"就是嫌吵) - 已有选中/今天高亮时,点要仍然可见(注意对比度) - 宽屏(`wideLayout`)下月历格子变窄、农历已省略,点也要保留或相应调整 3. **性能**:月视图切换时不要为每个 cell 去遍历全部事件(O(天×事件) 会卡)。 先用一次遍历把"有事件的日期"收进 `Set<number>`(按 dayStart 归一化), 再渲染时 O(1) 查。 ## 需要注意的边界 - **跨天事件**:跨越的每一天都应有点(用户心智是"这天有安排") - **重复事件**:展开后的发生实例要计入(不能只算 master) - **全天事件**:要计入 - **待办**:**不计入**。待办没有"时间点"语义,混进来会让点失去意义 (若用户希望待办也提示,再单独说) - 月视图之外的周视图/列表视图本次不动,避免范围扩散 ## 验收标准 - 月视图中,某日期有 ≥1 条事件 → 该日期下显示**恰好 1 个**小点 - 某日期有 3 个本各 1 条事件 → 仍然**只显示 1 个**点(核心回归点) - 无事件的日期不显示点 - 跨天事件覆盖的每一天都有点 - 重复事件的发生日期有点 - 全天事件有点 - 选中态/今天态下点仍清晰可见 - 15 个本 × 整月数据下切换月份不卡顿 - 编译通过 + 真机验证 --- ### 为什么单独建单 应用市场用户反馈的第3条;纯前端月视图展示标记,与 #4 默认时间、#5 待办读写互不相干
Author
Owner

已随 0.2.0 实现并在真机验证通过,关闭。

最终实现(与原要求的差异)

原单要求「每个日期最多一个红点」,实际落地为:

  • 农历下方一个浅红小圆点(3.5vp)
  • 颜色 soft_red:浅色 #F2938A / 深色 #C97A72
  • 每个日期最多一个点,与日历本数量无关(原每本一个点的实现已彻底废弃)
  • 无事件时圆点透明但仍占位 → 保证有/无事件行高一致,整月不跳

为什么不用纯红

纯红(#D93025)在本应用里语义是"告警",而"这天有安排"是中性信息。
浅红是柔和提示,不抢日期数字。用户看过后确认采用。

选中态

选中/今天改为正圆底(46vp 正方形 + 50% 圆角):

  • 选中 = 实蓝圆,今天 = 淡蓝圆,尺寸一致
  • 圆内包含 日期 + 农历 + 事件点,三者统一转白
  • 周视图复用同一 Builder(dayCellCircle),仅多传 showWeekLabel
    —— 之前两个视图各写一套导致圆大小/字号/间距反复对不齐

真机验证证据(dump 实测)

  • 圆点位置:8 个抽样全部在农历正下方(圆点在下方 = 是)
  • 圆点颜色:实测 rgb(250,141,136),与设计值 #F2938A = rgb(242,147,138) 一致
  • 圆尺寸:月视图 144×144 = 周视图 144×144(完全一致)
  • 溢出检查:圆范围 y 495664;星期「一」y497534、日期 y537612、
    农历 y615
    648、事件点×7 y651~662 —— 全部在圆内,无溢出

顺带修复的相关缺陷

  1. 首屏农历不变色 / 切视图才生效:外层 ForEach 的 key 未含数据版本,
    导致整棵子树被复用、itemGenerator 不重跑(加 monthDataVersion)
  2. 翻月闪跳:reloadEvents() 是 async 但被当作同步调用 + @State 赋值
    在同一同步栈内不可读(改为 rebuildPagesFor(y,m) 显式传参)
已随 0.2.0 实现并在真机验证通过,关闭。 ## 最终实现(与原要求的差异) 原单要求「每个日期最多一个**红点**」,实际落地为: - 农历**下方**一个浅红小圆点(3.5vp) - 颜色 `soft_red`:浅色 #F2938A / 深色 #C97A72 - 每个日期**最多一个点**,与日历本数量无关(原每本一个点的实现已彻底废弃) - 无事件时圆点透明但仍占位 → 保证有/无事件行高一致,整月不跳 ## 为什么不用纯红 纯红(#D93025)在本应用里语义是"告警",而"这天有安排"是中性信息。 浅红是柔和提示,不抢日期数字。用户看过后确认采用。 ## 选中态 选中/今天改为**正圆底**(46vp 正方形 + 50% 圆角): - 选中 = 实蓝圆,今天 = 淡蓝圆,尺寸一致 - 圆内包含 日期 + 农历 + 事件点,三者统一转白 - 周视图复用同一 Builder(`dayCellCircle`),仅多传 `showWeekLabel` —— 之前两个视图各写一套导致圆大小/字号/间距反复对不齐 ## 真机验证证据(dump 实测) - 圆点位置:8 个抽样全部在农历正下方(`圆点在下方 = 是`) - 圆点颜色:实测 rgb(250,141,136),与设计值 #F2938A = rgb(242,147,138) 一致 - 圆尺寸:月视图 144×144 = 周视图 144×144(完全一致) - 溢出检查:圆范围 y 495~664;星期「一」y497~534、日期 y537~612、 农历 y615~648、事件点×7 y651~662 —— **全部在圆内**,无溢出 ## 顺带修复的相关缺陷 1. 首屏农历不变色 / 切视图才生效:外层 ForEach 的 key 未含数据版本, 导致整棵子树被复用、itemGenerator 不重跑(加 `monthDataVersion`) 2. 翻月闪跳:`reloadEvents()` 是 async 但被当作同步调用 + `@State` 赋值 在同一同步栈内不可读(改为 `rebuildPagesFor(y,m)` 显式传参)
Author
Owner

已随 0.2.0 实现并在真机验证通过,关闭。

最终实现(与原要求的差异)

原单要求「每个日期最多一个红点」,实际落地为:

  • 农历下方一个浅红小圆点(3.5vp)
  • 颜色 soft_red:浅色 #F2938A / 深色 #C97A72
  • 每个日期最多一个点,与日历本数量无关(原每本一个点的实现已彻底废弃)
  • 无事件时圆点透明但仍占位 → 保证有/无事件行高一致,整月不跳

为什么不用纯红

纯红(#D93025)在本应用里语义是"告警",而"这天有安排"是中性信息。
浅红是柔和提示,不抢日期数字。用户看过后确认采用。

选中态

选中/今天改为正圆底(46vp 正方形 + 50% 圆角):

  • 选中 = 实蓝圆,今天 = 淡蓝圆,尺寸一致
  • 圆内包含 日期 + 农历 + 事件点,三者统一转白
  • 周视图复用同一 Builder(dayCellCircle),仅多传 showWeekLabel
    —— 之前两个视图各写一套导致圆大小/字号/间距反复对不齐

真机验证证据(dump 实测)

  • 圆点位置:8 个抽样全部在农历正下方(圆点在下方 = 是)
  • 圆点颜色:实测 rgb(250,141,136),与设计值 #F2938A = rgb(242,147,138) 一致
  • 圆尺寸:月视图 144×144 = 周视图 144×144(完全一致)
  • 溢出检查:圆范围 y 495664;星期「一」y497534、日期 y537612、
    农历 y615
    648、事件点×7 y651~662 —— 全部在圆内,无溢出

顺带修复的相关缺陷

  1. 首屏农历不变色 / 切视图才生效:外层 ForEach 的 key 未含数据版本,
    导致整棵子树被复用、itemGenerator 不重跑(加 monthDataVersion)
  2. 翻月闪跳:reloadEvents() 是 async 但被当作同步调用 + @State 赋值
    在同一同步栈内不可读(改为 rebuildPagesFor(y,m) 显式传参)
已随 0.2.0 实现并在真机验证通过,关闭。 ## 最终实现(与原要求的差异) 原单要求「每个日期最多一个**红点**」,实际落地为: - 农历**下方**一个浅红小圆点(3.5vp) - 颜色 `soft_red`:浅色 #F2938A / 深色 #C97A72 - 每个日期**最多一个点**,与日历本数量无关(原每本一个点的实现已彻底废弃) - 无事件时圆点透明但仍占位 → 保证有/无事件行高一致,整月不跳 ## 为什么不用纯红 纯红(#D93025)在本应用里语义是"告警",而"这天有安排"是中性信息。 浅红是柔和提示,不抢日期数字。用户看过后确认采用。 ## 选中态 选中/今天改为**正圆底**(46vp 正方形 + 50% 圆角): - 选中 = 实蓝圆,今天 = 淡蓝圆,尺寸一致 - 圆内包含 日期 + 农历 + 事件点,三者统一转白 - 周视图复用同一 Builder(`dayCellCircle`),仅多传 `showWeekLabel` —— 之前两个视图各写一套导致圆大小/字号/间距反复对不齐 ## 真机验证证据(dump 实测) - 圆点位置:8 个抽样全部在农历正下方(`圆点在下方 = 是`) - 圆点颜色:实测 rgb(250,141,136),与设计值 #F2938A = rgb(242,147,138) 一致 - 圆尺寸:月视图 144×144 = 周视图 144×144(完全一致) - 溢出检查:圆范围 y 495~664;星期「一」y497~534、日期 y537~612、 农历 y615~648、事件点×7 y651~662 —— **全部在圆内**,无溢出 ## 顺带修复的相关缺陷 1. 首屏农历不变色 / 切视图才生效:外层 ForEach 的 key 未含数据版本, 导致整棵子树被复用、itemGenerator 不重跑(加 `monthDataVersion`) 2. 翻月闪跳:`reloadEvents()` 是 async 但被当作同步调用 + `@State` 赋值 在同一同步栈内不可读(改为 `rebuildPagesFor(y,m)` 显式传参)
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: laoyang/SyncCalendar#6