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

摘要

在这里插入图片描述

订单管理是商业运营的核心环节,一个高效的订单管理系统能够显著提升业务效率。本文将详细介绍如何使用Flutter for OpenHarmony框架开发一款功能完整的订单管理系统。文章涵盖了链表数据结构设计、订单模型实现、UI界面设计、数据持久化等核心技术点。通过本文学习,读者将掌握Flutter在鸿蒙平台上开发企业级数据管理应用的完整流程,了解链表结构在移动应用中的实际应用。


一、项目背景与功能概述

1.1 订单管理的重要性

订单管理是电商、零售、批发等行业运营的核心环节,涉及订单录入、查询、修改、统计等多个方面。传统的订单管理方式存在效率低、易出错、难以统计等问题,需要通过数字化手段提升管理水平。

1.2 应用功能规划

功能模块 具体功能
信息管理 记录订单的完整信息
日常操作 订单录入、修改、删除
信息查询 按订单编号、商品名称、买家姓名查询
数据存储 文件读写保存订单数据
数据排序 按交货日期排序

1.3 订单数据结构

每个订单包含以下信息:

  • 订单编号:唯一标识
  • 商品名称:订购的商品
  • 订购数量:购买数量
  • 商品单价:单个商品价格
  • 卖家:销售方
  • 买家:购买方
  • 订单日期:下单日期
  • 交货日期:预计交付日期
  • 总价:数量 × 单价(自动计算)

二、链表数据结构设计

2.1 为什么选择链表

链表是一种动态数据结构,具有以下优势:

  • 动态分配内存,无需预先确定大小
  • 插入和删除操作效率高
  • 适合需要频繁增删数据的场景

2.2 链表节点设计

// 订单节点类(链表节点)
class OrderNode {
  Order data;      // 数据域:存储订单信息
  OrderNode? next; // 指针域:指向下一个节点

  OrderNode({required this.data, this.next});
}

节点结构

  • data:存储订单对象
  • next:指向下一个节点的引用

2.3 链表操作示意图

head → [订单1] → [订单2] → [订单3] → null
        data      data      data
        next      next      next

三、技术选型与架构设计

3.1 核心技术栈

数据结构

  • 自定义链表类(OrderLinkedList)
  • 链表节点类(OrderNode)
  • 订单数据类(Order)

数据持久化

  • path_provider:获取文件存储路径
  • JSON序列化:数据格式转换
  • File API:文件读写操作

UI组件

  • TabBar:多标签页切换
  • TextField:输入框
  • ListView:订单列表展示
  • Card:订单卡片样式

3.2 应用架构

OrderManagementApp (应用根组件)
    └── OrderManagementPage (订单管理页面)
        ├── AppBar (导航栏 + TabBar)
        ├── TabBarView (标签页内容)
        │   ├── 订单录入标签页
        │   │   ├── 输入表单区域
        │   │   ├── 操作按钮区域
        │   │   └── 订单列表区域
        │   └── 订单查询标签页
        │       ├── 查询条件区域
        │       └── 查询结果区域
        └── FloatingActionButton (排序按钮)

3.3 数据流设计

在这里插入图片描述


四、数据模型实现

4.1 订单类设计

class Order {
  String orderId;        // 订单编号
  String productName;    // 商品名称
  int quantity;          // 订购数量
  double unitPrice;      // 商品单价
  String seller;         // 卖家
  String buyer;          // 买家
  String orderDate;      // 订单日期
  String deliveryDate;   // 交货日期
  double totalPrice;     // 总价

  Order({
    required this.orderId,
    required this.productName,
    required this.quantity,
    required this.unitPrice,
    required this.seller,
    required this.buyer,
    required this.orderDate,
    required this.deliveryDate,
  }) : totalPrice = quantity * unitPrice;
}

设计要点

  • 使用初始化列表自动计算总价
  • 所有字段使用required确保必填
  • 命名清晰易懂

4.2 JSON序列化

// 转换为JSON
Map<String, dynamic> toJson() {
  return {
    'orderId': orderId,
    'productName': productName,
    'quantity': quantity,
    'unitPrice': unitPrice,
    'seller': seller,
    'buyer': buyer,
    'orderDate': orderDate,
    'deliveryDate': deliveryDate,
    'totalPrice': totalPrice,
  };
}

// 从JSON创建
factory Order.fromJson(Map<String, dynamic> json) {
  return Order(
    orderId: json['orderId'] as String,
    productName: json['productName'] as String,
    quantity: json['quantity'] as int,
    unitPrice: json['unitPrice'] as double,
    seller: json['seller'] as String,
    buyer: json['buyer'] as String,
    orderDate: json['orderDate'] as String,
    deliveryDate: json['deliveryDate'] as String,
  );
}

