人生心电图应用


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

一、项目概述

运行效果图

image-20260408185515864

image-20260408185523861

image-20260408185528603

image-20260408185532874

1.1 应用简介

人生心电图是一款独特的数据可视化应用,将用户的情绪、睡眠、运动等生活数据绘制成一条"生命线"。通过心电图式的曲线展示,让用户直观地看到自己生活的起伏变化,更好地了解和管理自己的生活质量。

应用以青色为主色调,象征生命与活力。界面设计简洁现代,采用深色主题营造专业感。通过CustomPaint绘制心电图曲线,将抽象的生活数据转化为直观的视觉呈现,帮助用户发现生活中的规律和趋势。

1.2 核心功能

功能模块 功能描述 实现方式
心电图展示 生命线可视化 CustomPaint绘制
数据记录 记录六维生活数据 滑块输入
类型切换 切换不同数据类型 选择器组件
趋势分析 数据趋势分析 统计算法
数据分布 各维度数据分布 进度条展示
生活洞察 智能生活建议 规则引擎

1.3 生活数据类型

应用追踪六大生活维度:

数据类型 图标 颜色 说明
情绪 sentiment_satisfied #E91E63 情绪状态和心情
睡眠 bedtime #9C27B0 睡眠质量和时长
运动 directions_run #4CAF50 运动量和强度
工作 work #FF9800 工作效率和压力
社交 people #2196F3 社交活动和互动
健康 favorite #F44336 身体健康状况

1.4 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
图形绘制 CustomPaint -
目标平台 鸿蒙OS / Web API 21+

1.5 项目结构

lib/
└── main_life_ecg.dart
    ├── LifeEcgApp                   # 应用入口
    ├── LifeDataType                 # 生活数据类型枚举
    ├── LifeDataPoint                # 数据点模型
    ├── LifeEcgRecord                # 心电图记录模型
    ├── LifeEcgHomePage              # 主页面(底部导航)
    ├── _buildEcgPage                # 心电图页面
    ├── _buildRecordPage             # 记录页面
    ├── _buildAnalysisPage           # 分析页面
    └── EcgPainter                   # 心电图绘制器

二、设计理念

2.1 生命线概念

生命线

数据采集

可视化

分析洞察

情绪状态

睡眠质量

运动情况

工作状态

社交活动

健康状况

心电图曲线

数据点标记

颜色编码

趋势分析

分布统计

生活建议

2.2 数据可视化理念

数据可视化

心电图形式

起伏曲线

直观展示

生命律动

颜色编码

红色 低值

橙色 中值

绿色 高值

多维度

六大维度

独立追踪

综合分析

2.3 色彩体系

应用采用青色为主色调:

颜色类型 色值 用途
主色 #00BCD4 (Cyan) 导航、按钮、强调
辅助色 #0097A7 (Dark Cyan) 渐变、次要元素
情绪 #E91E63 (Pink) 情绪数据
睡眠 #9C27B0 (Purple) 睡眠数据
运动 #4CAF50 (Green) 运动数据
工作 #FF9800 (Orange) 工作数据
社交 #2196F3 (Blue) 社交数据
健康 #F44336 (Red) 健康数据

2.4 数值评估体系

数值范围 等级 颜色 说明
0-30 红色 需要关注和改善
31-70 橙色 正常水平
71-100 绿色 良好状态

三、系统架构

3.1 整体架构图

Data Layer

Business Layer

Presentation Layer

主页面
LifeEcgHomePage

心电图页

记录页

分析页

心电图绘制

类型选择器

最近记录

数据滑块

统计卡片

趋势分析

分布图表

数据采集
滑块输入

可视化引擎
CustomPaint

分析引擎
统计算法

LifeDataType
数据类型

LifeEcgRecord
记录模型

3.2 类图设计

uses

manages

visualizes

filters

LifeEcgApp

+Widget build()

«enumeration»

LifeDataType

+emotion 情绪

+sleep 睡眠

+exercise 运动

+work 工作

+social 社交

+health 健康

+String label

+IconData icon

+Color color

LifeDataPoint

+DateTime time

+int value

+LifeDataType type

+String note

LifeEcgRecord

+String id

+DateTime date

+Map<LifeDataType,int> values

+String summary

LifeEcgHomePage

-int _currentIndex

-List<LifeEcgRecord> _records

