Flutter for OpenHarmony 实战:mango_shop 订单模块的流程设计与鸿蒙端数据持久化

在这里插入图片描述

作者:爱吃大芒果

个人主页 爱吃大芒果

本文所属专栏Flutter

更多专栏
Ascend C 算子开发教程(进阶)
鸿蒙集成
OpenAgents
openJiuwen
从0到1自学C++


订单模块现状分析

通过对 mango_shop 项目的分析,我们发现:

  1. 现有实现

    • 定义了 OrderOrderItem 模型类
    • 实现了待付款订单页面 PendingPaymentOrders
    • 实现了基本的订单展示、支付和取消功能
    • 使用硬编码的模拟数据,没有实际的网络请求
  2. 存在问题

    • 订单数据没有持久化存储,应用重启后数据会丢失
    • 没有实现完整的订单状态流转
    • 没有实现订单历史记录的管理
    • 没有针对 OpenHarmony 平台的特殊适配

订单模块优化方案

1. 订单流程设计

1.1 订单状态流转
创建订单 → 待付款 → 待发货 → 待收货 → 已完成
                ↓
             已取消
1.2 订单操作流程
  1. 创建订单

    • 从购物车选择商品
    • 确认收货地址和支付方式
    • 生成订单
  2. 支付订单

    • 选择支付方式
    • 完成支付
    • 更新订单状态为待发货
  3. 取消订单

    • 用户主动取消
    • 超时自动取消
    • 更新订单状态为已取消
  4. 确认收货

    • 用户确认收到商品
    • 更新订单状态为已完成
  5. 订单售后

    • 申请退款/退货
    • 处理售后请求

2. 订单状态管理

2.1 订单模型设计
// lib/models/order.dart
import 'package:mango_shop/models/address.dart';

// 订单商品模型
class OrderItem {
  final String id;
  final String name;
  final String image;
  final double price;
  int quantity;

  OrderItem({
    required this.id,
    required this.name,
    required this.image,
    required this.price,
    required this.quantity,
  });

  // 从 JSON 创建订单商品实例
  factory OrderItem.fromJson(Map<String, dynamic> json) {
    return OrderItem(
      id: json['id'] ?? '',
      name: json['name'] ?? '',
      image: json['image'] ?? '',
      price: json['price'] ?? 0.0,
      quantity: json['quantity'] ?? 1,
    );
  }

  // 转换为 JSON
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'image': image,
      'price': price,
      'quantity': quantity,
    };
  }
}

// 订单状态枚举
enum OrderStatus {
  pendingPayment, // 待付款
  pendingShipment, // 待发货
  shipping, // 待收货
  completed, // 已完成
  cancelled, // 已取消
}

// 订单模型
class Order {
  final String orderId;
  final String createTime;
  final double totalPrice;
  final int totalQuantity;
  final List<OrderItem> items;
  final OrderStatus status;
  final String? paymentMethod;
  final Address? address;
  final String? trackingNumber;

  Order({
    required this.orderId,
    required this.createTime,
    required this.totalPrice,
    required this.totalQuantity,
    required this.items,
    required this.status,
    this.paymentMethod,
    this.address,
    this.trackingNumber,
  });

  // 从 JSON 创建订单实例
  factory Order.fromJson(Map<String, dynamic> json) {
    final List<dynamic> itemsJson = json['items'] ?? [];
    final List<OrderItem> items = itemsJson.map((item) => OrderItem.fromJson(item)).toList();
    
    OrderStatus status;
    switch (json['status']) {
      case 'pendingPayment':
        status = OrderStatus.pendingPayment;
        break;
      case 'pendingShipment':
        status = OrderStatus.pendingShipment;
        break;
      case 'shipping':
        status = OrderStatus.shipping;
        break;
      case 'completed':
        status = OrderStatus.completed;
        break;
      case 'cancelled':
        status = OrderStatus.cancelled;
        break;
      default:
        status = OrderStatus.pendingPayment;
    }

    return Order(
      orderId: json['orderId'] ?? '',
      createTime: json['createTime'] ?? '',
      totalPrice: json['totalPrice'] ?? 0.0,
      totalQuantity: json['totalQuantity'] ?? 0,
      items: items,
      status: status,
      paymentMethod: json['paymentMethod'],
      address: json['address'] != null ? Address.fromJson(json['address']) : null,
      trackingNumber: json['trackingNumber'],
    );
  }

  // 转换为 JSON
  Map<String, dynamic> toJson() {
    String statusStr;
    switch (status) {
      case OrderStatus.pendingPayment:
        statusStr = 'pendingPayment';
        break;
      case OrderStatus.pendingShipment:
        statusStr = 'pendingShipment';
        break;
      case OrderStatus.shipping:
        statusStr = 'shipping';
        break;
      case OrderStatus.completed:
        statusStr = 'completed';
        break;
      case OrderStatus.cancelled:
        statusStr = 'cancelled';
        break;
    }

    return {
      'orderId': orderId,
      'createTime': createTime,
      'totalPrice': totalPrice,
      'totalQuantity': totalQuantity,
      'items': items.map((item) => item.toJson()).toList(),
      'status': statusStr,
      'paymentMethod': paymentMethod,
      'address': address?.toJson(),
      'trackingNumber': trackingNumber,
    };
  }
}

