Flutter校园洗衣房打卡应用开发教程

项目简介

校园洗衣房打卡是一款专为高校学生设计的智能洗衣管理应用,解决传统洗衣房使用中的诸多痛点。应用提供实时洗衣机状态查看、在线预约、使用记录管理、智能提醒等功能,让学生能够随时随地掌握洗衣房动态,合理安排洗衣时间,提升校园生活便利性。
运行效果图
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

核心功能特性

  • 实时状态监控:实时显示所有洗衣机的使用状态(空闲/使用中/已预约/故障/维护中)
  • 在线预约系统:支持提前预约空闲洗衣机,避免排队等待
  • 智能筛选功能:按楼栋、楼层、状态、类型等多维度筛选洗衣机
  • 使用记录管理:完整记录每次洗衣历史,包含时长、费用、模式等信息
  • 智能提醒通知:洗涤完成提醒、预约到期提醒、机器空闲提醒
  • 余额管理系统:在线充值、消费记录、余额查询
  • 数据统计分析:使用频率统计、费用分析、趋势图表展示
  • 收藏功能:收藏常用洗衣机,快速访问

技术架构

开发环境

  • 框架:Flutter 3.x
  • 开发语言:Dart
  • UI组件:Material Design 3
  • 状态管理:StatefulWidget + setState
  • 动画效果:AnimationController + FadeTransition
  • 数据存储:本地模拟数据 + SharedPreferences

项目结构

lib/
├── main.dart                 # 应用入口和主要逻辑
├── models/                   # 数据模型
│   ├── washing_machine.dart  # 洗衣机模型
│   ├── reservation.dart      # 预约模型
│   ├── usage_record.dart     # 使用记录模型
│   └── user.dart             # 用户模型
├── pages/                    # 页面组件
│   ├── home_page.dart        # 首页
│   ├── reservations_page.dart # 预约页面
│   ├── records_page.dart     # 记录页面
│   └── profile_page.dart     # 个人中心
└── widgets/                  # 自定义组件
    ├── machine_card.dart     # 洗衣机卡片组件
    ├── status_badge.dart     # 状态标签组件
    └── stats_card.dart       # 统计卡片组件

数据模型设计

洗衣机模型(WashingMachine)

洗衣机模型是应用的核心数据结构,记录每台洗衣机的详细信息:

class WashingMachine {
  final String id;              // 洗衣机唯一标识
  final String name;            // 名称(如:1号机)
  final String location;        // 位置描述
  final String building;        // 楼栋
  final int floor;              // 楼层
  final String area;            // 区域
  final MachineType type;       // 类型:洗衣机/烘干机/洗烘一体
  final double capacity;        // 容量(kg)
  MachineStatus status;         // 状态:空闲/使用中/已预约/故障/维护中
  final double price;           // 价格(元/次)
  int remainingTime;            // 剩余时间(分钟)
  DateTime? startTime;          // 开始时间
  DateTime? endTime;            // 预计结束时间
  String? currentUser;          // 当前使用者
  bool isFavorite;              // 是否收藏
  final String brand;           // 品牌
  final String model;           // 型号
  final int powerWatt;          // 功率(瓦)
  final List<String> features;  // 功能特性
  final double rating;          // 评分
  final int usageCount;         // 使用次数
}

enum MachineType {
  washer,    // 洗衣机
  dryer,     // 烘干机
  combo      // 洗烘一体
}

enum MachineStatus {
  idle,       // 空闲
  inUse,      // 使用中
  reserved,   // 已预约
  fault,      // 故障
  maintenance // 维护中
}

预约模型(Reservation)

预约模型记录用户的预约信息:

class Reservation {
  final String id;              // 预约唯一标识
  final String machineId;       // 关联洗衣机ID
  final String machineName;     // 洗衣机名称
  final String userId;          // 用户ID
  final String userName;        // 用户名称
  final DateTime reservationTime; // 预约时间
  final DateTime startTime;     // 开始时间
  final DateTime endTime;       // 结束时间
  ReservationStatus status;     // 状态:待使用/使用中/已完成/已取消/已过期
  final double estimatedCost;   // 预计费用
  final String notes;           // 备注
  final DateTime createdAt;     // 创建时间
}

