【听见课堂 HarmonyOS NEXT 实战系列 46】不接系统日历,也能做一周任务视图

任务中心需要“一周视图”,并不意味着应用必须先申请系统日历权限。听见课堂的 P09 页面只围绕本地已确认任务生成周历:Service 统一计算日期键,ArkUI 只负责展示和组合筛选,系统日历里不会被静默写入任何事件。

本地任务快照生成周一到周日七天视图的完整数据链

一、先确认需求:查看任务,不等于写入系统日历

当前目标是让用户快速判断本周哪天有任务、哪天存在逾期项,并能点击某天缩小列表范围。数据已经保存在应用自己的 RelationalStore 中,因此无需把同一份任务复制到系统日历。

只有当产品要创建系统事件、读取用户既有日程或与其他日历应用协同时,才需要评估 Calendar Kit、权限说明、拒绝路径和数据同步冲突。

二、周历的数据源必须是正式任务快照

getTaskCenterSnapshot() 先过滤 confirmed=true 的任务,再解析截止时间、过期状态和日期键。候选任务不会因为带有“明天”之类文本就出现在周历中。

这使周历继续服从前文建立的人工确认边界:自动规则只能提出建议,正式任务视图只消费用户确认后的 canonical data。

三、为什么要先固定同一个 nowMillis

Service 在一次快照中只调用一次 Date.now(),再把相同的 nowMillis 传给截止时间解析、是否逾期、日期分组和周历构建。

如果每个步骤各自取时间,恰好跨过午夜时可能出现“列表认为今天、周历认为昨天”的短暂不一致。固定时间基准是一个成本很低但很重要的确定性设计。

四、周一作为一周起点如何计算

startOfWeek() 先把本地时间归零到 00:00,再根据 getDay() 计算偏移。JavaScript 中周日是 0,因此周日需要回退 6 天,其余日期使用 1 - weekday 回到周一。

const weekday: number = value.getDay();
const offset: number = weekday === 0 ? -6 : 1 - weekday;
return value.getTime() + offset * DAY_MILLIS;

这段规则明确选择“周一到周日”,与页面中文习惯保持一致。

五、七天不是七个硬编码按钮

buildWeekDays() 从周一起点循环 7 次,为每一天生成 TaskCalendarDay。模型包含 dateKey、星期标签、日期数字、是否今天、任务数和过期数。

页面只是 ForEach(calendarDays),不用维护七份重复状态,也不会把业务统计散落进 Builder。

六、dateKey 是列表与周历的连接键

任务在映射为 TaskCenterItem 时就得到形如 YYYY-MM-DDdateKey。周历生成每一天时也调用同一个 TaskDateResolver.dateKey()

两边用相同规则形成稳定连接,避免页面拿“周一”“今天”这类展示文案做数据匹配。

七、一天的任务数和过期数怎样聚合

每个日历格先筛选 item.dateKey === dateKey 的任务,再分别计算总数和 overdue=true 的数量。

const dayItems = items.filter((item: TaskCenterItem) => item.dateKey === dateKey);
const taskCount = dayItems.length;
const overdueCount = dayItems.filter((item: TaskCenterItem) => item.overdue).length;

统计来自同一批列表项,因此不会出现周历角标和任务列表各算一套口径。

八、今天标识不能只依赖颜色

P09 用边框和颜色突出今天,同时在格子内部显示“今天”,并提供完整的 accessibilityText:星期、日期、任务数、过期数和当前是否选中。

颜色只是视觉增强,文字与无障碍语义才是状态信息的可靠载体。

周历日期键、任务计数、过期计数与组合筛选的状态关系

九、点击日期后如何组合筛选

selectTaskCalendarDay() 保存所选 dateKey,并把日期筛选切换为“今天”或“本周”。真正的列表过滤同时检查状态、日期分组和精确日期键。

因此“已过期 + 周三”会取两者交集,而不是后一次点击覆盖前一次条件。

十、为什么本周筛选还要包含今天

任务的 dateGroup 把当天标记为“今天”,本周其他日期标记为“本周”。所以页面在选择“本周”时显式兼容 dateGroup === '今天'

这是展示分组与筛选集合不同的典型例子:今天既是独立快捷分组,也属于自然意义上的本周。

十一、空态要解释是“组合后为空”

某天可能有任务,但叠加“已完成”状态后没有结果。页面显示“所选日期暂无符合当前状态筛选的任务”,而不是笼统说“没有任务”。

准确空态能帮助用户理解数据没有丢失,只是当前筛选组合没有命中。

十二、手机和大屏共享同一份周历数据

手机端周历横向滚动,每格固定宽度;大屏端七格按可用空间等分。两种布局都消费同一个 calendarDays,选择逻辑和筛选逻辑没有分叉。

响应式差异留在 ArkUI 布局层,日期计算留在 Resolver,符合页面与业务规则分离的原则。

十三、未知截止时间为什么不进入具体日期格

无法解析的截止文本会得到 dueAtMillis=0 和空 dateKey,仍可出现在任务列表的“未指定”分组,但不会被硬塞进本周任意一天。

这比猜一个日期更诚实,也提醒后续产品补充人工修订入口。

十四、当前实现有哪些时间边界

周历以本地时区和固定 24 小时毫秒数推进。对当前中国本地课堂场景可用,但若未来支持存在夏令时切换的地区,应改为逐日操作本地 Date,避免跨 DST 时产生小时偏移。

当前周视图也只有本周,没有前后周翻页;这属于产品范围,不应描述为完整日历系统。

十五、什么时候才值得接入 Calendar Kit

当需求升级为“把确认任务写入系统日历”“读取冲突日程”“跨应用提醒”时,才进入 Calendar Kit 方案评估。届时必须补充权限申请时机、拒绝后继续使用本地周历、重复事件幂等键和撤销同步策略。

在此之前,本地周历更简单、更少权限,也更符合课堂隐私数据最小化原则。

十六、总结

一周任务视图的核心不是系统日历 API,而是统一时间基准、稳定 dateKey、明确的周起点和可组合筛选。听见课堂用本地 Resolver 与任务快照完成七天映射,让手机和大屏共享业务语义,同时保留未来接入 Calendar Kit 的清晰边界。

下一篇继续分析:完成与撤销完成为什么不能只是一个没有数据门禁的 Toggle。

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