-Map<LifeDataType,int> _currentValues

-DateTime _selectedDate

-LifeDataType _selectedType

-AnimationController _pulseController

+void _saveRecord()

+Map<LifeDataType,double> _calculateAverageValues()

+Map<LifeDataType,String> _calculateTrends()

EcgPainter

+List<LifeEcgRecord> records

+LifeDataType selectedType

+void paint()

+bool shouldRepaint()

3.3 数据流程时序图

绘制引擎 心电图页 数据存储 数据滑块 记录页 用户 绘制引擎 心电图页 数据存储 数据滑块 记录页 用户 loop [每个维度] 打开记录页 显示六维数据滑块 调整数值 更新数值 保存记录 存储记录 切换到心电图页 加载记录 传递数据 绘制心电图 展示生命线

四、核心功能实现

4.1 心电图绘制

心电图绘制是应用的核心功能:

class EcgPainter extends CustomPainter {
  final List<LifeEcgRecord> records;
  final LifeDataType selectedType;

  
  void paint(Canvas canvas, Size size) {
    if (records.isEmpty) return;

    final paint = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = 2
      ..strokeCap = StrokeCap.round;

    final path = Path();
    final points = <Offset>[];

    // 计算数据点位置
    for (int i = 0; i < records.length; i++) {
      final x = (i / (records.length - 1)) * size.width;
      final value = records[i].values[selectedType] ?? 50;
      final y = size.height - (value / 100 * size.height * 0.8) - 20;
      points.add(Offset(x, y));
    }

    // 绘制平滑曲线
    for (int i = 0; i < points.length; i++) {
      if (i == 0) {
        path.moveTo(points[i].dx, points[i].dy);
      } else {
        final prevPoint = points[i - 1];
        final currentPoint = points[i];
        final controlPoint = Offset(
          (prevPoint.dx + currentPoint.dx) / 2,
          (prevPoint.dy + currentPoint.dy) / 2,
        );
        path.quadraticBezierTo(
          prevPoint.dx, prevPoint.dy,
          controlPoint.dx, controlPoint.dy,
        );
      }
    }

    // 绘制曲线
    canvas.drawPath(path, paint);

    // 绘制数据点
    for (int i = 0; i < points.length; i++) {
      final point = points[i];
      final value = records[i].values[selectedType] ?? 50;

      // 根据数值确定颜色
      Color pointColor;
      if (value < 30) {
        pointColor = Colors.red;
      } else if (value < 70) {
        pointColor = Colors.orange;
      } else {
        pointColor = Colors.green;
      }

      // 绘制数据点
      final circlePaint = Paint()
        ..color = pointColor
        ..style = PaintingStyle.fill;
      canvas.drawCircle(point, 4, circlePaint);
    }
  }
}

4.2 数据记录系统

六维数据记录系统:

Widget _buildValueSlider(LifeDataType type) {
  final value = _currentValues[type] ?? 50;

  return Container(
    padding: const EdgeInsets.all(16),
    decoration: BoxDecoration(
      color: Colors.white.withValues(alpha: 0.05),
      borderRadius: BorderRadius.circular(16),
      border: Border.all(
        color: type.color.withValues(alpha: 0.3),
      ),
    ),
    child: Column(
      children: [
        // 类型标签和数值显示
        Row(
          children: [
            Container(
              width: 36,
              height: 36,
              decoration: BoxDecoration(
                color: type.color.withValues(alpha: 0.2),
                borderRadius: BorderRadius.circular(10),
              ),
              child: Icon(type.icon, color: type.color),
            ),
            const SizedBox(width: 12),
            Expanded(
              child: Text(type.label),
            ),
            Container(
              child: Text('$value'),
            ),
          ],
        ),
        // 滑块
        Slider(
          value: value.toDouble(),
          min: 0,
          max: 100,
          divisions: 100,
          onChanged: (newValue) {
            setState(() {
              _currentValues[type] = newValue.round();
            });
          },
        ),
      ],
    ),
  );
}

4.3 趋势分析算法

计算各维度的趋势:

