请添加图片描述

前言

健康报告是对用户一段时间内健康数据的综合分析和总结。通过健康报告,用户可以全面了解自己的健康状况,发现潜在问题,获得改善建议。

这篇文章会讲解健康报告页面的实现,包括健康评分卡片、健康指标列表、健康建议等核心组件。


页面整体结构

健康报告页面包含健康评分卡片、健康指标列表和健康建议三个主要部分。

class HealthReportPage extends StatelessWidget {
  const HealthReportPage({super.key});

  
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFFAFAFC),
      appBar: AppBar(
        backgroundColor: Colors.transparent,
        leading: IconButton(
          icon: Icon(Icons.arrow_back_ios_rounded, size: 20.w), 
          onPressed: () => Get.back()
        ),
        title: Text('健康报告', style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.w600)),
        centerTitle: true,
        actions: [
          IconButton(
            icon: Icon(Icons.share_outlined, size: 22.w), 
            onPressed: () {}
          ),
        ],
      ),
      body: SingleChildScrollView(
        padding: EdgeInsets.all(20.w),
        child: Column(
          children: [
            _buildScoreCard(),
            SizedBox(height: 20.h),
            _buildIndicators(),
            SizedBox(height: 20.h),
            _buildSuggestions(),
          ],
        ),
      ),
    );
  }
}

AppBar 右侧添加了分享按钮,用户可以把健康报告分享给家人或医生。页面使用统一的浅灰色背景,三个卡片垂直排列。


健康评分卡片

健康评分卡片是整个报告的核心,用渐变背景和圆形评分展示突出显示。

Widget _buildScoreCard() {
  return Container(
    padding: EdgeInsets.all(24.w),
    decoration: BoxDecoration(
      gradient: const LinearGradient(
        colors: [Color(0xFF6C63FF), Color(0xFF8B7FFF)]
      ),
      borderRadius: BorderRadius.circular(24.r),
    ),
    child: Column(
      children: [
        Text('2026年1月健康报告', style: TextStyle(
          fontSize: 13.sp, 
          color: Colors.white70
        )),
        SizedBox(height: 16.h),
        Container(
          width: 100.w,
          height: 100.w,
          decoration: BoxDecoration(
            color: Colors.white.withOpacity(0.2),
            shape: BoxShape.circle,
          ),
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Text('85', style: TextStyle(
                  fontSize: 36.sp, 
                  fontWeight: FontWeight.w700, 
                  color: Colors.white
                )),
                Text('分', style: TextStyle(
                  fontSize: 14.sp, 
                  color: Colors.white70
                )),
              ],
            ),
          ),
        ),
        SizedBox(height: 16.h),
        Text('健康状态良好', style: TextStyle(
          fontSize: 18.sp, 
          fontWeight: FontWeight.w600, 
          color: Colors.white
        )),
      ],
    ),
  );
}

渐变色从 #6C63FF#8B7FFF,是应用的主题紫色。评分用圆形容器包裹,半透明白色背景让数字更突出。

评分下方显示健康状态的文字描述,让用户快速了解自己的整体健康水平。


健康评分计算

健康评分可以根据各项指标综合计算:

int _calculateHealthScore({
  required double weightScore,
  required double bpScore,
  required double sleepScore,
  required double exerciseScore,
}) {
  // 各项指标权重
  const weightWeight = 0.2;
  const bpWeight = 0.3;
  const sleepWeight = 0.25;
  const exerciseWeight = 0.25;
  
  final totalScore = weightScore * weightWeight +
      bpScore * bpWeight +
      sleepScore * sleepWeight +
      exerciseScore * exerciseWeight;
  
  return totalScore.round();
}

String _getScoreDescription(int score) {
  if (score >= 90) return '健康状态优秀';
  if (score >= 80) return '健康状态良好';
  if (score >= 70) return '健康状态一般';
  if (score >= 60) return '需要关注健康';
  return '健康状态较差';
}

评分根据体重、血压、睡眠、运动四个维度加权计算,每个维度有不同的权重。血压权重最高,因为它对健康影响最大。


健康指标列表

健康指标列表展示各项健康数据的当前值和状态。