enum ReservationStatus {
  pending,    // 待使用
  active,     // 使用中
  completed,  // 已完成
  cancelled,  // 已取消
  expired     // 已过期
}

使用记录模型(UsageRecord)

使用记录模型详细记录每次洗衣的完整信息:

class UsageRecord {
  final String id;              // 记录唯一标识
  final String machineId;       // 关联洗衣机ID
  final String machineName;     // 洗衣机名称
  final String userId;          // 用户ID
  final DateTime startTime;     // 开始时间
  final DateTime endTime;       // 结束时间
  final int duration;           // 使用时长(分钟)
  final double cost;            // 费用
  final String washMode;        // 洗涤模式:标准/快洗/强力/轻柔
  final bool isCompleted;       // 是否完成
  double rating;                // 评分
  String feedback;              // 反馈
  final List<String> photos;    // 照片
}

用户模型(User)

用户模型记录用户的个人信息和使用统计:

class User {
  final String id;              // 用户唯一标识
  final String name;            // 姓名
  final String studentId;       // 学号
  final String phone;           // 手机号
  final String building;        // 楼栋
  final String room;            // 房间号
  double balance;               // 余额
  final List<String> favoriteMachines; // 收藏的洗衣机
  int totalUsageCount;          // 总使用次数
  double totalSpent;            // 累计消费
  int points;                   // 积分
}

界面设计

主界面布局

应用采用底部导航栏设计,包含四个主要页面:

  1. 首页:洗衣机状态总览和快速筛选
  2. 预约:我的预约列表和预约管理
  3. 记录:使用历史记录和统计分析
  4. 我的:个人中心和设置

色彩方案

  • 主色调:蓝色系(#2196F3)- 代表清洁、科技感
  • 辅助色
    • 绿色(#4CAF50)- 空闲状态
    • 橙色(#FF9800)- 使用中状态
    • 蓝色(#2196F3)- 已预约状态
    • 红色(#F44336)- 故障状态
    • 灰色(#9E9E9E)- 维护中状态

状态指示设计

空闲    ● 绿色徽章 + "空闲"文字
使用中  ● 橙色徽章 + "使用中"文字 + 剩余时间
已预约  ● 蓝色徽章 + "已预约"文字
故障    ● 红色徽章 + "故障"文字
维护中  ● 灰色徽章 + "维护中"文字

核心功能实现

1. 首页洗衣机列表

首页展示所有洗衣机的实时状态,支持快速筛选和搜索:

顶部统计栏

  • 显示空闲、使用中、已预约洗衣机的数量
  • 使用渐变背景和卡片布局
  • 数字大字体突出显示

快速筛选栏

  • 横向滚动的筛选标签
  • 支持按状态筛选(全部/空闲/使用中/已预约)
  • 选中状态高亮显示

洗衣机卡片

  • 显示洗衣机名称、位置、状态
  • 使用中的机器显示剩余时间和进度条
  • 空闲机器显示价格和"立即预约"按钮
  • 点击卡片查看详细信息
Widget _buildMachineCard(WashingMachine machine) {
  return Card(
    elevation: 2,
    margin: EdgeInsets.only(bottom: 12),
    child: InkWell(
      onTap: () => _showMachineDetail(machine),
      child: Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 标题行:图标 + 名称 + 状态徽章
            Row(
              children: [
                Icon(Icons.local_laundry_service, color: Colors.blue),
                SizedBox(width: 12),
                Expanded(
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(machine.name, style: TextStyle(fontWeight: FontWeight.bold)),
                      Text(machine.location, style: TextStyle(color: Colors.grey)),
                    ],
                  ),
                ),
                _buildStatusBadge(machine.status),
              ],
            ),
            
            // 使用中显示剩余时间
            if (machine.status == MachineStatus.inUse) ...[
              SizedBox(height: 12),
              Container(
                padding: EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.orange.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Row(
                  children: [
                    Icon(Icons.timer, color: Colors.orange),
                    SizedBox(width: 8),
                    Text('剩余时间:${machine.remainingTime}分钟'),
                  ],
                ),
              ),
            ],
            
            // 空闲显示价格和预约按钮
            if (machine.status == MachineStatus.idle) ...[
              SizedBox(height: 8),
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text(${machine.price}/次', 
                    style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
                  ElevatedButton(
                    onPressed: () => _showReservationDialog(machine),
                    child: Text('立即预约'),
                  ),
                ],
              ),
            ],
          ],
        ),
      ),
    ),
  );
}