五、UI界面设计

5.1 标签页布局

使用DefaultTabController实现双标签页:

DefaultTabController(
  length: 2,
  child: Scaffold(
    appBar: AppBar(
      title: const Text('订单管理系统'),
      bottom: const TabBar(
        tabs: [
          Tab(text: '订单录入'),
          Tab(text: '订单查询'),
        ],
      ),
    ),
    body: TabBarView(
      children: [
        _buildInputTab(),
        _buildSearchTab(),
      ],
    ),
  ),
)

5.2 输入表单设计

订单录入表单包含8个输入框:

Column(
  children: [
    _buildInputField('订单编号', _controllers[0]),
    _buildInputField('商品名称', _controllers[1]),
    _buildInputField('订购数量', _controllers[2], TextInputType.number),
    _buildInputField('商品单价', _controllers[3], TextInputType.number),
    _buildInputField('卖家', _controllers[4]),
    _buildInputField('买家', _controllers[5]),
    _buildInputField('订单日期', _controllers[6]),
    _buildInputField('交货日期', _controllers[7]),
  ],
)

在这里插入图片描述

输入框组件

Widget _buildInputField(String label, TextEditingController controller, [TextInputType? keyboardType]) {
  return Padding(
    padding: const EdgeInsets.only(bottom: 12),
    child: TextField(
      controller: controller,
      keyboardType: keyboardType ?? TextInputType.text,
      decoration: InputDecoration(
        labelText: label,
        border: const OutlineInputBorder(),
      ),
    ),
  );
}

5.3 订单列表展示

使用Card + ListTile展示订单:

Widget _buildOrderList(List<Order> orders, {bool showDelete = false}) {
  return ListView.builder(
    shrinkWrap: true,
    itemCount: orders.length,
    itemBuilder: (context, index) {
      final order = orders[index];
      return Card(
        margin: const EdgeInsets.symmetric(vertical: 4),
        child: ListTile(
          title: Text('${order.productName} (${order.orderId})'),
          subtitle: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('数量: ${order.quantity} × ¥${order.unitPrice.toStringAsFixed(2)}'),
              Text('卖家: ${order.seller} | 买家: ${order.buyer}'),
              Text('订单日期: ${order.orderDate}'),
              Text('交货日期: ${order.deliveryDate}'),
              Text('总价: ¥${order.totalPrice.toStringAsFixed(2)}',
                  style: const TextStyle(fontWeight: FontWeight.bold, color: Colors.red)),
            ],
          ),
          trailing: showDelete
              ? IconButton(
                  icon: const Icon(Icons.delete),
                  onPressed: () => _deleteOrder(order.orderId),
                )
              : null,
        ),
      );
    },
  );
}

六、订单录入功能

6.1 表单验证

bool _validateInputs() {
  // 检查必填项
  for (int i = 0; i < _controllers.length; i++) {
    if (_controllers[i].text.isEmpty) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(content: Text('请填写${_getFieldLabel(i)}')),
      );
      return false;
    }
  }

  // 验证数量
  int? quantity = int.tryParse(_controllers[2].text);
  if (quantity == null || quantity <= 0) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('订购数量必须大于0')),
    );
    return false;
  }

  // 验证单价
  double? price = double.tryParse(_controllers[3].text);
  if (price == null || price <= 0) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('商品单价必须大于0')),
    );
    return false;
  }

  // 验证订单编号唯一性
  if (_orderList.findById(_controllers[0].text) != null) {
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('订单编号已存在')),
    );
    return false;
  }

  return true;
}

6.2 添加订单

void _addOrder() {
  if (_validateInputs()) {
    Order order = Order(
      orderId: _controllers[0].text,
      productName: _controllers[1].text,
      quantity: int.parse(_controllers[2].text),
      unitPrice: double.parse(_controllers[3].text),
      seller: _controllers[4].text,
      buyer: _controllers[5].text,
      orderDate: _controllers[6].text,
      deliveryDate: _controllers[7].text,
    );

    setState(() {
      _orderList.add(order);
      _clearInputs();
      _saveOrders();
    });

    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('订单添加成功')),
    );
  }
}

6.3 删除订单

使用AlertDialog确认删除操作:

void _deleteOrder(String orderId) {
  showDialog(
    context: context,
    builder: (context) => AlertDialog(
      title: const Text('确认删除'),
      content: const Text('确定要删除这个订单吗?'),
      actions: [
        TextButton(
          onPressed: () => Navigator.pop(context),
          child: const Text('取消'),
        ),
        TextButton(
          onPressed: () {
            setState(() {
              _orderList.delete(orderId);
              _searchResults.clear();
              _saveOrders();
            });
            Navigator.pop(context);
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('订单删除成功')),
            );
          },
          child: const Text('确定'),
        ),
      ],
    ),
  );
}

