及时做APP开发实战(十九)-数据统计与图表展示
及时做APP开发实战(十九)-数据统计与图表展示本文将介绍如何实现专注数据统计和图表展示功能包括日统计、周统计、月统计等。一、功能需求1.1 统计页面布局【图1统计页面整体布局】┌─────────────────────────────────────┐ │ 专注统计 │ ├─────────────────────────────────────┤ │ ┌─────────────────────────────┐ │ │ │ 今日专注 │ │ │ │ │ │ │ │ 8个番茄钟 │ │ │ │ ⏱️ 200分钟 │ │ │ │ 完成5个待办 │ │ │ └─────────────────────────────┘ │ │ │ │ ┌─────────────────────────────┐ │ │ │ 本周统计 │ │ │ │ │ │ │ │ 一 二 三 四 五 六 日 │ │ │ │ ▓▓ ▓▓▓ ▓▓ ▓▓▓▓ ▓▓ ▓ ▓▓▓ │ │ │ │ 2 3 2 4 2 1 3 │ │ │ └─────────────────────────────┘ │ │ │ │ ┌─────────────────────────────┐ │ │ │ 累计统计 │ │ │ │ │ │ │ │ 总专注时长: 50小时 │ │ │ │ 总番茄钟: 100个 │ │ │ │ 总待办: 80个 │ │ │ └─────────────────────────────┘ │ └─────────────────────────────────────┘1.2 统计维度维度说明展示方式今日统计今日专注数据数字卡片本周统计近7天专注趋势柱状图本月统计近30天专注趋势折线图累计统计历史总数据数字汇总二、数据模型2.1 统计数据模型【图2统计图表效果】// src/main/ets/model/StatisticsModel.etsexportclassDailyStatistics{date:string;// 日期 YYYY-MM-DDpomodoroCount:number0;// 番茄钟数focusMinutes:number0;// 专注分钟数completedTodos:number0;// 完成待办数}exportclassStatisticsSummary{// 今日统计todayPomodoros:number0;todayMinutes:number0;todayTodos:number0;// 本周统计weekPomodoros:number0;weekMinutes:number0;weekData:DailyStatistics[][];// 累计统计totalPomodoros:number0;totalMinutes:number0;totalTodos:number0;}exportclassChartData{label:string;// 标签日期value:number0;// 数值color:string;// 颜色}2.2 统计计算逻辑// src/main/ets/viewmodel/StatisticsViewModel.etsexportclassStatisticsViewModel{privatefocusRepository:FocusRepository;privatetodoRepository:TodoRepository;/** * 获取今日统计 */asyncgetTodayStatistics():PromiseDailyStatistics{consttodayDateTimeUtil.formatDate(newDate());constrecordsawaitthis.focusRepository.getRecordsByDate(today);conststatisticsnewDailyStatistics();statistics.datetoday;statistics.pomodoroCountrecords.length;statistics.focusMinutesrecords.reduce((sum,r)sumr.duration,0);consttodosawaitthis.todoRepository.getCompletedByDate(today);statistics.completedTodostodos.length;returnstatistics;}/** * 获取本周统计 */asyncgetWeekStatistics():PromiseDailyStatistics[]{constweekData:DailyStatistics[][];consttodaynewDate();for(leti6;i0;i--){constdatenewDate(today);date.setDate(date.getDate()-i);constdateStrDateTimeUtil.formatDate(date);constdayStatsawaitthis.getDayStatistics(dateStr);weekData.push(dayStats);}returnweekData;}/** * 获取累计统计 */asyncgetTotalStatistics():PromiseStatisticsSummary{constsummarynewStatisticsSummary();constallRecordsawaitthis.focusRepository.getAllRecords();summary.totalPomodorosallRecords.length;summary.totalMinutesallRecords.reduce((sum,r)sumr.duration,0);constallTodosawaitthis.todoRepository.getAllTodos();summary.totalTodosallTodos.filter(tt.completed).length;returnsummary;}}三、统计页面实现3.1 页面结构【图3统计卡片效果】// src/main/ets/pages/StatisticsPage.etsEntryComponentstruct StatisticsPage{StatetodayStats:DailyStatisticsnewDailyStatistics();StateweekData:DailyStatistics[][];StatetotalStats:StatisticsSummarynewStatisticsSummary();StateisLoading:booleantrue;asyncaboutToAppear(){awaitthis.loadStatistics();}asyncloadStatistics(){constviewModelnewStatisticsViewModel();this.todayStatsawaitviewModel.getTodayStatistics();this.weekDataawaitviewModel.getWeekStatistics();this.totalStatsawaitviewModel.getTotalStatistics();this.isLoadingfalse;}build(){Column(){this.TitleBar()if(this.isLoading){this.LoadingView()}else{this.StatisticsContent()}}.width(100%).height(100%).backgroundColor(#F5F5F5)}}3.2 今日统计卡片BuilderTodayStatisticsCard(){Column(){Text(今日专注).fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:15})Row(){// 番茄钟数Column(){Text().fontSize(24)Text(${this.todayStats.pomodoroCount}).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#FF6B6B)Text(个番茄钟).fontSize(12).fontColor(#999999)}.layoutWeight(1)// 专注时长Column(){Text(⏱️).fontSize(24)Text(${this.todayStats.focusMinutes}).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#4CAF50)Text(分钟).fontSize(12).fontColor(#999999)}.layoutWeight(1)// 完成待办Column(){Text().fontSize(24)Text(${this.todayStats.completedTodos}).fontSize(28).fontWeight(FontWeight.Bold).fontColor(#2196F3)Text(个待办).fontSize(12).fontColor(#999999)}.layoutWeight(1)}.width(100%)}.width(100%).padding(20).backgroundColor(#FFFFFF).borderRadius(12).margin({top:15,left:15,right:15})}3.3 本周统计图表BuilderWeekChartCard(){Column(){Text(本周统计).fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:15})// 柱状图Row(){ForEach(this.weekData,(day:DailyStatistics,index:number){Column(){// 柱子Column().width(20).height(this.getBarHeight(day.pomodoroCount)).backgroundColor(#FF6B6B).borderRadius({topLeft:4,topRight:4})// 日期标签Text(this.getWeekDayLabel(index)).fontSize(10).fontColor(#999999).margin({top:5})}.layoutWeight(1).justifyContent(FlexAlign.End)})}.width(100%).height(120)}.width(100%).padding(20).backgroundColor(#FFFFFF).borderRadius(12).margin({top:15,left:15,right:15})}// 计算柱子高度privategetBarHeight(count:number):number{constmaxHeight80;constmaxCountMath.max(...this.weekData.map(dd.pomodoroCount),1);return(count/maxCount)*maxHeight;}// 获取星期标签privategetWeekDayLabel(index:number):string{constlabels[一,二,三,四,五,六,日];returnlabels[index];}3.4 累计统计卡片BuilderTotalStatisticsCard(){Column(){Text(累计统计).fontSize(16).fontWeight(FontWeight.Bold).margin({bottom:15})Column(){// 总专注时长Row(){Text(总专注时长).fontSize(14).fontColor(#666666)Blank()Text(${Math.floor(this.totalStats.totalMinutes/60)}小时${this.totalStats.totalMinutes%60}分钟).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#FF6B6B)}.width(100%).margin({bottom:10})// 总番茄钟Row(){Text(总番茄钟).fontSize(14).fontColor(#666666)Blank()Text(${this.totalStats.totalPomodoros}个).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#4CAF50)}.width(100%).margin({bottom:10})// 总完成待办Row(){Text(总完成待办).fontSize(14).fontColor(#666666)Blank()Text(${this.totalStats.totalTodos}个).fontSize(14).fontWeight(FontWeight.Bold).fontColor(#2196F3)}.width(100%)}}.width(100%).padding(20).backgroundColor(#FFFFFF).borderRadius(12).margin({top:15,left:15,right:15,bottom:15})}四、数据查询实现4.1 按日期查询// src/main/ets/repository/FocusRepository.etsexportclassFocusRepository{/** * 获取指定日期的专注记录 */asyncgetRecordsByDate(date:string):PromiseFocusRecord[]{constallRecordsawaitthis.getAllRecords();returnallRecords.filter(record{constrecordDateDateTimeUtil.formatDate(newDate(record.startTime));returnrecordDatedate;});}/** * 获取日期范围内的专注记录 */asyncgetRecordsByDateRange(startDate:string,endDate:string):PromiseFocusRecord[]{constallRecordsawaitthis.getAllRecords();returnallRecords.filter(record{constrecordDateDateTimeUtil.formatDate(newDate(record.startTime));returnrecordDatestartDaterecordDateendDate;});}}4.2 待办统计查询// src/main/ets/repository/TodoRepository.etsexportclassTodoRepository{/** * 获取指定日期完成的待办 */asyncgetCompletedByDate(date:string):PromiseTodoItem[]{constallTodosawaitthis.getAllTodos();returnallTodos.filter(todo{if(!todo.completed)returnfalse;constcompletedDateDateTimeUtil.formatDate(newDate(todo.completedAt||todo.createdAt));returncompletedDatedate;});}}五、总结本文实现了专注数据统计和图表展示功能核心要点数据模型DailyStatistics、StatisticsSummary统计计算今日、本周、累计统计图表展示柱状图、数字卡片数据查询按日期范围查询