在这里插入图片描述

2.2 订单状态管理

使用 Riverpod 进行订单状态管理:

// lib/providers/order_provider.dart
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mango_shop/models/order.dart';
import 'package:mango_shop/services/order_service.dart';

// 订单状态
class OrderState {
  final List<Order> orders;
  final bool isLoading;
  final String? errorMessage;

  const OrderState({
    required this.orders,
    this.isLoading = false,
    this.errorMessage,
  });

  // 按状态获取订单
  List<Order> getOrdersByStatus(OrderStatus status) {
    return orders.where((order) => order.status == status).toList();
  }

  // 获取待付款订单
  List<Order> get pendingPaymentOrders => getOrdersByStatus(OrderStatus.pendingPayment);

  // 获取待发货订单
  List<Order> get pendingShipmentOrders => getOrdersByStatus(OrderStatus.pendingShipment);

  // 获取待收货订单
  List<Order> get shippingOrders => getOrdersByStatus(OrderStatus.shipping);

  // 获取已完成订单
  List<Order> get completedOrders => getOrdersByStatus(OrderStatus.completed);

  // 获取已取消订单
  List<Order> get cancelledOrders => getOrdersByStatus(OrderStatus.cancelled);
}

// 订单状态提供者
class OrderNotifier extends StateNotifier<OrderState> {
  final OrderService _orderService;

  OrderNotifier(this._orderService) : super(const OrderState(orders: [])) {
    // 初始化时加载订单数据
    _loadOrders();
  }

  // 加载订单数据
  Future<void> _loadOrders() async {
    state = state.copyWith(isLoading: true);
    
    try {
      final orders = await _orderService.getOrders();
      state = OrderState(orders: orders);
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
    }
  }

  // 创建订单
  Future<Order> createOrder(List<Map<String, dynamic>> orderData) async {
    state = state.copyWith(isLoading: true);
    
    try {
      final order = await _orderService.createOrder(orderData);
      final updatedOrders = [...state.orders, order];
      await _orderService.saveOrders(updatedOrders);
      state = OrderState(orders: updatedOrders);
      return order;
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
      rethrow;
    }
  }

  // 支付订单
  Future<void> payOrder(String orderId) async {
    state = state.copyWith(isLoading: true);
    
    try {
      final updatedOrders = await _orderService.payOrder(orderId, state.orders);
      state = OrderState(orders: updatedOrders);
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
    }
  }

  // 取消订单
  Future<void> cancelOrder(String orderId) async {
    state = state.copyWith(isLoading: true);
    
    try {
      final updatedOrders = await _orderService.cancelOrder(orderId, state.orders);
      state = OrderState(orders: updatedOrders);
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
    }
  }

  // 确认收货
  Future<void> confirmReceipt(String orderId) async {
    state = state.copyWith(isLoading: true);
    
    try {
      final updatedOrders = await _orderService.confirmReceipt(orderId, state.orders);
      state = OrderState(orders: updatedOrders);
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
    }
  }

  // 删除订单
  Future<void> deleteOrder(String orderId) async {
    state = state.copyWith(isLoading: true);
    
    try {
      final updatedOrders = await _orderService.deleteOrder(orderId, state.orders);
      state = OrderState(orders: updatedOrders);
    } catch (e) {
      state = state.copyWith(
        isLoading: false,
        errorMessage: e.toString(),
      );
    }
  }

  // 刷新订单
  Future<void> refreshOrders() async {
    await _loadOrders();
  }
}

// 创建订单状态提供者
final orderProvider = StateNotifierProvider<OrderNotifier, OrderState>((ref) {
  final orderService = OrderService();
  return OrderNotifier(orderService);
});

// 便捷获取待付款订单的提供者
final pendingPaymentOrdersProvider = Provider<List<Order>>((ref) {
  return ref.watch(orderProvider).pendingPaymentOrders;
});

// 便捷获取待发货订单的提供者
final pendingShipmentOrdersProvider = Provider<List<Order>>((ref) {
  return ref.watch(orderProvider).pendingShipmentOrders;
});

// 便捷获取待收货订单的提供者
final shippingOrdersProvider = Provider<List<Order>>((ref) {
  return ref.watch(orderProvider).shippingOrders;
});

// 便捷获取已完成订单的提供者
final completedOrdersProvider = Provider<List<Order>>((ref) {
  return ref.watch(orderProvider).completedOrders;
});

在这里插入图片描述
在这里插入图片描述

3. 订单数据持久化