Widget _buildIndicators() {
  final items = [
    {'label': '体重', 'value': '65.5 kg', 'status': '正常', 'color': const Color(0xFF00C9A7)},
    {'label': '血压', 'value': '120/80', 'status': '正常', 'color': const Color(0xFF00C9A7)},
    {'label': '睡眠', 'value': '7.2 h', 'status': '良好', 'color': const Color(0xFF00C9A7)},
    {'label': '运动', 'value': '156 min', 'status': '达标', 'color': const Color(0xFF00C9A7)},
  ];

  return Container(
    padding: EdgeInsets.all(20.w),
    decoration: BoxDecoration(
      color: Colors.white, 
      borderRadius: BorderRadius.circular(20.r)
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('健康指标', style: TextStyle(
          fontSize: 16.sp, 
          fontWeight: FontWeight.w600, 
          color: const Color(0xFF1A1A2E)
        )),
        SizedBox(height: 16.h),
        ...items.map((item) => Padding(
          padding: EdgeInsets.only(bottom: 14.h),
          child: Row(
            children: [
              Expanded(
                child: Text(item['label'] as String, style: TextStyle(
                  fontSize: 14.sp, 
                  color: Colors.grey[600]
                ))
              ),
              Text(item['value'] as String, style: TextStyle(
                fontSize: 15.sp, 
                fontWeight: FontWeight.w600, 
                color: const Color(0xFF1A1A2E)
              )),
              SizedBox(width: 12.w),
              Container(
                padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
                decoration: BoxDecoration(
                  color: (item['color'] as Color).withOpacity(0.12), 
                  borderRadius: BorderRadius.circular(6.r)
                ),
                child: Text(item['status'] as String, style: TextStyle(
                  fontSize: 11.sp, 
                  color: item['color'] as Color
                )),
              ),
            ],
          ),
        )),
      ],
    ),
  );
}

每个指标一行,左边是指标名称,中间是数值,右边是状态标签。状态标签用颜色区分:绿色表示正常/良好/达标,黄色表示一般,红色表示需要关注。


指标状态判断

根据各项指标的数值判断状态:

Map<String, dynamic> _getIndicatorStatus(String type, dynamic value) {
  switch (type) {
    case '体重':
      // 假设目标体重是63kg
      final diff = (value as double) - 63;
      if (diff.abs() <= 2) {
        return {'status': '正常', 'color': const Color(0xFF00C9A7)};
      } else if (diff.abs() <= 5) {
        return {'status': '偏离', 'color': const Color(0xFFFFBE0B)};
      } else {
        return {'status': '需关注', 'color': const Color(0xFFFF6B6B)};
      }
    
    case '血压':
      final systolic = (value as Map)['systolic'] as int;
      if (systolic < 120) {
        return {'status': '正常', 'color': const Color(0xFF00C9A7)};
      } else if (systolic < 140) {
        return {'status': '偏高', 'color': const Color(0xFFFFBE0B)};
      } else {
        return {'status': '过高', 'color': const Color(0xFFFF6B6B)};
      }
    
    case '睡眠':
      final hours = value as double;
      if (hours >= 7 && hours <= 9) {
        return {'status': '良好', 'color': const Color(0xFF00C9A7)};
      } else if (hours >= 6) {
        return {'status': '一般', 'color': const Color(0xFFFFBE0B)};
      } else {
        return {'status': '不足', 'color': const Color(0xFFFF6B6B)};
      }
    
    case '运动':
      final minutes = value as int;
      if (minutes >= 150) {
        return {'status': '达标', 'color': const Color(0xFF00C9A7)};
      } else if (minutes >= 100) {
        return {'status': '接近', 'color': const Color(0xFFFFBE0B)};
      } else {
        return {'status': '不足', 'color': const Color(0xFFFF6B6B)};
      }
    
    default:
      return {'status': '未知', 'color': Colors.grey};
  }
}

每种指标有不同的判断标准,根据医学建议和用户目标来确定状态。


健康建议卡片

健康建议根据各项指标的状态给出个性化的改善建议。

Widget _buildSuggestions() {
  return Container(
    padding: EdgeInsets.all(20.w),
    decoration: BoxDecoration(
      color: Colors.white, 
      borderRadius: BorderRadius.circular(20.r)
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('健康建议', style: TextStyle(
          fontSize: 16.sp, 
          fontWeight: FontWeight.w600, 
          color: const Color(0xFF1A1A2E)
        )),
        SizedBox(height: 16.h),
        _buildSuggestionItem('继续保持规律的作息时间'),
        _buildSuggestionItem('每周运动时间已达标,继续保持'),
        _buildSuggestionItem('建议增加饮水量至2000ml/天'),
      ],
    ),
  );
}

