
本文深入解析 ImportantDays 项目中统计面板的数据计算逻辑包括getStats()方法的实现、四种统计维度全部/即将/今天/已过的筛选条件、排序策略以及统计数据的 UI 呈现。一、统计面板概述ImportantDays 在两个页面展示统计数据列表页ImportantDayPage顶部统计栏我的页MinePage统计卡片统计维度维度含义颜色全部所有重要日总数灰/红即将即将到来的重要日红/青今天今天到达的重要日青/黄已过已过期的重要日灰二、getStats() 方法getStats():Stats{return{total:this.allDays.length,upcoming:this.getUpcomingDays().length,past:this.getPastDays().length,today:this.getTodayDays().length};}返回Stats接口定义的统计对象exportinterfaceStats{total:number;upcoming:number;past:number;today:number;}三、全部totaltotal:this.allDays.length最简单的统计——直接返回数组长度包含所有重要日无论状态。四、即将到来upcominggetUpcomingDays():ImportantDay[]{returnthis.allDays.filter(dd.isCountdownd.getDaysDiff()0).sort((a,b)a.getDaysDiff()-b.getDaysDiff());}筛选条件d.isCountdownd.getDaysDiff()0条件含义d.isCountdown倒数模式正数模式不算即将到来d.getDaysDiff() 0目标日尚未过去排序策略.sort((a,b)a.getDaysDiff()-b.getDaysDiff())按天数差升序排列——最近到来的排在前面。示例重要日列表 - 妈妈生日倒数还有3天 - 结婚纪念日倒数还有30天 - 旅行计划正数已过10天 - 考试日期倒数已过5天 - 今天会议倒数还有0天 筛选结果isCountdown diff 0 - 今天会议diff0 - 妈妈生日diff3 - 结婚纪念日diff30 排序后 1. 今天会议0天 2. 妈妈生日3天 3. 结婚纪念日30天五、已过pastgetPastDays():ImportantDay[]{returnthis.allDays.filter(dd.getDaysDiff()0).sort((a,b)b.getDaysDiff()-a.getDaysDiff());}筛选条件d.getDaysDiff()0目标日已过去天数差为负不区分倒数/正数模式。排序策略.sort((a,b)b.getDaysDiff()-a.getDaysDiff())按天数差降序排列——刚过去的排在前面-1排在-10前面。示例筛选结果diff 0 - 考试日期diff-5 - 旅行计划diff-10 排序后 1. 考试日期-5天刚过去 2. 旅行计划-10天六、今天todaygetTodayDays():ImportantDay[]{returnthis.allDays.filter(dd.isToday());}筛选条件d.isToday()// 即 d.getDaysDiff() 0目标日就是今天不区分倒数/正数模式。不排序今天的重要日通常很少0-2个不需要排序。七、统计逻辑的关系图allDays全部 / | \ / | \ upcoming today past (正数未来) diff 0 diff 0 diff 0 diff 0 且 倒数 且 正数统计覆盖分析统计维度筛选条件覆盖范围total无所有upcomingisCountdown diff 0倒数模式中未过期的todaydiff 0今天到达的pastdiff 0所有已过期的注意正数模式未过期不在即将中正数模式下diff 0目标日还没到的重要日不在upcoming因为isCountdown false不在past因为diff 0不在today因为diff ! 0只在total中这是合理的设计——正数模式用于纪念已过的日子未到状态不是用户关注的重点。八、需要提醒的重要日getDaysNeedReminder():ImportantDay[]{returnthis.allDays.filter(dd.shouldRemind());}shouldRemind 逻辑shouldRemind():boolean{if(!this.reminderEnabled)returnfalse;constdiffthis.getDaysDiff();returndiff0diffthis.reminderDaysBefore;}条件含义reminderEnabled用户启用了提醒diff 0目标日未过期diff reminderDaysBefore在提醒范围内与即将的关系upcoming: isCountdown diff 0 needReminder: reminderEnabled diff 0 diff reminderDaysBeforeneedReminder是upcoming的子集如果isCountdown true额外要求启用提醒且在提醒范围内。九、统计数据的 UI 呈现列表页统计栏BuilderstatsBar(){Row(){this.statItem(全部,this.manager.getStats().total,#666666)this.statItem(即将,this.manager.getStats().upcoming,#FF6B6B)this.statItem(今天,this.manager.getStats().today,#4ECDC4)this.statItem(已过,this.manager.getStats().past,#999999)}.justifyContent(FlexAlign.SpaceAround)}我的页统计卡片BuilderstatsCard(){Row(){// 全部 - 红色Text(${this.manager.getStats().total}).fontColor(#FF6B6B)// 即将到来 - 青色Text(${this.manager.getStats().upcoming}).fontColor(#4ECDC4)// 今天 - 黄色Text(${this.manager.getStats().today}).fontColor(#F7DC6F)// 已过 - 灰色Text(${this.manager.getStats().past}).fontColor(#999999)}}两个页面的颜色差异统计项列表页颜色我的页颜色全部#666666灰#FF6B6B红即将#FF6B6B红#4ECDC4青今天#4ECDC4青#F7DC6F黄已过#999999灰#999999灰列表页强调即将红色我的页强调全部红色。十、实时更新机制数据变化 → 统计更新用户添加重要日 ↓ manager.addDay(day) ↓ allDays.push(day) → Trace 变化 ↓ triggerRefresh() → refreshNum 变化 ↓ UI 重新渲染 ↓ getStats() 重新调用 ↓ 统计数字更新每次渲染都实时计算getStats()不是缓存结果而是每次 UI 渲染时实时计算// 每次渲染都调用this.manager.getStats().totalthis.manager.getStats().upcomingthis.manager.getStats().todaythis.manager.getStats().past由于重要日数量通常不多几十条实时计算的性能开销可忽略。十一、性能优化方向如果重要日数量很大数百条可以考虑缓存统计结果// 概念性优化TracecachedStats:Stats|nullnull;getStats():Stats{if(!this.cachedStats||this.statsDirty){this.cachedStats{total:this.allDays.length,upcoming:this.getUpcomingDays().length,past:this.getPastDays().length,today:this.getTodayDays().length};this.statsDirtyfalse;}returnthis.cachedStats;}// 增删改时标记脏privatetriggerRefresh():void{this.refreshNum;this.statsDirtytrue;// 标记需要重新计算}十二、总结统计面板的数据计算体现了以下设计四维度统计全部/即将/今天/已过覆盖用户关注的所有状态实时计算每次渲染实时计算确保数据准确筛选清晰每个维度有明确的筛选条件排序合理即将按时间升序已过按时间降序双页展示列表页和我的页以不同样式展示同一数据颜色区分不同维度使用不同颜色视觉直观统计面板让用户一目了然地了解重要日的整体分布是信息密度与可读性的良好平衡。