Map<LifeDataType, String> _calculateTrends() {
  final trends = <LifeDataType, String>{};
  
  if (_records.length < 2) {
    for (var type in LifeDataType.values) {
      trends[type] = '稳定';
    }
    return trends;
  }

  // 分割数据:最近7天 vs 之前的数据
  final recent = _records.skip(_records.length - 7).toList();
  final earlier = _records.take(_records.length - 7).toList();

  for (var type in LifeDataType.values) {
    // 计算最近平均值
    final recentAvg = recent.isEmpty
        ? 0.0
        : recent.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) / recent.length;
    
    // 计算之前平均值
    final earlierAvg = earlier.isEmpty
        ? 0.0
        : earlier.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) / earlier.length;

    // 计算差异
    final diff = recentAvg - earlierAvg;
    
    // 判断趋势
    if (diff > 5) {
      trends[type] = '上升';
    } else if (diff < -5) {
      trends[type] = '下降';
    } else {
      trends[type] = '稳定';
    }
  }
  
  return trends;
}

4.4 平均值计算

计算各维度的平均值:

Map<LifeDataType, double> _calculateAverageValues() {
  final avgValues = <LifeDataType, double>{};
  
  for (var type in LifeDataType.values) {
    final sum = _records.fold<int>(
      0,
      (sum, record) => sum + (record.values[type] ?? 0),
    );
    avgValues[type] = _records.isEmpty ? 0 : sum / _records.length;
  }
  
  return avgValues;
}

五、UI设计规范

5.1 配色方案

应用采用青色为主色调:

颜色类型 色值 RGB 用途
主色 #00BCD4 0,188,212 导航、按钮
辅助色 #0097A7 0,151,167 渐变、次要元素
情绪 #E91E63 233,30,99 情绪数据
睡眠 #9C27B0 156,39,176 睡眠数据
运动 #4CAF50 76,175,80 运动数据
工作 #FF9800 255,152,0 工作数据
社交 #2196F3 33,150,243 社交数据
健康 #F44336 244,67,54 健康数据

5.2 字体规范

元素 字号 字重 颜色
页面标题 24-28px Bold #FFFFFF
卡片标题 18px Bold #FFFFFF
数据标签 13-16px Medium 70% White
数值显示 16-20px Bold 动态颜色
辅助文字 11-14px Regular 40-60% White

5.3 组件规范

5.3.1 心电图展示
┌─────────────────────────────────────────────┐
│  生命线                          最近30天    │
│                                             │
│         ╱╲      ╱╲                          │
│        ╱  ╲    ╱  ╲    ╱╲                   │
│    ╱╲ ╱    ╲  ╱    ╲  ╱  ╲                  │
│   ╱  ╲      ╲╱      ╲╱    ╲                 │
│  ╱                              ╲            │
│ ╱                                ╲           │
│                                             │
│  1/1                              1/30      │
└─────────────────────────────────────────────┘
5.3.2 数据滑块
┌─────────────────────────────────────────────┐
│  😊 情绪                          75        │
│  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  │
│  低                                    高    │
└─────────────────────────────────────────────┘
5.3.3 趋势标签
┌─────────────────────────────────────────────┐
│  😊 情绪 ↗ 上升                              │
│  😴 睡眠 → 稳定                              │
│  🏃 运动 ↘ 下降                              │
└─────────────────────────────────────────────┘

六、交互设计

6.1 数据记录流程

存储系统 数据滑块 记录页 用户 存储系统 数据滑块 记录页 用户 loop [每个维度] 打开记录页 显示六维数据 调整数值 实时更新 点击保存 保存记录 显示成功提示

6.2 心电图查看流程

情绪

睡眠

运动

其他

打开心电图页

加载数据记录

绘制心电图

选择数据类型

显示情绪曲线

显示睡眠曲线

显示运动曲线

显示其他曲线

查看数据点

6.3 页面切换状态

点击记录Tab

点击分析Tab

点击心电图Tab

点击分析Tab

点击心电图Tab

点击记录Tab

心电图页

记录页

分析页


七、数据分析

7.1 数据采集维度

六大生活数据维度:

维度 说明 评估指标
情绪 心情状态和情绪波动 愉悦度、稳定性
睡眠 睡眠质量和时长 深度、时长、质量
运动 运动量和强度 频率、强度、时长
工作 工作效率和压力 效率、压力、满意度
社交 社交活动和互动 频率、质量、满意度
健康 身体健康状况 体能、状态、舒适度

7.2 趋势分析方法

差异 > 5

差异 < -5

其他

原始数据

数据分割