在这里插入图片描述


七、完整代码实现

7.1 链表核心操作

class OrderLinkedList {
  OrderNode? head;
  int length = 0;

  // 添加订单
  void add(Order order) {
    OrderNode newNode = OrderNode(data: order);
    if (head == null) {
      head = newNode;
    } else {
      OrderNode? current = head;
      while (current!.next != null) {
        current = current.next;
      }
      current.next = newNode;
    }
    length++;
  }

  // 根据订单编号查找
  OrderNode? findById(String orderId) {
    OrderNode? current = head;
    while (current != null) {
      if (current.data.orderId == orderId) {
        return current;
      }
      current = current.next;
    }
    return null;
  }

  // 根据商品名称查找
  List<Order> findByProductName(String productName) {
    List<Order> results = [];
    OrderNode? current = head;
    while (current != null) {
      if (current.data.productName.contains(productName)) {
        results.add(current.data);
      }
      current = current.next;
    }
    return results;
  }

  // 根据买家姓名查找
  List<Order> findByBuyer(String buyerName) {
    List<Order> results = [];
    OrderNode? current = head;
    while (current != null) {
      if (current.data.buyer.contains(buyerName)) {
        results.add(current.data);
      }
      current = current.next;
    }
    return results;
  }

  // 删除订单
  bool delete(String orderId) {
    if (head == null) return false;

    if (head!.data.orderId == orderId) {
      head = head!.next;
      length--;
      return true;
    }

    OrderNode? current = head;
    while (current!.next != null) {
      if (current.next!.data.orderId == orderId) {
        current.next = current.next!.next;
        length--;
        return true;
      }
      current = current.next;
    }
    return false;
  }

  // 按交货日期排序
  void sortByDeliveryDate() {
    if (head == null || head!.next == null) return;

    List<Order> orders = toList();
    orders.sort((a, b) => a.deliveryDate.compareTo(b.deliveryDate));

    fromList(orders);
  }

  // 获取所有订单
  List<Order> toList() {
    List<Order> orders = [];
    OrderNode? current = head;
    while (current != null) {
      orders.add(current.data);
      current = current.next;
    }
    return orders;
  }
}

7.2 文件读写操作

// 保存到文件
Future<void> _saveOrders() async {
  try {
    final directory = await getApplicationDocumentsDirectory();
    final file = File('${directory.path}/orders.json');
    final orders = _orderList.toList();
    final json = jsonEncode(orders.map((e) => e.toJson()).toList());
    await file.writeAsString(json);
  } catch (e) {
    debugPrint('保存失败: $e');
  }
}

// 从文件加载
Future<void> _loadOrders() async {
  try {
    final directory = await getApplicationDocumentsDirectory();
    final file = File('${directory.path}/orders.json');
    if (await file.exists()) {
      final json = await file.readAsString();
      final List<dynamic> data = jsonDecode(json);
      for (var item in data) {
        _orderList.add(Order.fromJson(item as Map<String, dynamic>));
      }
      setState(() {});
    }
  } catch (e) {
    debugPrint('加载失败: $e');
  }
}

八、运行效果与测试

8.1 项目运行命令

cd E:\HarmonyOS\oh.code\order_management
flutter run -d ohos

8.2 功能测试清单

订单录入测试

  • 输入完整信息,成功添加订单
  • 订单编号重复时提示错误
  • 数量为0或负数时提示错误
  • 单价为0或负数时提示错误
  • 必填项为空时提示错误

订单查询测试

  • 按订单编号精确查询
  • 按商品名称模糊查询
  • 按买家姓名模糊查询
  • 查询无结果时显示提示

订单删除测试

  • 删除订单时弹出确认对话框
  • 确认删除后订单移除
  • 取消删除后订单保留

排序功能测试

  • 按交货日期升序排列
  • 排序后保存到文件

数据持久化测试

  • 重启应用后数据保持
  • 添加订单后自动保存
  • 删除订单后自动保存

九、总结

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

  1. 链表数据结构:自定义链表类实现动态数据管理
  2. 数据模型设计:Order类封装订单信息,支持JSON序列化
  3. UI界面设计:TabBar实现多标签页,Card展示订单列表
  4. 表单验证:多重验证确保数据准确性
  5. 数据持久化:JSON文件存储订单数据

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

  • 订单编辑功能
  • 数据统计与图表
  • 高级搜索过滤
  • 导出Excel报表
  • 多用户权限管理

通过本文的学习,读者应该能够独立开发类似的数据管理系统,掌握Flutter在鸿蒙平台上的数据管理和持久化技巧。


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

Logo

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

更多推荐