Widget _buildSuggestionItem(String text) {
  return Padding(
    padding: EdgeInsets.only(bottom: 12.h),
    child: Row(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Icon(Icons.lightbulb_outline_rounded, size: 18.w, color: const Color(0xFFFFBE0B)),
        SizedBox(width: 10.w),
        Expanded(
          child: Text(text, style: TextStyle(
            fontSize: 14.sp, 
            color: Colors.grey[700]
          ))
        ),
      ],
    ),
  );
}

每条建议前面用黄色灯泡图标,表示这是一个提示或建议。建议内容根据用户的健康数据动态生成。


动态生成建议

根据健康指标状态生成个性化建议:

List<String> _generateSuggestions(Map<String, String> statuses) {
  List<String> suggestions = [];
  
  // 体重建议
  if (statuses['体重'] == '正常') {
    suggestions.add('体重保持在健康范围内,继续保持');
  } else if (statuses['体重'] == '偏离') {
    suggestions.add('体重略有偏离目标,注意饮食和运动');
  } else {
    suggestions.add('建议制定体重管理计划,控制饮食增加运动');
  }
  
  // 血压建议
  if (statuses['血压'] == '正常') {
    suggestions.add('血压正常,继续保持健康的生活方式');
  } else if (statuses['血压'] == '偏高') {
    suggestions.add('血压略高,建议减少盐分摄入,保持运动');
  } else {
    suggestions.add('血压偏高,建议就医检查并遵医嘱');
  }
  
  // 睡眠建议
  if (statuses['睡眠'] == '良好') {
    suggestions.add('睡眠质量良好,继续保持规律作息');
  } else {
    suggestions.add('建议改善睡眠,保证每天7-8小时睡眠');
  }
  
  // 运动建议
  if (statuses['运动'] == '达标') {
    suggestions.add('运动量已达标,继续保持运动习惯');
  } else {
    suggestions.add('建议增加运动量,每周至少150分钟中等强度运动');
  }
  
  return suggestions;
}

建议内容根据各项指标的状态动态生成,给用户提供有针对性的指导。


报告时间范围

健康报告可以支持不同的时间范围:

Widget _buildTimeRangeSelector() {
  final ranges = ['本周', '本月', '近三月'];
  final selectedIndex = 1;
  
  return Row(
    children: ranges.asMap().entries.map((entry) {
      final isSelected = entry.key == selectedIndex;
      return Expanded(
        child: GestureDetector(
          onTap: () {
            // 切换时间范围
          },
          child: Container(
            margin: EdgeInsets.only(right: entry.key < ranges.length - 1 ? 8.w : 0),
            padding: EdgeInsets.symmetric(vertical: 10.h),
            decoration: BoxDecoration(
              color: isSelected 
                ? const Color(0xFF6C63FF) 
                : Colors.white,
              borderRadius: BorderRadius.circular(10.r),
              border: isSelected 
                ? null 
                : Border.all(color: Colors.grey[200]!),
            ),
            child: Center(
              child: Text(
                entry.value,
                style: TextStyle(
                  fontSize: 13.sp,
                  color: isSelected ? Colors.white : Colors.grey[600],
                  fontWeight: isSelected ? FontWeight.w600 : FontWeight.w400,
                ),
              ),
            ),
          ),
        ),
      );
    }).toList(),
  );
}

用户可以选择查看本周、本月或近三月的健康报告,不同时间范围的数据会有所不同。


分享功能

健康报告可以分享给家人或医生:

void _shareReport() {
  // 生成报告摘要
  final summary = '''
健康报告 - 2026年1月
健康评分:85分
状态:健康状态良好

主要指标:
- 体重:65.5 kg(正常)
- 血压:120/80 mmHg(正常)
- 睡眠:7.2 小时/天(良好)
- 运动:156 分钟/周(达标)
''';
  
  // 调用系统分享
  // Share.share(summary);
}

分享功能生成一个文字摘要,用户可以通过微信、短信等方式分享给他人。


小结

健康报告页面通过评分卡片、指标列表和建议三个层次,帮助用户全面了解自己的健康状况。

核心设计要点包括:健康评分用圆形容器突出显示,指标状态用颜色标签区分,建议内容根据数据动态生成。这些设计让用户能快速了解自己的健康水平,并获得有针对性的改善建议。


欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