志愿者活动应用


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

一、项目概述

运行效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.1 应用简介

志愿者活动是一款专注于志愿服务管理与记录的移动应用,为志愿者和活动组织者提供便捷、高效的服务平台。志愿服务是社会文明进步的重要标志,越来越多的人投身于公益事业。本应用帮助用户发现志愿活动、在线报名参与、记录服务时长、获取志愿证书,让志愿服务更加规范化、数字化。

应用支持多种类型的志愿活动发布与展示,包括社区服务、环境保护、教育支援、敬老爱老等八大类别。活动详情页展示完整的活动信息,支持一键报名与取消报名。个人中心记录累计志愿时长、参与活动数量、获得徽章等成就,激励更多人参与志愿服务。

1.2 核心功能

功能模块 功能描述 实现方式
活动列表 志愿活动浏览与筛选 ListView + FilterChip
活动详情 活动信息完整展示 ModalBottomSheet
在线报名 一键报名/取消报名 状态管理
我的记录 参与活动历史记录 ListView
志愿统计 时长统计与类型分布 图表展示
个人中心 用户信息与徽章展示 Card + ListView

1.3 活动属性

属性 类型 说明
活动ID String 唯一标识
活动标题 String 活动名称
活动描述 String 详细说明
活动类型 ActivityType 八大类别
活动状态 ActivityStatus 招募/进行/结束/取消
开始时间 DateTime 活动开始时间
结束时间 DateTime 活动结束时间
活动地点 String 举办地点
最大人数 int 招募上限
当前人数 int 已报名人数
志愿时长 int 服务时长(小时)
主办方 String 组织单位
联系电话 String 咨询电话
报名要求 List 参与条件

1.4 活动类型

类型 图标 颜色 说明
社区服务 home_work 蓝色 社区公益服务
环境保护 eco 绿色 环保志愿活动
教育支援 school 橙色 支教助学活动
敬老爱老 elderly 紫色 养老服务活动
医疗援助 medical_services 红色 医疗志愿服务
文化传播 theater_comedy 青色 文化志愿活动
体育赛事 sports_soccer 靛蓝 赛事志愿服务
公益慈善 volunteer_activism 粉色 慈善公益活动

1.5 活动状态

状态 颜色 说明
招募中 绿色 正在招募志愿者
进行中 蓝色 活动正在进行
已结束 灰色 活动已结束
已取消 红色 活动已取消

1.6 技术栈

技术领域 技术选型 版本要求
开发框架 Flutter >= 3.0.0
编程语言 Dart >= 2.17.0
设计规范 Material Design 3 -
状态管理 setState -
日期处理 intl ^0.19.0
目标平台 鸿蒙OS API 21+

1.7 项目结构

lib/
└── main_volunteer.dart
    ├── VolunteerApp              # 应用入口
    ├── ActivityStatus            # 活动状态枚举
    ├── ActivityType              # 活动类型枚举
    ├── VolunteerActivity         # 活动数据模型
    ├── VolunteerRecord           # 志愿记录模型
    ├── VolunteerUser             # 用户数据模型
    └── VolunteerHomePage         # 主页面
        ├── _buildActivityListPage()  # 活动列表页
        ├── _buildMyRecordsPage()     # 我的记录页
        ├── _buildStatisticsPage()    # 统计页面
        ├── _buildProfilePage()       # 个人中心页
        ├── _buildActivityCard()      # 活动卡片
        └── _showActivityDetail()     # 活动详情弹窗

二、系统架构

2.1 整体架构图

Business Logic

Presentation Layer

Data Layer

VolunteerActivity
活动模型

VolunteerRecord
记录模型

VolunteerUser
用户模型

ActivityType
类型枚举

ActivityStatus
状态枚举

主页面

活动列表Tab

我的记录Tab

统计Tab

个人中心Tab

活动详情弹窗

基本信息

报名操作

要求说明

活动报名
报名/取消

状态管理
已报名/未报名

统计计算
时长/类型

等级计算
志愿者等级

2.2 类图设计

contains

manages

manages

manages

has

has

has

VolunteerApp

+Widget build()

«enumeration»

ActivityStatus

recruiting

ongoing

completed

cancelled

+String label

+Color color

«enumeration»

ActivityType

community

environment

education

elderly

medical

culture

sports

charity

+String label

+IconData icon

+Color color

VolunteerActivity

+String id

+String title

+String description

+ActivityType type

+ActivityStatus status

+DateTime startTime

+DateTime endTime

+String location

+int maxParticipants

+int currentParticipants