3.1 订单服务实现
// lib/services/order_service.dart
import 'dart:convert';
import 'package:mango_shop/models/order.dart';
import 'package:mango_shop/services/secure_storage_service.dart';
import 'package:mango_shop/utils/platform/adapter.dart';

class OrderService {
  static const String _ordersKey = 'mango_shop_orders';
  final SecureStorageService _storage = SecureStorageService();

  // 获取订单数据
  Future<List<Order>> getOrders() async {
    try {
      final ordersJson = await _storage.read(_ordersKey);
      if (ordersJson == null) {
        return _getMockOrders();
      }
      
      final List<dynamic> ordersList = jsonDecode(ordersJson);
      return ordersList.map((item) => Order.fromJson(item)).toList();
    } catch (e) {
      print('获取订单数据失败: $e');
      return _getMockOrders();
    }
  }

  // 保存订单数据
  Future<void> saveOrders(List<Order> orders) async {
    try {
      final ordersJson = jsonEncode(orders.map((order) => order.toJson()).toList());
      await _storage.write(_ordersKey, ordersJson);
    } catch (e) {
      print('保存订单数据失败: $e');
    }
  }

  // 创建订单
  Future<Order> createOrder(List<Map<String, dynamic>> orderData) async {
    // 生成订单号
    final orderId = '${DateTime.now().year}${DateTime.now().month.toString().padLeft(2, '0')}${DateTime.now().day.toString().padLeft(2, '0')}${DateTime.now().hour.toString().padLeft(2, '0')}${DateTime.now().minute.toString().padLeft(2, '0')}${DateTime.now().second.toString().padLeft(2, '0')}';
    
    // 计算总价和总数量
    double totalPrice = 0;
    int totalQuantity = 0;
    List<OrderItem> items = [];
    
    for (var itemData in orderData) {
      final item = OrderItem(
        id: itemData['id'],
        name: itemData['name'],
        image: itemData['image'],
        price: itemData['price'],
        quantity: itemData['quantity'],
      );
      items.add(item);
      totalPrice += item.price * item.quantity;
      totalQuantity += item.quantity;
    }
    
    // 创建订单
    final order = Order(
      orderId: orderId,
      createTime: DateTime.now().toString(),
      totalPrice: totalPrice,
      totalQuantity: totalQuantity,
      items: items,
      status: OrderStatus.pendingPayment,
    );
    
    // 保存订单
    final orders = await getOrders();
    orders.add(order);
    await saveOrders(orders);
    
    return order;
  }

  // 支付订单
  Future<List<Order>> payOrder(String orderId, List<Order> orders) async {
    // 更新订单状态
    final updatedOrders = orders.map((order) {
      if (order.orderId == orderId) {
        return Order(
          orderId: order.orderId,
          createTime: order.createTime,
          totalPrice: order.totalPrice,
          totalQuantity: order.totalQuantity,
          items: order.items,
          status: OrderStatus.pendingShipment,
          paymentMethod: '在线支付',
          address: order.address,
          trackingNumber: order.trackingNumber,
        );
      }
      return order;
    }).toList();
    
    // 保存订单
    await saveOrders(updatedOrders);
    return updatedOrders;
  }

  // 取消订单
  Future<List<Order>> cancelOrder(String orderId, List<Order> orders) async {
    // 更新订单状态
    final updatedOrders = orders.map((order) {
      if (order.orderId == orderId) {
        return Order(
          orderId: order.orderId,
          createTime: order.createTime,
          totalPrice: order.totalPrice,
          totalQuantity: order.totalQuantity,
          items: order.items,
          status: OrderStatus.cancelled,
          paymentMethod: order.paymentMethod,
          address: order.address,
          trackingNumber: order.trackingNumber,
        );
      }
      return order;
    }).toList();
    
    // 保存订单
    await saveOrders(updatedOrders);
    return updatedOrders;
  }

  // 确认收货
  Future<List<Order>> confirmReceipt(String orderId, List<Order> orders) async {
    // 更新订单状态
    final updatedOrders = orders.map((order) {
      if (order.orderId == orderId) {
        return Order(
          orderId: order.orderId,
          createTime: order.createTime,
          totalPrice: order.totalPrice,
          totalQuantity: order.totalQuantity,
          items: order.items,
          status: OrderStatus.completed,
          paymentMethod: order.paymentMethod,
          address: order.address,
          trackingNumber: order.trackingNumber,
        );
      }
      return order;
    }).toList();
    
    // 保存订单
    await saveOrders(updatedOrders);
    return updatedOrders;
  }

  // 删除订单
  Future<List<Order>> deleteOrder(String orderId, List<Order> orders) async {
    // 移除订单
    final updatedOrders = orders.where((order) => order.orderId != orderId).toList();
    
    // 保存订单
    await saveOrders(updatedOrders);
    return updatedOrders;
  }