2. 预约功能

预约流程

  1. 用户选择空闲的洗衣机
  2. 选择预约时间(日期 + 时间)
  3. 确认预约信息和费用
  4. 扣除预约押金(5元)
  5. 生成预约记录
  6. 发送预约成功通知

预约对话框

void _showReservationDialog(WashingMachine machine) {
  DateTime selectedDate = DateTime.now();
  TimeOfDay selectedTime = TimeOfDay.now();
  
  showDialog(
    context: context,
    builder: (context) => StatefulBuilder(
      builder: (context, setState) => AlertDialog(
        title: Text('预约 ${machine.name}'),
        content: SingleChildScrollView(
          child: Column(
            mainAxisSize: MainAxisSize.min,
            children: [
              // 机器信息
              ListTile(
                leading: Icon(Icons.local_laundry_service),
                title: Text(machine.name),
                subtitle: Text(machine.location),
              ),
              
              Divider(),
              
              // 日期选择
              ListTile(
                leading: Icon(Icons.calendar_today),
                title: Text('预约日期'),
                subtitle: Text(_formatDate(selectedDate)),
                onTap: () async {
                  final date = await showDatePicker(
                    context: context,
                    initialDate: selectedDate,
                    firstDate: DateTime.now(),
                    lastDate: DateTime.now().add(Duration(days: 7)),
                  );
                  if (date != null) {
                    setState(() => selectedDate = date);
                  }
                },
              ),
              
              // 时间选择
              ListTile(
                leading: Icon(Icons.access_time),
                title: Text('预约时间'),
                subtitle: Text(selectedTime.format(context)),
                onTap: () async {
                  final time = await showTimePicker(
                    context: context,
                    initialTime: selectedTime,
                  );
                  if (time != null) {
                    setState(() => selectedTime = time);
                  }
                },
              ),
              
              // 预计费用
              Container(
                padding: EdgeInsets.all(12),
                decoration: BoxDecoration(
                  color: Colors.blue.withOpacity(0.1),
                  borderRadius: BorderRadius.circular(8),
                ),
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Text('预计费用'),
                    Text(${machine.price.toStringAsFixed(2)}', 
                      style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
                  ],
                ),
              ),
            ],
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: Text('取消'),
          ),
          ElevatedButton(
            onPressed: () {
              _confirmReservation(machine, selectedDate, selectedTime);
              Navigator.pop(context);
            },
            child: Text('确认预约'),
          ),
        ],
      ),
    ),
  );
}

3. 使用记录管理

记录列表展示

  • 按时间倒序排列
  • 显示洗衣机名称、时间、费用
  • 显示洗涤模式和时长
  • 支持评分和反馈

使用统计卡片