+int requiredHours

+String organizer

+String contactPhone

+List<String> requirements

+bool isFull

+double progress

VolunteerRecord

+String id

+String activityId

+String activityTitle

+ActivityType type

+DateTime date

+double hours

+String location

+String certificate

VolunteerUser

+String name

+String phone

+double totalHours

+int activityCount

+int level

+List<String> badges

+String levelTitle

VolunteerHomePage

-int _selectedIndex

-List<VolunteerActivity> _activities

-List<VolunteerRecord> _records

-Set<String> _registeredActivities

-VolunteerUser _currentUser

+Widget build()

-void _registerActivity()

-void _cancelRegistration()

-void _showActivityDetail()

2.3 数据流程图

浏览活动

报名活动

取消报名

查看统计

用户操作

操作类型

加载活动列表

更新报名状态

恢复报名状态

计算统计数据

显示活动卡片

更新人数+1

更新人数-1

显示统计图表

刷新界面

2.4 报名流程

活动数据 报名状态 活动卡片 用户 活动数据 报名状态 活动卡片 用户 alt [未满员] [已满员] 点击报名按钮 检查是否满员 添加活动ID到已报名集合 更新当前人数+1 返回新活动对象 显示报名成功提示 按钮禁用

三、核心模块设计

3.1 数据模型设计

3.1.1 活动状态枚举 (ActivityStatus)
enum ActivityStatus {
  recruiting('招募中', Colors.green),
  ongoing('进行中', Colors.blue),
  completed('已结束', Colors.grey),
  cancelled('已取消', Colors.red);

  final String label;
  final Color color;
  const ActivityStatus(this.label, this.color);
}
3.1.2 活动类型枚举 (ActivityType)
enum ActivityType {
  community('社区服务', Icons.home_work, Colors.blue),
  environment('环境保护', Icons.eco, Colors.green),
  education('教育支援', Icons.school, Colors.orange),
  elderly('敬老爱老', Icons.elderly, Colors.purple),
  medical('医疗援助', Icons.medical_services, Colors.red),
  culture('文化传播', Icons.theater_comedy, Colors.teal),
  sports('体育赛事', Icons.sports_soccer, Colors.indigo),
  charity('公益慈善', Icons.volunteer_activism, Colors.pink);

  final String label;
  final IconData icon;
  final Color color;
  const ActivityType(this.label, this.icon, this.color);
}
3.1.3 活动模型 (VolunteerActivity)
class VolunteerActivity {
  final String id;                  // 唯一标识
  final String title;               // 活动标题
  final String description;         // 活动描述
  final ActivityType type;          // 活动类型
  final ActivityStatus status;      // 活动状态
  final DateTime startTime;         // 开始时间
  final DateTime endTime;           // 结束时间
  final String location;            // 活动地点
  final int maxParticipants;        // 最大人数
  final int currentParticipants;    // 当前人数
  final int requiredHours;          // 志愿时长
  final String organizer;           // 主办方
  final String contactPhone;        // 联系电话
  final List<String> requirements;  // 报名要求

  bool get isFull => currentParticipants >= maxParticipants;
  double get progress => currentParticipants / maxParticipants;
}
3.1.4 志愿记录模型 (VolunteerRecord)
class VolunteerRecord {
  final String id;                  // 记录ID
  final String activityId;          // 活动ID
  final String activityTitle;       // 活动标题
  final ActivityType type;          // 活动类型
  final DateTime date;              // 参与日期
  final double hours;               // 服务时长
  final String location;            // 活动地点
  final String? certificate;        // 认证证书编号
  final String? feedback;           // 活动反馈
}
3.1.5 用户模型 (VolunteerUser)
class VolunteerUser {
  final String name;                // 用户姓名
  final String phone;               // 手机号码
  final double totalHours;          // 累计时长
  final int activityCount;          // 活动次数
  final int level;                  // 志愿者等级
  final List<String> badges;        // 获得徽章

  String get levelTitle {
    if (level >= 5) return '五星志愿者';
    if (level >= 4) return '四星志愿者';
    if (level >= 3) return '三星志愿者';
    if (level >= 2) return '二星志愿者';
    return '一星志愿者';
  }
}

3.2 报名管理逻辑

3.2.1 报名流程

点击报名

是否满员?

按钮禁用

添加到已报名集合

更新活动人数+1

创建新活动对象

替换原活动

显示成功提示