  // 模拟订单数据
  List<Order> _getMockOrders() {
    return [
      Order(
        orderId: '202601280001',
        createTime: '2026-01-28 14:30:25',
        totalPrice: 85.7,
        totalQuantity: 6,
        items: [
          OrderItem(
            id: '1',
            name: '新鲜芒果 泰国进口大青芒 2个装 单果约400-500g 新鲜水果',
            image: 'lib/assets/220c3184-fec6-4c46-8606-67015ed201cc.png',
            price: 29.9,
            quantity: 2,
          ),
          OrderItem(
            id: '3',
            name: '广西百色芒果 桂七香芒 2个装 单果约300-400g 新鲜水果',
            image: 'lib/assets/220c3184-fec6-4c46-8606-67015ed201cc.png',
            price: 25.9,
            quantity: 1,
          ),
        ],
        status: OrderStatus.pendingPayment,
      ),
      Order(
        orderId: '202601280002',
        createTime: '2026-01-28 13:15:40',
        totalPrice: 15.9,
        totalQuantity: 1,
        items: [
          OrderItem(
            id: '2',
            name: '海南小台农芒果 500g装 单果约80-120g 新鲜水果',
            image: 'lib/assets/52da9c14-9404-4e4d-83a1-4a294050350f.png',
            price: 15.9,
            quantity: 1,
          ),
        ],
        status: OrderStatus.pendingShipment,
        paymentMethod: '在线支付',
      ),
      Order(
        orderId: '202601270001',
        createTime: '2026-01-27 10:20:30',
        totalPrice: 59.8,
        totalQuantity: 4,
        items: [
          OrderItem(
            id: '4',
            name: '云南芒果 新鲜水果 2个装',
            image: 'lib/assets/220c3184-fec6-4c46-8606-67015ed201cc.png',
            price: 17.9,
            quantity: 2,
          ),
          OrderItem(
            id: '5',
            name: '白菜 新鲜蔬菜 500g装',
            image: 'lib/assets/白菜.png',
            price: 2.9,
            quantity: 2,
          ),
        ],
        status: OrderStatus.shipping,
        paymentMethod: '在线支付',
        trackingNumber: 'SF1234567890',
      ),
      Order(
        orderId: '202601260001',
        createTime: '2026-01-26 09:15:20',
        totalPrice: 39.8,
        totalQuantity: 2,
        items: [
          OrderItem(
            id: '1',
            name: '新鲜芒果 泰国进口大青芒 2个装 单果约400-500g 新鲜水果',
            image: 'lib/assets/220c3184-fec6-4c46-8606-67015ed201cc.png',
            price: 29.9,
            quantity: 1,
          ),
          OrderItem(
            id: '6',
            name: '萝卜 新鲜蔬菜 500g装',
            image: 'lib/assets/胡萝卜.png',
            price: 3.9,
            quantity: 1,
          ),
        ],
        status: OrderStatus.completed,
        paymentMethod: '在线支付',
        trackingNumber: 'YT9876543210',
      ),
    ];
  }
}
3.2 地址模型
// lib/models/address.dart
class Address {
  final String id;
  final String name;
  final String phone;
  final String province;
  final String city;
  final String district;
  final String detail;
  final bool isDefault;

  Address({
    required this.id,
    required this.name,
    required this.phone,
    required this.province,
    required this.city,
    required this.district,
    required this.detail,
    this.isDefault = false,
  });

  // 从 JSON 创建地址实例
  factory Address.fromJson(Map<String, dynamic> json) {
    return Address(
      id: json['id'] ?? '',
      name: json['name'] ?? '',
      phone: json['phone'] ?? '',
      province: json['province'] ?? '',
      city: json['city'] ?? '',
      district: json['district'] ?? '',
      detail: json['detail'] ?? '',
      isDefault: json['isDefault'] ?? false,
    );
  }

  // 转换为 JSON
  Map<String, dynamic> toJson() {
    return {
      'id': id,
      'name': name,
      'phone': phone,
      'province': province,
      'city': city,
      'district': district,
      'detail': detail,
      'isDefault': isDefault,
    };
  }

  // 获取完整地址
  String get fullAddress {
    return '$province$city$district$detail';
  }
}

4. 订单页面实现

4.1 待付款订单页面
// lib/pages/Orders/PendingPaymentOrders.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mango_shop/providers/order_provider.dart';
import 'package:mango_shop/utils/colors.dart';
import 'package:mango_shop/utils/text_styles.dart';