Widget _buildUsageStatsCard() {
  final totalRecords = _usageRecords.length;
  final totalCost = _usageRecords.fold(0.0, (sum, r) => sum + r.cost);
  final totalDuration = _usageRecords.fold(0, (sum, r) => sum + r.duration);
  final avgCost = totalRecords > 0 ? totalCost / totalRecords : 0.0;
  
  return Card(
    margin: EdgeInsets.all(16),
    elevation: 4,
    child: Padding(
      padding: EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text('使用统计', style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          SizedBox(height: 16),
          Row(
            children: [
              Expanded(child: _buildStatItem('总次数', '$totalRecords次', Icons.repeat)),
              Expanded(child: _buildStatItem('总费用', ${totalCost.toStringAsFixed(2)}', Icons.attach_money)),
            ],
          ),
          SizedBox(height: 12),
          Row(
            children: [
              Expanded(child: _buildStatItem('总时长', '${totalDuration}分钟', Icons.timer)),
              Expanded(child: _buildStatItem('平均费用', ${avgCost.toStringAsFixed(2)}', Icons.trending_up)),
            ],
          ),
        ],
      ),
    ),
  );
}

4. 个人中心

用户信息展示

  • 头像、姓名、学号
  • 余额显示和充值按钮
  • 使用统计(次数、消费、积分)

功能菜单

  • 我的收藏
  • 优惠券
  • 使用记录
  • 消息通知
  • 设置
  • 帮助与反馈
  • 关于
Widget _buildProfilePage() {
  return SingleChildScrollView(
    child: Column(
      children: [
        // 用户信息头部
        Container(
          padding: EdgeInsets.all(20),
          decoration: BoxDecoration(
            gradient: LinearGradient(
              colors: [Colors.blue.shade400, Colors.blue.shade600],
            ),
          ),
          child: Column(
            children: [
              CircleAvatar(
                radius: 40,
                backgroundColor: Colors.white,
                child: Icon(Icons.person, size: 40, color: Colors.blue),
              ),
              SizedBox(height: 12),
              Text(_currentUser.name, 
                style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white)),
              Text('学号:${_currentUser.studentId}', 
                style: TextStyle(color: Colors.white70)),
              SizedBox(height: 16),
              
              // 余额卡片
              Container(
                padding: EdgeInsets.symmetric(horizontal: 20, vertical: 12),
                decoration: BoxDecoration(
                  color: Colors.white,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Icon(Icons.account_balance_wallet, color: Colors.blue),
                    SizedBox(width: 8),
                    Text('余额:'),
                    Text(${_currentUser.balance.toStringAsFixed(2)}', 
                      style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold)),
                    SizedBox(width: 12),
                    ElevatedButton(
                      onPressed: _showRechargeDialog,
                      child: Text('充值'),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
        
        // 统计信息
        Padding(
          padding: EdgeInsets.all(16),
          child: Row(
            children: [
              Expanded(child: _buildStatCard('使用次数', '${_currentUser.totalUsageCount}', Icons.repeat)),
              SizedBox(width: 12),
              Expanded(child: _buildStatCard('累计消费', ${_currentUser.totalSpent.toStringAsFixed(0)}', Icons.attach_money)),
              SizedBox(width: 12),
              Expanded(child: _buildStatCard('积分', '${_currentUser.points}', Icons.stars)),
            ],
          ),
        ),
        
        // 功能列表
        _buildMenuList(),
      ],
    ),
  );
}

5. 智能提醒系统

提醒类型

  • 洗涤完成提醒:洗衣完成后立即通知
  • 预约到期提醒:预约时间前30分钟提醒
  • 机器空闲提醒:收藏的机器空闲时通知
  • 余额不足提醒:余额低于10元时提醒

提醒实现

void _sendReminder(String title, String message) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
      content: Row(
        children: [
          Icon(Icons.notifications, color: Colors.white),
          SizedBox(width: 8),
          Expanded(child: Text(message)),
        ],
      ),
      action: SnackBarAction(
        label: '查看',
        onPressed: () {
          // 跳转到相关页面
        },
      ),
      duration: Duration(seconds: 5),
    ),
  );
}

// 洗涤完成提醒
void _sendCompletionNotification(WashingMachine machine) {
  _sendReminder(
    '洗涤完成',
    '${machine.name}洗涤已完成,请及时取衣',
  );
}

// 预约到期提醒
void _sendReservationReminder(Reservation reservation) {
  final timeUntilStart = reservation.startTime.difference(DateTime.now());
  if (timeUntilStart.inMinutes <= 30 && timeUntilStart.inMinutes > 0) {
    _sendReminder(
      '预约提醒',
      '您预约的${reservation.machineName}即将开始,请尽快到达',
    );
  }
}

6. 实时状态更新

使用定时器模拟洗衣机状态的实时更新:

Timer? _statusUpdateTimer;

void _startStatusUpdates() {
  _statusUpdateTimer = Timer.periodic(Duration(seconds: 30), (timer) {
    setState(() {
      for (var machine in _machines) {
        if (machine.status == MachineStatus.inUse && machine.remainingTime > 0) {
          // 更新剩余时间
          machine.remainingTime -= 1;
          
          // 如果时间到了,更新状态为空闲
          if (machine.remainingTime <= 0) {
            machine.status = MachineStatus.idle;
            machine.remainingTime = 0;
            machine.currentUser = null;
            _sendCompletionNotification(machine);
          }
        }
      }
    });
  });
}


void dispose() {
  _statusUpdateTimer?.cancel();
  super.dispose();
}

数据初始化

示例数据

应用内置了完整的示例数据,包括多台洗衣机、预约记录和使用记录:

void _initializeData() {
  // 初始化当前用户
  _currentUser = User(
    id: 'user001',
    name: '张三',
    studentId: '2021001234',
    phone: '13800138000',
    building: '1号楼',
    room: '301',
    balance: 50.0,
    favoriteMachines: ['wm001', 'wm003'],
    totalUsageCount: 15,
    totalSpent: 75.0,
    points: 150,
  );

  // 初始化洗衣机数据
  _machines = [
    WashingMachine(
      id: 'wm001',
      name: '1号洗衣机',
      location: '1号楼 1楼 A区',
      building: '1号楼',
      floor: 1,
      area: 'A区',
      type: MachineType.washer,
      capacity: 8.0,
      status: MachineStatus.idle,
      price: 3.0,
      remainingTime: 0,
      isFavorite: true,
      brand: '海尔',
      model: 'XQG80-B1426',
      powerWatt: 1800,
      features: ['标准洗', '快洗', '强力洗', '轻柔洗'],
      rating: 4.5,
      usageCount: 156,
    ),
    WashingMachine(
      id: 'wm002',
      name: '2号洗衣机',
      location: '1号楼 1楼 A区',
      building: '1号楼',
      floor: 1,
      area: 'A区',
      type: MachineType.washer,
      capacity: 8.0,
      status: MachineStatus.inUse,
      price: 3.0,
      remainingTime: 25,
      startTime: DateTime.now().subtract(Duration(minutes: 20)),
      endTime: DateTime.now().add(Duration(minutes: 25)),
      currentUser: '李四',
      isFavorite: false,
      brand: '小天鹅',
      model: 'TB80V23H',
      powerWatt: 1600,
      features: ['标准洗', '快洗', '节能洗'],
      rating: 4.3,
      usageCount: 142,
    ),
    WashingMachine(
      id: 'wm003',
      name: '3号烘干机',
      location: '1号楼 1楼 B区',
      building: '1号楼',
      floor: 1,
      area: 'B区',
      type: MachineType.dryer,
      capacity: 6.0,
      status: MachineStatus.idle,
      price: 2.5,
      remainingTime: 0,
      isFavorite: true,
      brand: '美的',
      model: 'MH60-Z01',
      powerWatt: 2000,
      features: ['标准烘干', '快速烘干', '低温烘干'],
      rating: 4.6,
      usageCount: 98,
    ),
    WashingMachine(
      id: 'wm004',
      name: '4号洗衣机',
      location: '1号楼 2楼 A区',
      building: '1号楼',
      floor: 2,
      area: 'A区',
      type: MachineType.washer,
      capacity: 10.0,
      status: MachineStatus.reserved,
      price: 4.0,
      remainingTime: 0,
      isFavorite: false,
      brand: '海尔',
      model: 'XQG100-B1426',
      powerWatt: 2000,
      features: ['标准洗', '快洗', '强力洗', '轻柔洗', '羊毛洗'],
      rating: 4.7,
      usageCount: 203,
    ),
    WashingMachine(
      id: 'wm005',
      name: '5号洗衣机',
      location: '2号楼 1楼 A区',
      building: '2号楼',
      floor: 1,
      area: 'A区',
      type: MachineType.combo,
      capacity: 8.0,
      status: MachineStatus.idle,
      price: 5.0,
      remainingTime: 0,
      isFavorite: false,
      brand: 'LG',
      model: 'FLW10G4W',
      powerWatt: 2200,
      features: ['洗烘一体', '蒸汽除菌', '智能投放'],
      rating: 4.8,
      usageCount: 187,
    ),
  ];

  // 初始化预约记录
  _reservations = [
    Reservation(
      id: 'res001',
      machineId: 'wm004',
      machineName: '4号洗衣机',
      userId: 'user001',
      userName: '张三',
      reservationTime: DateTime.now().subtract(Duration(hours: 2)),
      startTime: DateTime.now().add(Duration(minutes: 30)),
      endTime: DateTime.now().add(Duration(minutes: 75)),
      status: ReservationStatus.pending,
      estimatedCost: 4.0,
      notes: '',
      createdAt: DateTime.now().subtract(Duration(hours: 2)),
    ),
  ];

  // 初始化使用记录
  _usageRecords = [
    UsageRecord(
      id: 'ur001',
      machineId: 'wm001',
      machineName: '1号洗衣机',
      userId: 'user001',
      startTime: DateTime.now().subtract(Duration(days: 1, hours: 2)),
      endTime: DateTime.now().subtract(Duration(days: 1, hours: 1, minutes: 15)),
      duration: 45,
      cost: 3.0,
      washMode: '标准洗',
      isCompleted: true,
      rating: 5.0,
      feedback: '洗得很干净',
      photos: [],
    ),
    UsageRecord(
      id: 'ur002',
      machineId: 'wm003',
      machineName: '3号烘干机',
      userId: 'user001',
      startTime: DateTime.now().subtract(Duration(days: 2, hours: 3)),
      endTime: DateTime.now().subtract(Duration(days: 2, hours: 2, minutes: 30)),
      duration: 30,
      cost: 2.5,
      washMode: '标准烘干',
      isCompleted: true,
      rating: 4.5,
      feedback: '烘干效果不错',
      photos: [],
    ),
    UsageRecord(
      id: 'ur003',
      machineId: 'wm001',
      machineName: '1号洗衣机',
      userId: 'user001',
      startTime: DateTime.now().subtract(Duration(days: 5, hours: 1)),
      endTime: DateTime.now().subtract(Duration(days: 5, minutes: 15)),
      duration: 45,
      cost: 3.0,
      washMode: '快洗',
      isCompleted: true,
      rating: 4.0,
      feedback: '',
      photos: [],
    ),
  ];
}

辅助方法

工具函数

// 获取洗衣机图标
IconData _getMachineIcon(MachineType type) {
  switch (type) {
    case MachineType.washer:
      return Icons.local_laundry_service;
    case MachineType.dryer:
      return Icons.dry_cleaning;
    case MachineType.combo:
      return Icons.wash;
  }
}

// 获取状态颜色
Color _getStatusColor(MachineStatus status) {
  switch (status) {
    case MachineStatus.idle:
      return Colors.green;
    case MachineStatus.inUse:
      return Colors.orange;
    case MachineStatus.reserved:
      return Colors.blue;
    case MachineStatus.fault:
      return Colors.red;
    case MachineStatus.maintenance:
      return Colors.grey;
  }
}

// 格式化日期
String _formatDate(DateTime date) {
  return '${date.year}-${date.month.toString().padLeft(2, '0')}-${date.day.toString().padLeft(2, '0')}';
}

// 格式化日期时间
String _formatDateTime(DateTime dateTime) {
  return '${_formatDate(dateTime)} ${dateTime.hour.toString().padLeft(2, '0')}:${dateTime.minute.toString().padLeft(2, '0')}';
}

// 格式化时间
String _formatTime(DateTime time) {
  return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}';
}

// 获取筛选后的洗衣机列表
List<WashingMachine> _getFilteredMachines() {
  return _machines.where((machine) {
    // 按状态筛选
    if (_selectedStatus != null && machine.status != _selectedStatus) {
      return false;
    }
    
    // 按楼栋筛选
    if (_selectedBuilding != null && machine.building != _selectedBuilding) {
      return false;
    }
    
    // 按楼层筛选
    if (_selectedFloor != null && machine.floor != _selectedFloor) {
      return false;
    }
    
    // 搜索关键词
    if (_searchQuery.isNotEmpty) {
      final query = _searchQuery.toLowerCase();
      return machine.name.toLowerCase().contains(query) ||
             machine.location.toLowerCase().contains(query);
    }
    
    return true;
  }).toList();
}

性能优化

列表优化

使用ListView.builder而不是ListView,实现按需加载:

ListView.builder(
  itemCount: machines.length,
  itemBuilder: (context, index) {
    return _buildMachineCard(machines[index]);
  },
  // 添加缓存范围
  cacheExtent: 500,
)

动画优化

使用FadeTransition实现页面切换动画:

FadeTransition(
  opacity: _fadeAnimation,
  child: IndexedStack(
    index: _selectedIndex,
    children: [
      _buildHomePage(),
      _buildReservationsPage(),
      _buildRecordsPage(),
      _buildProfilePage(),
    ],
  ),
)

状态管理优化

合理使用setState,只更新需要刷新的部分:

// 只更新特定洗衣机的状态
void _updateMachineStatus(String machineId, MachineStatus status) {
  setState(() {
    final index = _machines.indexWhere((m) => m.id == machineId);
    if (index != -1) {
      _machines[index].status = status;
    }
  });
}

扩展功能建议

1. 支付功能

  • 集成微信支付、支付宝
  • 支持校园卡支付
  • 优惠券和折扣码

2. 社交功能

  • 用户评价和评分
  • 使用心得分享
  • 好友互助功能

3. 智能推荐

  • AI预测空闲时段
  • 推荐最佳洗涤模式
  • 个性化使用建议

4. 管理端功能

  • 洗衣机远程监控
  • 故障预警系统
  • 数据统计分析
  • 用户管理

5. 增值服务

  • 洗衣液自动售卖
  • 衣物寄存服务
  • 专业洗护服务
  • 上门取送服务

常见问题

Q1: 如何处理洗衣机状态的实时更新?

A: 本项目使用定时器模拟实时更新。实际项目中建议使用WebSocket或Server-Sent Events实现真正的实时通信。

Q2: 如何保证预约不冲突?

A: 在服务端实现分布式锁机制,确保同一时间段同一台洗衣机只能被一个用户预约。客户端在提交预约前也应检查最新状态。

Q3: 如何优化列表滚动性能?

A: 使用ListView.builder实现按需加载,添加cacheExtent属性增加缓存范围,使用const构造函数减少重建。

Q4: 预约后可以取消吗?

A: 可以。在预约开始前30分钟可以免费取消,之后取消会扣除部分押金。

Q5: 余额不足怎么办?

A: 可以通过应用内充值功能进行充值,支持多种支付方式。

项目总结

本项目实现了一个功能完整的校园洗衣房打卡应用,主要特点包括:

功能完整性

  • 实时状态监控
  • 在线预约系统
  • 使用记录管理
  • 智能提醒通知
  • 个人中心管理

用户体验

  • 界面简洁美观
  • 操作流畅便捷
  • 响应速度快
  • 动画效果自然

技术实现

  • 代码结构清晰
  • 注释完整详细
  • 遵循最佳实践
  • 性能优化到位

学习价值

  • Flutter基础组件使用
  • 状态管理实践
  • 动画效果实现
  • 数据模型设计
  • 业务逻辑处理

通过本项目的学习和实践,可以掌握Flutter应用开发的核心技能,为开发更复杂的应用打下坚实基础。

参考资料

  • Flutter官方文档:https://flutter.dev/docs
  • Material Design 3:https://m3.material.io
  • Dart语言指南:https://dart.dev/guides

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

Logo

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

更多推荐