平均值计算

差异分析

趋势判断

上升趋势

下降趋势

稳定趋势

7.3 健康度计算

综合健康度评分算法:

int _calculateHealthScore(Map<LifeDataType, double> avgValues) {
  // 计算所有维度的平均值
  final avg = avgValues.values.reduce((a, b) => a + b) / avgValues.length;
  
  // 返回整数分数
  return avg.round();
}

7.4 数据分布分析

各维度数据分布统计:

// 计算各维度的平均值
for (var type in LifeDataType.values) {
  final avg = _records.isEmpty
      ? 0.0
      : _records.fold<int>(0, (sum, r) => sum + (r.values[type] ?? 0)) /
          _records.length;
  
  // 显示进度条
  LinearProgressIndicator(
    value: avg / 100,
    backgroundColor: Colors.white.withValues(alpha: 0.1),
    valueColor: AlwaysStoppedAnimation<Color>(type.color),
  );
}

八、扩展功能规划

8.1 后续版本规划

2024-01-07 2024-01-14 2024-01-21 2024-01-28 2024-02-04 2024-02-11 2024-02-18 2024-02-25 2024-03-03 2024-03-10 2024-03-17 2024-03-24 心电图绘制 数据记录 趋势分析 数据导出 提醒功能 分享功能 AI分析 云端同步 社区功能 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 人生心电图开发计划

8.2 功能扩展建议

8.2.1 数据导出

支持多种格式导出:

  • CSV格式导出
  • PDF报告生成
  • 图片分享
  • 数据备份
8.2.2 智能提醒

基于数据的智能提醒:

  • 数据记录提醒
  • 异常数据警告
  • 趋势变化提醒
  • 健康建议推送
8.2.3 AI分析

人工智能数据分析:

  • 异常检测
  • 模式识别
  • 预测分析
  • 个性化建议

九、注意事项

9.1 开发注意事项

  1. 数据绘制:CustomPaint需要正确计算坐标

  2. 性能优化:大量数据点时注意性能

  3. 状态管理:使用setState管理本地状态

  4. 用户体验:保持界面简洁,避免信息过载

9.2 常见问题

问题 原因 解决方案
曲线不显示 数据为空 检查records
数据点位置错误 坐标计算错误 检查paint方法
颜色不正确 颜色逻辑错误 检查颜色判断
趋势分析错误 算法问题 检查计算逻辑

9.3 使用提示

📊 人生心电图使用小贴士 📊

每天记录,持续追踪。
关注趋势,发现规律。
平衡生活,关注健康。
数据驱动,科学决策。

提示:建议每天固定时间记录,保持数据的连续性。


十、运行说明

10.1 环境要求

环境 版本要求
Flutter SDK >= 3.0.0
Dart SDK >= 2.17.0
鸿蒙OS API 21+

10.2 运行命令

# 查看可用设备
flutter devices

# 运行到Web服务器
flutter run -d web-server -t lib/main_life_ecg.dart --web-port 8126

# 运行到鸿蒙设备
flutter run -d 127.0.0.1:5555 lib/main_life_ecg.dart

# 运行到Windows
flutter run -d windows -t lib/main_life_ecg.dart

# 代码分析
flutter analyze lib/main_life_ecg.dart

十一、总结

人生心电图是一款独特的数据可视化应用,将用户的情绪、睡眠、运动等生活数据绘制成一条"生命线"。通过心电图式的曲线展示,让用户直观地看到自己生活的起伏变化,更好地了解和管理自己的生活质量。

从技术实现来看,应用使用CustomPaint绘制心电图曲线,将抽象的生活数据转化为直观的视觉呈现。通过六维数据记录系统,全面追踪用户的生活状态。采用趋势分析算法,帮助用户发现生活中的规律和趋势。

从用户体验来看,应用提供简洁直观的界面,让用户轻松记录和查看数据。通过颜色编码和趋势标签,让用户快速理解数据含义。提供生活洞察建议,帮助用户改善生活质量。

应用不仅是一个数据记录工具,更是一个生活管理平台。它提醒我们:每天记录,持续追踪;关注趋势,发现规律;平衡生活,关注健康;数据驱动,科学决策。在快节奏的现代生活中,人生心电图为我们提供了一种科学管理生活的方式。

记录生命的每一次跳动


Logo

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

更多推荐