class PendingPaymentOrders extends ConsumerWidget {
  const PendingPaymentOrders({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final pendingOrders = ref.watch(pendingPaymentOrdersProvider);
    final orderNotifier = ref.read(orderProvider.notifier);

    // 处理支付
    void _handlePayment(String orderId) {
      // 显示支付确认对话框
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('确认支付'),
            content: const Text('是否确认支付该订单?'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('取消'),
              ),
              TextButton(
                onPressed: () async {
                  Navigator.of(context).pop();
                  // 处理支付
                  await orderNotifier.payOrder(orderId);
                  // 显示支付成功提示
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('支付成功!')),
                  );
                },
                child: Text('确认支付', style: AppTextStyles.bodyMedium.copyWith(color: AppColors.primary, fontWeight: FontWeight.w600)),
              ),
            ],
          );
        },
      );
    }

    // 取消订单
    void _cancelOrder(String orderId) {
      // 显示取消确认对话框
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('确认取消'),
            content: const Text('是否确认取消该订单?'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('不取消'),
              ),
              TextButton(
                onPressed: () async {
                  Navigator.of(context).pop();
                  // 处理取消订单
                  await orderNotifier.cancelOrder(orderId);
                  // 显示取消成功提示
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('订单已取消')),
                  );
                },
                child: Text('确认取消', style: AppTextStyles.bodyMedium.copyWith(color: AppColors.primary, fontWeight: FontWeight.w600)),
              ),
            ],
          );
        },
      );
    }

    // 构建订单商品项
    Widget _buildOrderItem(orderItem) {
      return Container(
        padding: const EdgeInsets.all(12),
        margin: const EdgeInsets.symmetric(vertical: 4),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: Colors.grey[100]!),
        ),
        child: Row(
          children: [
            // 商品图片
            Container(
              width: 60,
              height: 60,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(4),
                image: DecorationImage(
                  image: AssetImage(orderItem.image),
                  fit: BoxFit.cover,
                ),
              ),
            ),
            const SizedBox(width: 12),
            // 商品信息
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    orderItem.name,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
                  ),
                  const SizedBox(height: 8),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        ${orderItem.price.toStringAsFixed(2)}',
                        style: const TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: Colors.red,
                        ),
                      ),
                      Text('x${orderItem.quantity}', style: const TextStyle(fontSize: 14, color: Colors.grey)),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    // 构建订单卡片
    Widget _buildOrderCard(order) {
      return Container(
        margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          boxShadow: [
            BoxShadow(
              color: Colors.grey[200]!,
              spreadRadius: 1,
              blurRadius: 3,
              offset: const Offset(0, 1),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 订单头部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text('订单号:${order.orderId}', style: const TextStyle(fontSize: 14)),
                  Text(order.createTime, style: const TextStyle(fontSize: 12, color: Colors.grey)),
                ],
              ),
            ),
            // 订单商品列表
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12),
              child: Column(
                children: order.items.map((item) => _buildOrderItem(item)).toList(),
              ),
            ),
            // 订单底部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(
                    '共${order.totalQuantity}件商品,合计:¥${order.totalPrice.toStringAsFixed(2)}',
                    style: const TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.bold,
                      color: Colors.red,
                    ),
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.end,
                    children: [
                      OutlinedButton(
                        onPressed: () => _cancelOrder(order.orderId),
                        child: Text('取消订单', style: AppTextStyles.bodySmall.copyWith(color: AppColors.textSecondary)),
                        style: OutlinedButton.styleFrom(
                          padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
                          side: BorderSide(color: AppColors.gray300),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8),
                          ),
                        ),
                      ),
                      const SizedBox(width: 12),
                      ElevatedButton(
                        onPressed: () => _handlePayment(order.orderId),
                        child: const Text('立即支付'),
                        style: ElevatedButton.styleFrom(
                          backgroundColor: AppColors.primary,
                          foregroundColor: AppColors.white,
                          padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
                          elevation: 2,
                          shadowColor: AppColors.primary.withOpacity(0.3),
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(8),
                          ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('待付款订单'),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 1,
      ),
      body: pendingOrders.isEmpty
          ? _buildEmptyState()
          : ListView.builder(
              itemCount: pendingOrders.length,
              itemBuilder: (context, index) {
                return _buildOrderCard(pendingOrders[index]);
              },
            ),
    );
  }

  // 构建空状态
  Widget _buildEmptyState() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Icon(Icons.payment, size: 80, color: Colors.grey),
          const SizedBox(height: 20),
          const Text('暂无待付款订单', style: TextStyle(fontSize: 16, color: Colors.grey)),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              // 跳转到首页
              Navigator.pushNamed(context, '/');
            },
            child: const Text('去购物'),
            style: ElevatedButton.styleFrom(
              backgroundColor: AppColors.primary,
              foregroundColor: AppColors.white,
              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
              elevation: 2,
              shadowColor: AppColors.primary.withOpacity(0.3),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

在这里插入图片描述

4.2 待发货订单页面
// lib/pages/Orders/PendingShipmentOrders.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mango_shop/providers/order_provider.dart';
import 'package:mango_shop/utils/colors.dart';
import 'package:mango_shop/utils/text_styles.dart';

class PendingShipmentOrders extends ConsumerWidget {
  const PendingShipmentOrders({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final pendingShipmentOrders = ref.watch(pendingShipmentOrdersProvider);

    // 构建订单商品项
    Widget _buildOrderItem(orderItem) {
      return Container(
        padding: const EdgeInsets.all(12),
        margin: const EdgeInsets.symmetric(vertical: 4),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: Colors.grey[100]!),
        ),
        child: Row(
          children: [
            // 商品图片
            Container(
              width: 60,
              height: 60,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(4),
                image: DecorationImage(
                  image: AssetImage(orderItem.image),
                  fit: BoxFit.cover,
                ),
              ),
            ),
            const SizedBox(width: 12),
            // 商品信息
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    orderItem.name,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
                  ),
                  const SizedBox(height: 8),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        ${orderItem.price.toStringAsFixed(2)}',
                        style: const TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: Colors.red,
                        ),
                      ),
                      Text('x${orderItem.quantity}', style: const TextStyle(fontSize: 14, color: Colors.grey)),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    // 构建订单卡片
    Widget _buildOrderCard(order) {
      return Container(
        margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          boxShadow: [
            BoxShadow(
              color: Colors.grey[200]!,
              spreadRadius: 1,
              blurRadius: 3,
              offset: const Offset(0, 1),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 订单头部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text('订单号:${order.orderId}', style: const TextStyle(fontSize: 14)),
                  Text(order.createTime, style: const TextStyle(fontSize: 12, color: Colors.grey)),
                ],
              ),
            ),
            // 订单商品列表
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12),
              child: Column(
                children: order.items.map((item) => _buildOrderItem(item)).toList(),
              ),
            ),
            // 订单底部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(
                    '共${order.totalQuantity}件商品,合计:¥${order.totalPrice.toStringAsFixed(2)}',
                    style: const TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.bold,
                      color: Colors.red,
                    ),
                  ),
                  const SizedBox(height: 12),
                  const Text('商家正在处理您的订单', style: TextStyle(fontSize: 14, color: Colors.grey)),
                ],
              ),
            ),
          ],
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('待发货订单'),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 1,
      ),
      body: pendingShipmentOrders.isEmpty
          ? _buildEmptyState()
          : ListView.builder(
              itemCount: pendingShipmentOrders.length,
              itemBuilder: (context, index) {
                return _buildOrderCard(pendingShipmentOrders[index]);
              },
            ),
    );
  }

  // 构建空状态
  Widget _buildEmptyState() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Icon(Icons.local_shipping, size: 80, color: Colors.grey),
          const SizedBox(height: 20),
          const Text('暂无待发货订单', style: TextStyle(fontSize: 16, color: Colors.grey)),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              // 跳转到首页
              Navigator.pushNamed(context, '/');
            },
            child: const Text('去购物'),
            style: ElevatedButton.styleFrom(
              backgroundColor: AppColors.primary,
              foregroundColor: AppColors.white,
              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
              elevation: 2,
              shadowColor: AppColors.primary.withOpacity(0.3),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

在这里插入图片描述

4.3 待收货订单页面
// lib/pages/Orders/ShippingOrders.dart
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:mango_shop/providers/order_provider.dart';
import 'package:mango_shop/utils/colors.dart';
import 'package:mango_shop/utils/text_styles.dart';

class ShippingOrders extends ConsumerWidget {
  const ShippingOrders({Key? key}) : super(key: key);

  
  Widget build(BuildContext context, WidgetRef ref) {
    final shippingOrders = ref.watch(shippingOrdersProvider);
    final orderNotifier = ref.read(orderProvider.notifier);

    // 确认收货
    void _confirmReceipt(String orderId) {
      // 显示确认收货对话框
      showDialog(
        context: context,
        builder: (BuildContext context) {
          return AlertDialog(
            title: const Text('确认收货'),
            content: const Text('是否确认收到该订单的商品?'),
            actions: [
              TextButton(
                onPressed: () {
                  Navigator.of(context).pop();
                },
                child: const Text('取消'),
              ),
              TextButton(
                onPressed: () async {
                  Navigator.of(context).pop();
                  // 处理确认收货
                  await orderNotifier.confirmReceipt(orderId);
                  // 显示确认收货成功提示
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('确认收货成功!')),
                  );
                },
                child: Text('确认收货', style: AppTextStyles.bodyMedium.copyWith(color: AppColors.primary, fontWeight: FontWeight.w600)),
              ),
            ],
          );
        },
      );
    }

    // 构建订单商品项
    Widget _buildOrderItem(orderItem) {
      return Container(
        padding: const EdgeInsets.all(12),
        margin: const EdgeInsets.symmetric(vertical: 4),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          border: Border.all(color: Colors.grey[100]!),
        ),
        child: Row(
          children: [
            // 商品图片
            Container(
              width: 60,
              height: 60,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(4),
                image: DecorationImage(
                  image: AssetImage(orderItem.image),
                  fit: BoxFit.cover,
                ),
              ),
            ),
            const SizedBox(width: 12),
            // 商品信息
            Expanded(
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Text(
                    orderItem.name,
                    maxLines: 2,
                    overflow: TextOverflow.ellipsis,
                    style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
                  ),
                  const SizedBox(height: 8),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        ${orderItem.price.toStringAsFixed(2)}',
                        style: const TextStyle(
                          fontSize: 14,
                          fontWeight: FontWeight.bold,
                          color: Colors.red,
                        ),
                      ),
                      Text('x${orderItem.quantity}', style: const TextStyle(fontSize: 14, color: Colors.grey)),
                    ],
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    // 构建订单卡片
    Widget _buildOrderCard(order) {
      return Container(
        margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
        decoration: BoxDecoration(
          color: Colors.white,
          borderRadius: BorderRadius.circular(8),
          boxShadow: [
            BoxShadow(
              color: Colors.grey[200]!,
              spreadRadius: 1,
              blurRadius: 3,
              offset: const Offset(0, 1),
            ),
          ],
        ),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 订单头部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceBetween,
                children: [
                  Text('订单号:${order.orderId}', style: const TextStyle(fontSize: 14)),
                  Text(order.createTime, style: const TextStyle(fontSize: 12, color: Colors.grey)),
                ],
              ),
            ),
            // 订单商品列表
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12),
              child: Column(
                children: order.items.map((item) => _buildOrderItem(item)).toList(),
              ),
            ),
            // 物流信息
            if (order.trackingNumber != null)
              Padding(
                padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
                child: Container(
                  padding: const EdgeInsets.all(12),
                  decoration: BoxDecoration(
                    color: Colors.grey[50],
                    borderRadius: BorderRadius.circular(8),
                  ),
                  child: Row(
                    children: [
                      const Icon(Icons.local_shipping, color: Colors.blue),
                      const SizedBox(width: 12),
                      Expanded(
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            const Text('商品正在配送中', style: TextStyle(fontSize: 14)),
                            const SizedBox(height: 4),
                            Text('物流单号:${order.trackingNumber}', style: const TextStyle(fontSize: 12, color: Colors.grey)),
                          ],
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            // 订单底部
            Padding(
              padding: const EdgeInsets.all(12),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.end,
                children: [
                  Text(
                    '共${order.totalQuantity}件商品,合计:¥${order.totalPrice.toStringAsFixed(2)}',
                    style: const TextStyle(
                      fontSize: 14,
                      fontWeight: FontWeight.bold,
                      color: Colors.red,
                    ),
                  ),
                  const SizedBox(height: 12),
                  ElevatedButton(
                    onPressed: () => _confirmReceipt(order.orderId),
                    child: const Text('确认收货'),
                    style: ElevatedButton.styleFrom(
                      backgroundColor: AppColors.primary,
                      foregroundColor: AppColors.white,
                      padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 10),
                      elevation: 2,
                      shadowColor: AppColors.primary.withOpacity(0.3),
                      shape: RoundedRectangleBorder(
                        borderRadius: BorderRadius.circular(8),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ),
      );
    }

    return Scaffold(
      appBar: AppBar(
        title: const Text('待收货订单'),
        centerTitle: true,
        backgroundColor: Colors.white,
        elevation: 1,
      ),
      body: shippingOrders.isEmpty
          ? _buildEmptyState()
          : ListView.builder(
              itemCount: shippingOrders.length,
              itemBuilder: (context, index) {
                return _buildOrderCard(shippingOrders[index]);
              },
            ),
    );
  }

  // 构建空状态
  Widget _buildEmptyState() {
    return Center(
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          const Icon(Icons.local_shipping, size: 80, color: Colors.grey),
          const SizedBox(height: 20),
          const Text('暂无待收货订单', style: TextStyle(fontSize: 16, color: Colors.grey)),
          const SizedBox(height: 20),
          ElevatedButton(
            onPressed: () {
              // 跳转到首页
              Navigator.pushNamed(context, '/');
            },
            child: const Text('去购物'),
            style: ElevatedButton.styleFrom(
              backgroundColor: AppColors.primary,
              foregroundColor: AppColors.white,
              padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
              elevation: 2,
              shadowColor: AppColors.primary.withOpacity(0.3),
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.circular(8),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

5. 跨平台适配

5.1 OpenHarmony 平台适配

针对 OpenHarmony 平台,我们需要进行以下适配:

  1. 存储适配

    • OpenHarmony 平台的存储机制与其他平台有所不同,需要使用特定的存储 API
    • 实现平台感知的存储策略
  2. 性能优化

    • 针对 OpenHarmony 平台的性能特性,优化订单数据的加载和更新
    • 减少不必要的 UI 重建
  3. 平台感知实现

// lib/utils/platform/adapter.dart
import 'dart:io';

class PlatformAdapter {
  // 判断当前平台
  static bool get isOpenHarmony {
    return Platform.environment.containsKey('OHOS') || 
           Platform.operatingSystem.toLowerCase() == 'openharmony';
  }

  // 获取平台特定的存储策略
  static bool useSecureStorage {
    return !isOpenHarmony; // OpenHarmony 平台使用普通存储
  }

  // 获取平台特定的订单数据同步策略
  static bool useRealTimeSync {
    return !isOpenHarmony; // OpenHarmony 平台使用定时同步
  }

  // 获取平台特定的订单列表缓存大小限制
  static int get orderListCacheSizeLimit {
    return isOpenHarmony ? 50 : 100; // OpenHarmony 平台限制更小
  }
}
  1. OpenHarmony 特定的存储实现
// lib/services/ohos_storage_adapter.dart
import 'dart:convert';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:mango_shop/utils/platform/adapter.dart';
import 'package:path_provider/path_provider.dart';

class OhosStorageAdapter {
  static final OhosStorageAdapter _instance = OhosStorageAdapter._internal();
  factory OhosStorageAdapter() => _instance;

  OhosStorageAdapter._internal();

  // 检查是否为 OpenHarmony 平台
  bool get isOpenHarmony => PlatformAdapter.isOpenHarmony;

  // OpenHarmony 平台的存储路径
  Future<String> get _storagePath async {
    if (isOpenHarmony) {
      final directory = await getApplicationDocumentsDirectory();
      return '${directory.path}/mango_shop';
    }
    throw UnsupportedError('Not OpenHarmony platform');
  }

  // 确保存储目录存在
  Future<void> _ensureDirectoryExists() async {
    if (isOpenHarmony) {
      final path = await _storagePath;
      final directory = Directory(path);
      if (!directory.existsSync()) {
        directory.createSync(recursive: true);
      }
    }
  }

  // 保存订单数据到 OpenHarmony 存储
  Future<void> saveOrders(List<dynamic> orders) async {
    if (isOpenHarmony) {
      try {
        await _ensureDirectoryExists();
        final path = await _storagePath;
        final file = File('$path/orders.json');
        final ordersJson = jsonEncode(orders);
        await file.writeAsString(ordersJson);
        if (kDebugMode) {
          print('OpenHarmony: Saved orders to storage');
        }
      } catch (e) {
        if (kDebugMode) {
          print('OpenHarmony storage error: $e');
        }
      }
    }
  }

  // 从 OpenHarmony 存储读取订单数据
  Future<List<dynamic>> readOrders() async {
    if (isOpenHarmony) {
      try {
        await _ensureDirectoryExists();
        final path = await _storagePath;
        final file = File('$path/orders.json');
        if (file.existsSync()) {
          final ordersJson = await file.readAsString();
          if (kDebugMode) {
            print('OpenHarmony: Read orders from storage');
          }
          return jsonDecode(ordersJson);
        }
      } catch (e) {
        if (kDebugMode) {
          print('OpenHarmony storage error: $e');
        }
      }
    }
    return [];
  }
}

测试与调试

1. 订单功能测试

  1. 功能测试

    • 测试订单创建流程
    • 测试订单支付功能
    • 测试订单取消功能
    • 测试订单确认收货功能
    • 测试订单状态流转
  2. 数据持久化测试

    • 测试应用重启后订单数据是否保留
    • 测试订单数据的增删改查操作
    • 测试不同状态订单的存储和读取
  3. 跨平台测试

    • 确保在所有平台上订单功能表现一致
    • 特别测试 OpenHarmony 平台的适配情况

2. 调试工具

  1. 日志调试

    • 添加订单操作的详细日志,便于调试
    • 使用不同级别的日志,区分正常操作和错误情况
  2. 性能分析

    • 使用 Flutter DevTools 分析订单操作的性能
    • 监控内存使用和 UI 渲染性能
  3. 存储调试

    • 添加存储操作的日志,了解数据存储情况
    • 提供查看当前存储内容的工具

总结与展望

通过本文介绍的订单模块优化方案,我们可以:

  1. 提高代码可维护性:使用 Riverpod 进行状态管理,代码结构更清晰
  2. 增强数据持久性:实现订单数据的本地缓存,确保应用重启后数据不丢失
  3. 提升用户体验:优化订单操作的响应速度和流畅度
  4. 增强跨平台兼容性:针对 OpenHarmony 平台进行专门的适配
  5. 简化开发流程:封装订单服务,减少重复代码

未来,可以考虑:

  1. 订单同步:实现订单数据的云端同步,支持多设备共享订单信息
  2. 订单分析:添加订单数据分析功能,帮助用户了解消费情况
  3. 智能推荐:基于订单历史提供个性化商品推荐
  4. 多语言支持:添加订单相关的多语言支持,提升国际化体验

Flutter for OpenHarmony 为跨平台应用开发提供了新的可能性,通过合理的订单模块设计和跨平台适配,可以构建出在所有平台上表现出色的应用。


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

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