3.2.2 报名实现
void _registerActivity(VolunteerActivity activity) {
  setState(() {
    _registeredActivities.add(activity.id);
    final index = _activities.indexOf(activity);
    _activities[index] = VolunteerActivity(
      id: activity.id,
      title: activity.title,
      // ...其他属性
      currentParticipants: activity.currentParticipants + 1,
      // ...
    );
  });
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('已成功报名 ${activity.title}')),
  );
}

3.3 统计计算逻辑

3.3.1 类型分布计算

获取所有记录

遍历记录

按类型累加时长

还有记录?

计算百分比

返回统计结果

3.3.2 统计实现
Widget _buildTypeStatisticsCard() {
  final Map<ActivityType, double> typeHours = {};
  for (var record in _records) {
    typeHours[record.type] = (typeHours[record.type] ?? 0) + record.hours;
  }

  return Card(
    child: Column(
      children: typeHours.entries.map((entry) {
        final percentage = (entry.value / _currentUser.totalHours * 100);
        return LinearProgressIndicator(
          value: entry.value / _currentUser.totalHours,
          valueColor: AlwaysStoppedAnimation<Color>(entry.key.color),
        );
      }).toList(),
    ),
  );
}

3.4 页面结构设计

3.4.1 主页面布局

主页面

底部导航栏

IndexedStack

活动列表

我的记录

统计

我的

活动列表页

记录列表页

统计展示页

个人中心页

3.5 状态管理

3.5.1 核心状态变量
class _VolunteerHomePageState extends State<VolunteerHomePage> {
  int _selectedIndex = 0;                           // 当前Tab索引
  final List<VolunteerActivity> _activities = [];   // 活动列表
  final List<VolunteerRecord> _records = [];        // 志愿记录
  final Set<String> _registeredActivities = {};     // 已报名活动ID
  late VolunteerUser _currentUser;                  // 当前用户
}

四、UI设计规范

4.1 配色方案

应用采用绿色主题风格,体现公益与希望:

颜色类型 色值 用途
主色 Green AppBar、强调、按钮
招募中 Green 招募状态标识
进行中 Blue 进行状态标识
已结束 Grey 结束状态标识
已取消 Red 取消状态标识

4.2 活动类型颜色映射

类型 颜色 说明
社区服务 蓝色 社区公益
环境保护 绿色 环保活动
教育支援 橙色 支教助学
敬老爱老 紫色 养老服务
医疗援助 红色 医疗志愿
文化传播 青色 文化活动
体育赛事 靛蓝 赛事服务
公益慈善 粉色 慈善公益

4.3 组件规范

4.3.1 活动卡片
┌─────────────────────────────────────────────────────────────┐
│  ┌────┐  社区环境清洁活动                    [招募中]      │
│  │ 🌿 │  环境保护                                           │
│  └────┘                                                     │
├─────────────────────────────────────────────────────────────┤
│  🕐 03-18 09:00    📍 阳光社区服务中心                       │
├─────────────────────────────────────────────────────────────┤
│  ████████████████████████░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░   │
│  18/30人                                      [立即报名]   │
└─────────────────────────────────────────────────────────────┘
4.3.2 志愿记录卡片
┌─────────────────────────────────────────────────────────────┐
│  ┌────┐  图书馆整理书籍                            [已认证] │
│  │ 🎭 │  2024-03-10    ⏱ 3小时                               │
│  └────┘                                                    │
└─────────────────────────────────────────────────────────────┘
4.3.3 统计卡片
┌─────────────────────────────────────────────────────────────┐
│  累计志愿时长                                    Lv.3       │
│  128.5 小时                                    三星志愿者  │
└─────────────────────────────────────────────────────────────┘
4.3.4 活动详情弹窗
┌─────────────────────────────────────────────────────────────┐
│                        社区环境清洁活动                 ✕   │
├─────────────────────────────────────────────────────────────┤
│  ┌────┐  环境保护                          [招募中]        │
│  │ 🌿 │  阳光社区居委会                                     │
│  └────┘                                                    │
│  📅 03-18 09:00        ⏱ 4小时                             │
│  📍 阳光社区服务中心    👥 18/30人                          │
├─────────────────────────────────────────────────────────────┤
│  活动详情                                                   │
│  组织志愿者对社区公共区域进行清洁...                         │
│  📞 联系电话: 010-12345678                                  │
├─────────────────────────────────────────────────────────────┤
│  报名要求                                                   │
│  ✓ 年龄18岁以上                                            │
│  ✓ 身体健康                                                │
│  ✓ 自备清洁工具                                            │
├─────────────────────────────────────────────────────────────┤
│                    [立即报名]                               │
└─────────────────────────────────────────────────────────────┘

