From 86852cc47dc3cb2fe2f6b33e8aa10913bd656c52 Mon Sep 17 00:00:00 2001 From: Cxx0822 <1556464090@qq.com> Date: Tue, 2 Dec 2025 17:55:43 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E6=9B=B4=E6=96=B0=E7=9B=AE=E6=A0=87?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/AndroidManifest.xml | 2 +- lib/provider/health_provider.dart | 19 ++++++ lib/service/health_service.dart | 62 ++++++++++++++++++ lib/utils/record_utils.dart | 57 ++++++++++++----- lib/widget/record/goal_progress.dart | 43 ++++++++++--- lib/widget/record/record_daily.dart | 80 +++++++++++++----------- lib/widget/record/record_form.dart | 8 +-- 7 files changed, 207 insertions(+), 64 deletions(-) diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9e5ef3e..aee2e3e 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,6 @@ updateRecord(HealthRecord record) async { try { List records = diff --git a/lib/utils/record_utils.dart b/lib/utils/record_utils.dart index 0c9cd8e..d0c8648 100644 --- a/lib/utils/record_utils.dart +++ b/lib/utils/record_utils.dart @@ -6,7 +6,7 @@ bool checkHasRecordValue(HealthRecord record, RecordType type) { case RecordType.weight: return record.weight != 0; case RecordType.sport: - return record.sportProject != ''; + return record.sportDuration != 0; case RecordType.sleep: return record.sleepStartTime != ''; } @@ -30,21 +30,25 @@ String formatTime(TimeOfDay time) { return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}'; } +int calSleepMinuteDuration(String startTime, String endTime) { + final start = parseTime(startTime); + final end = parseTime(endTime); + + int startMinutes = start.hour * 60 + start.minute; + int endMinutes = end.hour * 60 + end.minute; + + // 处理跨天情况(如果结束时间小于开始时间,认为是第二天) + if (endMinutes < startMinutes) { + endMinutes += 24 * 60; + } + + return endMinutes - startMinutes; +} + // 计算睡眠时长 -String calculateDuration(String startTime, String endTime) { +String calSleepDuration(String startTime, String endTime) { try { - final start = parseTime(startTime); - final end = parseTime(endTime); - - int startMinutes = start.hour * 60 + start.minute; - int endMinutes = end.hour * 60 + end.minute; - - // 处理跨天情况(如果结束时间小于开始时间,认为是第二天) - if (endMinutes < startMinutes) { - endMinutes += 24 * 60; // 加上一天的分钟数 - } - - int durationMinutes = endMinutes - startMinutes; + int durationMinutes = calSleepMinuteDuration(startTime, endTime); int hours = durationMinutes ~/ 60; int minutes = durationMinutes % 60; @@ -53,3 +57,28 @@ String calculateDuration(String startTime, String endTime) { return '计算错误'; } } + +double roundNum(double value) { + return double.parse(value.toStringAsFixed(2)); +} + +double calWeightProgress(num currentWeight, num targetWeight, num startWeight) { + if (currentWeight == 0) return 0.0; + if (startWeight <= targetWeight) return 0.0; + if (currentWeight <= targetWeight) return 1.0; + + num totalToLose = startWeight - targetWeight; + num alreadyLost = startWeight - currentWeight; + + return formatProgress((alreadyLost / totalToLose).clamp(0.0, 1.0)); +} + +double formatProgress(double value) { + final result = roundNum(value); + + if (result >= 1) { + return 1; + } else { + return result; + } +} diff --git a/lib/widget/record/goal_progress.dart b/lib/widget/record/goal_progress.dart index 6a9e5bc..dd3ffe5 100644 --- a/lib/widget/record/goal_progress.dart +++ b/lib/widget/record/goal_progress.dart @@ -1,9 +1,13 @@ import 'package:fitnote/models/health.dart'; +import 'package:fitnote/provider/health_provider.dart'; +import 'package:fitnote/service/health_service.dart'; +import 'package:fitnote/utils/record_utils.dart'; import 'package:fitnote/widget/record/common.dart'; import 'package:flutter/material.dart'; import 'package:flutter_common/widget/common_widget.dart'; import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:getwidget/getwidget.dart'; +import 'package:provider/provider.dart'; class GoalProgress extends StatefulWidget { const GoalProgress({super.key}); @@ -13,8 +17,29 @@ class GoalProgress extends StatefulWidget { } class _GoalProgressState extends State { + final HealthService service = HealthService(); + + final int initWeight = 72; + final int goalWeight = 70; + final int goalTotalSpot = 600; + final int goalAvgSleep = 8; + + @override + void initState() { + super.initState(); + + WidgetsBinding.instance.addPostFrameCallback((_) { + final provider = context.read(); + provider.totalSpot = service.getTotalSport(); + provider.avgSleep = service.getAvgSleep(); + provider.latestWeight = service.getLatestWeight(); + }); + } + @override Widget build(BuildContext context) { + final provider = context.watch(); + return CommonCard( child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -27,28 +52,28 @@ class _GoalProgressState extends State { const SizedBox(height: 28), _buildProgressItem( title: '目标体重', - current: '65.2', - target: '60', + current: provider.latestWeight.toString(), + target: goalWeight.toString(), unit: 'kg', - progress: 0.85, + progress: calWeightProgress(provider.latestWeight, goalWeight, initWeight), color: RecordType.weight.color, ), const SizedBox(height: 28), _buildProgressItem( title: '运动总时长', - current: '450', - target: '600', + current: provider.totalSpot.toString(), + target: goalTotalSpot.toString(), unit: '分钟', - progress: 0.75, + progress: formatProgress(provider.totalSpot / goalTotalSpot), color: RecordType.sport.color, ), const SizedBox(height: 28), _buildProgressItem( title: '日均睡眠', - current: '7.2', - target: '8', + current: provider.avgSleep.toString(), + target: goalAvgSleep.toString(), unit: '小时', - progress: 0.9, + progress: formatProgress(provider.avgSleep / goalAvgSleep), color: RecordType.sleep.color, ), ], diff --git a/lib/widget/record/record_daily.dart b/lib/widget/record/record_daily.dart index b5a19bf..171c6c4 100644 --- a/lib/widget/record/record_daily.dart +++ b/lib/widget/record/record_daily.dart @@ -161,9 +161,33 @@ class _RecordDailyState extends State { provider.type = type; if (provider.isEditing) { - _initRecord(provider); + switch (provider.type) { + case RecordType.weight: + provider.updateWeight(_record.weight); + break; + case RecordType.sport: + provider.updateSportProject(_record.sportProject); + provider.updateSportDuration(_record.sportDuration); + break; + case RecordType.sleep: + provider.updateSleepStartTime(_record.sleepStartTime); + provider.updateSleepEndTime(_record.sleepEndTime); + break; + } } else { - _defaultRecord(provider); + switch (provider.type) { + case RecordType.weight: + provider.updateWeight(70); + break; + case RecordType.sport: + provider.updateSportProject('跑步'); + provider.updateSportDuration(30); + break; + case RecordType.sleep: + provider.updateSleepStartTime(''); + provider.updateSleepEndTime(''); + break; + } } showDialog( @@ -211,42 +235,22 @@ class _RecordDailyState extends State { ); } - void _initRecord(HealthProvider provider) { - switch (provider.type) { - case RecordType.weight: - provider.updateWeight(_record.weight); - break; - case RecordType.sport: - provider.updateSportProject(_record.sportProject); - provider.updateSportDuration(_record.sportDuration); - break; - case RecordType.sleep: - provider.updateSleepStartTime(_record.sleepStartTime); - provider.updateSleepEndTime(_record.sleepEndTime); - break; - } - } - void _resetRecord() { final provider = context.read(); if (!provider.isEditing) { - _defaultRecord(provider); - } - } - - void _defaultRecord(HealthProvider provider) { - switch (provider.type) { - case RecordType.weight: - provider.updateWeight(70); - break; - case RecordType.sport: - provider.updateSportProject('跑步'); - provider.updateSportDuration(30); - break; - case RecordType.sleep: - provider.updateSleepStartTime(''); - provider.updateSleepEndTime(''); - break; + switch (provider.type) { + case RecordType.weight: + provider.updateWeight(0); + break; + case RecordType.sport: + provider.updateSportProject('跑步'); + provider.updateSportDuration(0); + break; + case RecordType.sleep: + provider.updateSleepStartTime(''); + provider.updateSleepEndTime(''); + break; + } } } @@ -257,6 +261,10 @@ class _RecordDailyState extends State { setState(() { _record = service.getAllRecordByDate(provider.date); }); + + provider.updateLatestWeight(service.getLatestWeight()); + provider.updateTotalSpot(service.getTotalSport()); + provider.updateAvgSleep(service.getAvgSleep()); } Widget _buildRecordContent(RecordType type) { @@ -277,7 +285,7 @@ class _RecordDailyState extends State { final startTime = _record.sleepStartTime; final endTime = _record.sleepEndTime; if (startTime.isNotEmpty && endTime.isNotEmpty) { - final duration = calculateDuration(startTime, endTime); + final duration = calSleepDuration(startTime, endTime); title = "入睡 $startTime · 起床 $endTime · ${duration}"; } else if (startTime.isNotEmpty) { title = "入睡 $startTime"; diff --git a/lib/widget/record/record_form.dart b/lib/widget/record/record_form.dart index 1488e0a..52f9ca6 100644 --- a/lib/widget/record/record_form.dart +++ b/lib/widget/record/record_form.dart @@ -43,10 +43,10 @@ class _RecordFormState extends State { Widget _buildSleepDuration(HealthRecord record) { final startTime = record.sleepStartTime; final endTime = record.sleepEndTime; - late String duration = calculateDuration(startTime, endTime); + late String duration = calSleepDuration(startTime, endTime); if (startTime.isNotEmpty && endTime.isNotEmpty) { - duration = calculateDuration(startTime, endTime); + duration = calSleepDuration(startTime, endTime); } else { duration = ""; } @@ -151,7 +151,7 @@ class _RecordFormState extends State { provider.updateSleepStartTime(formatTime(time)); final startTime = provider.formItem.sleepStartTime; final endTime = provider.formItem.sleepEndTime; - calculateDuration(startTime, endTime); + calSleepDuration(startTime, endTime); }, ), ], @@ -169,7 +169,7 @@ class _RecordFormState extends State { provider.updateSleepEndTime(formatTime(time)); final startTime = provider.formItem.sleepStartTime; final endTime = provider.formItem.sleepEndTime; - calculateDuration(startTime, endTime); + calSleepDuration(startTime, endTime); }, ), ],