Flutter for OpenHarmony 实战:投票管理系统完整开发指南

Flutter for OpenHarmony 实战:投票管理系统完整开发指南

文章目录

  • [Flutter for OpenHarmony 实战:投票管理系统完整开发指南](#Flutter for OpenHarmony 实战:投票管理系统完整开发指南)
    • 摘要
    • 一、项目背景与功能概述
      • [1.1 投票系统的应用场景](#1.1 投票系统的应用场景)
      • [1.2 应用功能规划](#1.2 应用功能规划)
      • [1.3 投票规则说明](#1.3 投票规则说明)
    • 二、投票系统设计原则
      • [2.1 用户界面设计](#2.1 用户界面设计)
      • [2.2 数据流向设计](#2.2 数据流向设计)
    • 三、技术选型与架构设计
      • [3.1 核心技术栈](#3.1 核心技术栈)
      • [3.2 应用架构](#3.2 应用架构)
      • [3.3 状态管理设计](#3.3 状态管理设计)
    • 四、数据模型设计
      • [4.1 候选人数据类](#4.1 候选人数据类)
      • [4.2 选择状态管理](#4.2 选择状态管理)
    • 五、候选人管理界面
      • [5.1 界面布局设计](#5.1 界面布局设计)
      • [5.2 候选人解析逻辑](#5.2 候选人解析逻辑)
      • [5.3 取消按钮功能](#5.3 取消按钮功能)
      • [5.4 投票规则说明](#5.4 投票规则说明)
    • 六、投票界面实现
      • [6.1 候选人列表](#6.1 候选人列表)
      • [6.2 复选框状态管理](#6.2 复选框状态管理)
    • 七、统计信息展示
      • [7.1 统计卡片设计](#7.1 统计卡片设计)
      • [7.2 统计信息布局](#7.2 统计信息布局)
      • [7.3 操作按钮区域](#7.3 操作按钮区域)
    • 八、完整代码实现
      • [8.1 投票提交逻辑](#8.1 投票提交逻辑)
      • [8.2 排序功能](#8.2 排序功能)
      • [8.3 刷新重置功能](#8.3 刷新重置功能)
    • 九、运行效果与测试
      • [9.1 项目运行命令](#9.1 项目运行命令)
      • [9.2 功能测试清单](#9.2 功能测试清单)
    • 十、总结
    • 十、总结

摘要

投票管理系统是各类组织和活动中必不可少的应用工具。本文将详细介绍如何使用Flutter for OpenHarmony框架开发一款功能完整的投票管理系统。文章涵盖了复选框状态管理、选票验证逻辑、实时统计、数据排序等核心技术点。通过本文学习,读者将掌握Flutter在鸿蒙平台上开发交互式应用的方法,了解如何构建功能完善、用户友好的投票应用。


一、项目背景与功能概述

1.1 投票系统的应用场景

投票系统广泛应用于:

  • 班级干部选举
  • 公司决策投票
  • 活动评选
  • 意见调查
  • 民主评议

1.2 应用功能规划

功能模块 具体功能
候选人管理 输入候选人名单、确认、取消
投票功能 复选框选择、确定投票、刷新重置
选票验证 最多选3人、超过作废、不选为弃权
实时统计 总票数、有效票、废票、弃权票
排序功能 按票数排序显示候选人

1.3 投票规则说明

  • 每张选票最多可选择3位候选人
  • 选择超过3人,该票作废
  • 不选择任何候选人,视为弃权
  • 点击复选框选中/取消选中候选人

二、投票系统设计原则

2.1 用户界面设计

简洁性原则

  • 候选人设置阶段:清晰的多行输入框
  • 投票阶段:直观的复选框列表
  • 统计阶段:醒目的统计卡片

一致性原则

  • 颜色编码:绿色-有效票、红色-废票、灰色-弃权
  • 按钮样式统一
  • 交互反馈一致

2.2 数据流向设计


三、技术选型与架构设计

3.1 核心技术栈

状态管理

  • StatefulWidget管理组件状态
  • setState更新UI
  • Set数据结构存储选中状态

UI组件

  • TextField:候选人输入
  • CheckboxListTile:复选框列表
  • Card:统计卡片展示
  • ListView:候选人列表

数据处理

  • 正则表达式解析候选人
  • 集合操作处理选择状态
  • 排序算法实现票数排序

3.2 应用架构

复制代码
VotingSystemApp (应用根组件)
    └── VotingSystemPage (投票系统页面)
        ├── AppBar (导航栏 + 刷新按钮)
        ├── 候选人设置界面
        │   ├── 输入提示
        │   ├── 多行输入框
        │   ├── 确认/取消按钮
        │   └── 投票规则说明
        └── 投票界面
            ├── 候选人列表(复选框)
            └── 统计信息区域
                ├── 统计卡片(4个)
                └── 操作按钮(投票、排序)

3.3 状态管理设计

dart 复制代码
class _VotingSystemPageState extends State<VotingSystemPage> {
  final List<Candidate> _candidates = [];           // 候选人列表
  final Set<String> _selectedCandidates = {};       // 选中的候选人
  final TextEditingController _controller = TextEditingController();

  int _totalVotes = 0;      // 总选票数
  int _invalidVotes = 0;    // 废票数
  int _abstainedVotes = 0;  // 弃权票数

  bool _isVotingMode = false;  // 是否处于投票模式
}

四、数据模型设计

4.1 候选人数据类

dart 复制代码
class Candidate {
  String name;  // 候选人姓名
  int votes;    // 得票数

  Candidate({required this.name, this.votes = 0});
}

设计要点

  • name:候选人唯一标识
  • votes:初始值为0,投票时累加

4.2 选择状态管理

使用Set数据结构存储选中的候选人:

dart 复制代码
final Set<String> _selectedCandidates = {};

Set的优势

  • 自动去重
  • 高效查找
  • 方便添加/删除

五、候选人管理界面

5.1 界面布局设计

dart 复制代码
Widget _buildSetupInterface() {
  return Padding(
    padding: const EdgeInsets.all(24),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      children: [
        const Text('设置候选人名单'),
        const SizedBox(height: 16),
        const Text('请输入候选人姓名,用逗号或空格分隔'),
        const SizedBox(height: 16),
        TextField(
          controller: _candidatesController,
          maxLines: 5,
          decoration: const InputDecoration(
            labelText: '候选人名单',
            hintText: '例如:张三, 李四, 王五, 赵六',
            border: OutlineInputBorder(),
          ),
        ),
        // 按钮...
      ],
    ),
  );
}

5.2 候选人解析逻辑

dart 复制代码
void _confirmCandidates() {
  final text = _candidatesController.text.trim();
  if (text.isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('请输入候选人名单')),
    );
    return;
  }

  // 按逗号或空格分隔
  final names = text.split(RegExp('[,,\\s]+'));
  final validNames = names.where((name) => name.trim().isNotEmpty).toList();

  if (validNames.isEmpty) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('候选人名单不能为空')),
    );
    return;
  }

  setState(() {
    _candidates.clear();
    for (var name in validNames) {
      _candidates.add(Candidate(name: name.trim()));
    }
    _isVotingMode = true;
    _resetStatistics();
  });
}

解析规则

  • 支持中英文逗号分隔
  • 支持空格分隔
  • 自动过滤空字符串
  • 去除首尾空格

5.3 取消按钮功能

dart 复制代码
void _cancelCandidates() {
  _candidatesController.clear();
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('已清空输入')),
  );
}

5.4 投票规则说明

使用Card组件展示投票规则:

dart 复制代码
Card(
  color: Colors.blue.shade50,
  child: Padding(
    padding: const EdgeInsets.all(16),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Row(
          children: [
            Icon(Icons.info_outline, color: Colors.blue),
            const SizedBox(width: 8),
            const Text('投票规则'),
          ],
        ),
        const SizedBox(height: 12),
        const Text('• 每张选票最多可选3人'),
        const Text('• 选择超过3人视为废票'),
        const Text('• 不选择任何候选人视为弃权'),
        const Text('• 点击复选框进行投票'),
      ],
    ),
  ),
)

六、投票界面实现

6.1 候选人列表

使用ListView.builder + CheckboxListTile:

dart 复制代码
Expanded(
  child: ListView.builder(
    padding: const EdgeInsets.all(16),
    itemCount: _candidates.length,
    itemBuilder: (context, index) {
      final candidate = _candidates[index];
      final isSelected = _selectedCandidates.contains(candidate.name);

      return Card(
        margin: const EdgeInsets.only(bottom: 12),
        child: CheckboxListTile(
          title: Text(
            candidate.name,
            style: const TextStyle(fontSize: 18),
          ),
          subtitle: Text('得票: ${candidate.votes}'),
          value: isSelected,
          onChanged: (bool? value) {
            setState(() {
              if (value == true) {
                _selectedCandidates.add(candidate.name);
              } else {
                _selectedCandidates.remove(candidate.name);
              }
            });
          },
          controlAffinity: ListTileControlAffinity.leading,
          contentPadding: const EdgeInsets.all(16),
        ),
      );
    },
  ),
)

CheckboxListTile属性

  • title:候选人姓名
  • subtitle:当前得票数
  • value:是否选中
  • onChanged:选中状态变化回调
  • controlAffinity:复选框位置(左侧)

6.2 复选框状态管理

dart 复制代码
onChanged: (bool? value) {
  setState(() {
    if (value == true) {
      _selectedCandidates.add(candidate.name);
    } else {
      _selectedCandidates.remove(candidate.name);
    }
  });
}

状态更新流程

  1. 用户点击复选框
  2. 触发onChanged回调
  3. 更新_selectedCandidates集合
  4. 调用setState刷新UI
  5. 重新渲染显示新状态

七、统计信息展示

7.1 统计卡片设计

dart 复制代码
Widget _buildStatCard(String title, String value, Color color) {
  return Expanded(
    child: Card(
      color: color,
      child: Padding(
        padding: const EdgeInsets.all(12),
        child: Column(
          children: [
            Text(
              title,
              style: const TextStyle(
                fontSize: 12,
                color: Colors.white,
              ),
            ),
            const SizedBox(height: 4),
            Text(
              value,
              style: const TextStyle(
                fontSize: 24,
                fontWeight: FontWeight.bold,
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
    ),
  );
}

7.2 统计信息布局

dart 复制代码
Row(
  children: [
    _buildStatCard('总选票', '$_totalVotes', Colors.blue),
    const SizedBox(width: 12),
    _buildStatCard('有效票', '${_totalVotes - _invalidVotes - _abstainedVotes}', Colors.green),
    const SizedBox(width: 12),
    _buildStatCard('废票', '$_invalidVotes', Colors.red),
    const SizedBox(width: 12),
    _buildStatCard('弃权', '$_abstainedVotes', Colors.grey),
  ],
)

颜色编码

  • 蓝色:总选票
  • 绿色:有效票
  • 红色:废票
  • 灰色:弃权票

7.3 操作按钮区域

dart 复制代码
Row(
  children: [
    Expanded(
      child: ElevatedButton.icon(
        onPressed: _submitVote,
        icon: const Icon(Icons.how_to_vote),
        label: const Text('确定投票'),
        style: ElevatedButton.styleFrom(
          padding: const EdgeInsets.symmetric(vertical: 12),
          backgroundColor: Colors.green,
        ),
      ),
    ),
    const SizedBox(width: 12),
    Expanded(
      child: ElevatedButton.icon(
        onPressed: _sortByVotes,
        icon: const Icon(Icons.sort),
        label: const Text('按票数排序'),
        style: ElevatedButton.styleFrom(
          padding: const EdgeInsets.symmetric(vertical: 12),
        ),
      ),
    ),
  ],
)

八、完整代码实现

8.1 投票提交逻辑

dart 复制代码
void _submitVote() {
  // 情况1:弃权票
  if (_selectedCandidates.isEmpty) {
    setState(() {
      _abstainedVotes++;
      _totalVotes++;
      _selectedCandidates.clear();
    });

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('弃权票已记录')),
    );
    return;
  }

  // 情况2:废票(选择超过3人)
  if (_selectedCandidates.length > 3) {
    setState(() {
      _invalidVotes++;
      _totalVotes++;
      _selectedCandidates.clear();
    });

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(
        content: Text('选择超过3人,该票作废'),
        backgroundColor: Colors.red,
      ),
    );
    return;
  }

  // 情况3:有效票
  setState(() {
    for (var candidate in _candidates) {
      if (_selectedCandidates.contains(candidate.name)) {
        candidate.votes++;
      }
    }
    _totalVotes++;
    _selectedCandidates.clear();
  });

  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('投票成功')),
  );
}

验证流程

  1. 检查是否为空(弃权)
  2. 检查是否超过3人(废票)
  3. 为选中的候选人增加票数
  4. 清空选择状态

8.2 排序功能

dart 复制代码
void _sortByVotes() {
  setState(() {
    _candidates.sort((a, b) => b.votes.compareTo(a.votes));
  });

  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('已按票数排序')),
  );
}

排序规则

  • 按票数降序排列
  • 票数相同时保持原有顺序

8.3 刷新重置功能

dart 复制代码
void _refreshSystem() {
  setState(() {
    _candidates.clear();
    _selectedCandidates.clear();
    _candidatesController.clear();
    _isVotingMode = false;
    _resetStatistics();
  });

  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('系统已重置')),
  );
}

void _resetStatistics() {
  _totalVotes = 0;
  _invalidVotes = 0;
  _abstainedVotes = 0;
  for (var candidate in _candidates) {
    candidate.votes = 0;
  }
}

九、运行效果与测试

9.1 项目运行命令

bash 复制代码
cd E:\HarmonyOS\oh.code\voting_system
flutter run -d ohos

9.2 功能测试清单

候选人设置测试

  • 输入单个候选人
  • 输入多个候选人(逗号分隔)
  • 输入多个候选人(空格分隔)
  • 混合分隔符输入
  • 空输入验证
  • 取消按钮清空输入

投票功能测试

  • 选中单个候选人
  • 选中多个候选人(1-3人)
  • 选中超过3人(废票)
  • 不选中任何候选人(弃权)

统计功能测试

  • 有效票正确统计
  • 废票正确统计
  • 弃权票正确统计
  • 总票数正确计算

排序功能测试

  • 按票数降序排列
  • 排序后票数正确显示

重置功能测试

  • 刷新后回到设置界面
  • 所有数据清空

十、总结

本文详细介绍了使用Flutter for OpenHarmony开发投票管理系统的完整过程,涵盖了以下核心技术点:

  1. 复选框状态管理:CheckboxListTile + Set数据结构
  2. 选票验证逻辑:三层判断(弃权、废票、有效票)
  3. 实时统计机制:动态更新票数统计
  4. 排序算法:列表排序实现
  5. UI交互设计:直观的操作界面

这个项目展示了Flutter在交互式应用开发中的完整流程,代码结构清晰,功能完整。读者可以基于此项目添加更多功能,如:

  • 候选人图片显示
  • 投票时间限制
  • 历史记录查看
  • 导出投票结果
  • 多轮投票支持

通过本文的学习,读者应该能够独立开发类似的交互式应用,掌握Flutter在鸿蒙平台上的状态管理和UI交互技巧。


欢迎加入开源鸿蒙跨平台社区 : 开源鸿蒙跨平台开发者社区

  • 不选中任何候选人(弃权)

统计功能测试

  • 有效票正确统计
  • 废票正确统计
  • 弃权票正确统计
  • 总票数正确计算

排序功能测试

  • 按票数降序排列
  • 排序后票数正确显示

重置功能测试

  • 刷新后回到设置界面
  • 所有数据清空

十、总结

本文详细介绍了使用Flutter for OpenHarmony开发投票管理系统的完整过程,涵盖了以下核心技术点:

  1. 复选框状态管理:CheckboxListTile + Set数据结构
  2. 选票验证逻辑:三层判断(弃权、废票、有效票)
  3. 实时统计机制:动态更新票数统计
  4. 排序算法:列表排序实现
  5. UI交互设计:直观的操作界面

这个项目展示了Flutter在交互式应用开发中的完整流程,代码结构清晰,功能完整。读者可以基于此项目添加更多功能,如:

  • 候选人图片显示
  • 投票时间限制
  • 历史记录查看
  • 导出投票结果
  • 多轮投票支持

通过本文的学习,读者应该能够独立开发类似的交互式应用,掌握Flutter在鸿蒙平台上的状态管理和UI交互技巧。


欢迎加入开源鸿蒙跨平台社区 : 开源鸿蒙跨平台开发者社区

相关推荐
ujainu4 小时前
Flutter + OpenHarmony 游戏开发进阶:粒子系统初探——简易爆炸与得分飞字
flutter·游戏·openharmony
2501_944448004 小时前
Flutter for OpenHarmony衣橱管家App实战:支持我们功能实现
android·javascript·flutter
灰灰勇闯IT12 小时前
Flutter for OpenHarmony:自定义 Paint 绘图 —— 释放 Canvas 的创造力
flutter
2601_9498333913 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter
牛马11115 小时前
Flutter OverlayEntry
flutter
2603_9494621015 小时前
Flutter for OpenHarmony社团管理App实战:预算管理实现
android·javascript·flutter
2601_9499757917 小时前
Flutter for OpenHarmony艺考真题题库+帮助中心实现
flutter
子春一20 小时前
Flutter for OpenHarmony:构建一个 Flutter 井字棋游戏,深入解析状态驱动逻辑、胜利判定与极简交互设计
flutter·游戏·交互
雨季66620 小时前
Flutter 三端应用实战:OpenHarmony “极简手势轨迹球”——指尖与屏幕的诗意对话
开发语言·javascript·flutter