4.4 交互设计

4.4.1 操作方式
操作 手势 效果
查看活动详情 点击卡片 弹出详情面板
报名活动 点击报名按钮 更新报名状态
取消报名 点击取消按钮 恢复未报名状态
筛选活动 点击筛选按钮 弹出筛选面板
查看统计 切换到统计Tab 显示统计图表

五、核心功能实现

5.1 主页面构建


Widget build(BuildContext context) {
  return Scaffold(
    body: IndexedStack(
      index: _selectedIndex,
      children: [
        _buildActivityListPage(),
        _buildMyRecordsPage(),
        _buildStatisticsPage(),
        _buildProfilePage(),
      ],
    ),
    bottomNavigationBar: NavigationBar(
      selectedIndex: _selectedIndex,
      onDestinationSelected: (index) {
        setState(() {
          _selectedIndex = index;
        });
      },
      destinations: const [
        NavigationDestination(icon: Icon(Icons.event_outlined), label: '活动列表'),
        NavigationDestination(icon: Icon(Icons.history_outlined), label: '我的记录'),
        NavigationDestination(icon: Icon(Icons.bar_chart_outlined), label: '统计'),
        NavigationDestination(icon: Icon(Icons.person_outline), label: '我的'),
      ],
    ),
  );
}

5.2 活动卡片

Widget _buildActivityCard(VolunteerActivity activity) {
  final isRegistered = _registeredActivities.contains(activity.id);

  return Card(
    child: InkWell(
      onTap: () => _showActivityDetail(activity),
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          children: [
            Row(
              children: [
                Container(
                  width: 48,
                  height: 48,
                  decoration: BoxDecoration(
                    color: activity.type.color.withValues(alpha: 0.1),
                    borderRadius: BorderRadius.circular(12),
                  ),
                  child: Icon(activity.type.icon, color: activity.type.color),
                ),
                // ...活动信息
              ],
            ),
            LinearProgressIndicator(
              value: activity.progress,
              valueColor: AlwaysStoppedAnimation<Color>(
                activity.isFull ? Colors.red : Colors.green,
              ),
            ),
            if (activity.status == ActivityStatus.recruiting)
              isRegistered
                  ? OutlinedButton(onPressed: () => _cancelRegistration(activity), child: Text('取消报名'))
                  : FilledButton(onPressed: activity.isFull ? null : () => _registerActivity(activity), child: Text(activity.isFull ? '已满员' : '立即报名')),
          ],
        ),
      ),
    ),
  );
}

5.3 报名与取消

void _registerActivity(VolunteerActivity activity) {
  setState(() {
    _registeredActivities.add(activity.id);
    final index = _activities.indexOf(activity);
    _activities[index] = VolunteerActivity(
      // ...复制属性
      currentParticipants: activity.currentParticipants + 1,
    );
  });
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('已成功报名 ${activity.title}')),
  );
}

void _cancelRegistration(VolunteerActivity activity) {
  setState(() {
    _registeredActivities.remove(activity.id);
    final index = _activities.indexOf(activity);
    _activities[index] = VolunteerActivity(
      // ...复制属性
      currentParticipants: activity.currentParticipants - 1,
    );
  });
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('已取消报名')),
  );
}

5.4 统计展示

Widget _buildTotalHoursCard() {
  return Card(
    color: Theme.of(context).colorScheme.primaryContainer,
    child: Padding(
      padding: const EdgeInsets.all(20),
      child: Row(
        children: [
          Expanded(
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('累计志愿时长'),
                Text(
                  '${_currentUser.totalHours}',
                  style: Theme.of(context).textTheme.headlineLarge,
                ),
              ],
            ),
          ),
          Column(
            children: [
              Container(
                width: 80,
                height: 80,
                decoration: BoxDecoration(
                  color: Theme.of(context).colorScheme.primary.withValues(alpha: 0.2),
                  borderRadius: BorderRadius.circular(40),
                ),
                child: Center(
                  child: Text('Lv.${_currentUser.level}'),
                ),
              ),
              Text(_currentUser.levelTitle),
            ],
          ),
        ],
      ),
    ),
  );
}

5.5 活动详情弹窗

void _showActivityDetail(VolunteerActivity activity) {
  showModalBottomSheet(
    context: context,
    isScrollControlled: true,
    builder: (context) => DraggableScrollableSheet(
      initialChildSize: 0.85,
      maxChildSize: 0.95,
      minChildSize: 0.5,
      expand: false,
      builder: (context, scrollController) => Container(
        padding: const EdgeInsets.all(20),
        child: ListView(
          controller: scrollController,
          children: [
            _buildActivityInfoCard(activity),
            _buildActivityDescription(activity),
            _buildRequirements(activity),
            FilledButton(
              onPressed: activity.isFull ? null : () => _registerActivity(activity),
              child: Text(activity.isFull ? '已满员' : '立即报名'),
            ),
          ],
        ),
      ),
    ),
  );
}

六、志愿服务知识拓展

6.1 志愿者等级体系

志愿者等级

一星志愿者
0-50小时

二星志愿者
50-100小时

三星志愿者
100-200小时

四星志愿者
200-500小时

五星志愿者
500小时以上

6.2 志愿服务类型分布

类型 占比 热门活动
社区服务 25% 社区清洁、便民服务
环境保护 20% 植树造林、垃圾分类
教育支援 15% 乡村支教、课业辅导
敬老爱老 15% 敬老院服务、居家养老
公益慈善 10% 爱心捐赠、扶贫帮困
其他 15% 赛事服务、文化传播

6.3 志愿服务发展趋势

志愿服务发展

数字化管理

专业化服务

社区化发展

国际化交流

在线报名

时长记录

证书认证

专业培训

技能认证

项目评估

社区志愿站

邻里互助

基层治理

6.4 志愿者权益保障

权益 说明
人身保险 活动期间意外伤害保险
时长认定 志愿服务时长官方认定
证书认证 志愿服务证书发放
培训机会 免费技能培训机会
表彰激励 优秀志愿者表彰奖励

七、扩展功能规划

7.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 活动列表功能 报名管理功能 记录统计功能 活动发布功能 签到打卡功能 数据持久化 证书生成功能 社交分享功能 组织管理功能 V1.0 基础版本 V1.1 增强版本 V1.2 进阶版本 志愿者活动应用开发计划

7.2 功能扩展建议

7.2.1 活动管理
功能 说明
活动发布 组织方发布活动
活动审核 平台审核机制
活动评价 参与者评价反馈
活动分享 分享到社交平台
7.2.2 签到打卡
功能 说明
位置签到 GPS定位签到
二维码签到 扫码签到
人脸识别 人脸验证签到
时长记录 自动记录时长
7.2.3 证书管理
功能 说明
电子证书 自动生成证书
证书验证 扫码验证真伪
证书下载 PDF格式下载
证书打印 打印服务对接

八、注意事项

8.1 开发注意事项

  1. 颜色处理:使用 withValues(alpha:) 替代已废弃的 withOpacity()

  2. 日期格式化:使用intl包的DateFormat进行日期格式化

  3. 状态同步:报名状态使用Set存储,便于快速查找

  4. 数据不可变:活动对象更新时创建新对象,保持数据不可变性

  5. 进度条颜色:根据是否满员动态改变进度条颜色

8.2 用户体验优化

🤝 用户体验建议 🤝

  • 活动信息清晰完整
  • 报名操作简单便捷
  • 统计数据直观易懂
  • 个人成就激励参与

8.3 常见问题

问题 原因 解决方案
报名状态不同步 setState未调用 检查状态更新逻辑
人数统计错误 未创建新对象 使用不可变数据模式
进度条颜色错误 条件判断错误 检查isFull逻辑
弹窗状态不同步 StatefulBuilder未使用 使用setModalState

九、运行说明

9.1 环境要求

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

9.2 运行命令

# 查看可用设备
flutter devices

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

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

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

十、总结

志愿者活动应用通过完善的功能设计,帮助志愿者和活动组织者实现志愿服务的数字化管理。应用支持多种类型的志愿活动展示,包括社区服务、环境保护、教育支援等八大类别,满足不同志愿者的参与需求。

活动详情页展示完整的活动信息,包括时间地点、主办单位、报名要求等,让志愿者全面了解活动内容。一键报名功能简化了参与流程,取消报名功能提供了灵活的调整空间。报名进度条直观展示招募情况,满员状态自动禁用报名按钮。

个人中心记录累计志愿时长、参与活动数量、获得徽章等成就,激励更多人参与志愿服务。统计页面通过图表展示类型分布和月度趋势,让志愿者了解自己的服务情况。志愿者等级体系根据累计时长自动升级,增强用户的成就感和参与热情。

界面设计采用绿色主题风格,体现公益与希望。活动卡片通过类型颜色区分不同类别,进度条根据状态动态变色。应用采用Material Design 3设计规范,遵循Flutter最佳实践,代码结构清晰,易于维护和扩展。

志愿服务,让爱传递!

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