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

作者:爱吃大芒果
个人主页 爱吃大芒果
本文所属专栏Flutter
更多专栏
Ascend C 算子开发教程(进阶)
鸿蒙集成
OpenAgents
openJiuwen
从0到1自学C++
订单模块现状分析
通过对 mango_shop 项目的分析,我们发现:
-
现有实现:
- 定义了
Order和OrderItem模型类 - 实现了待付款订单页面
PendingPaymentOrders - 实现了基本的订单展示、支付和取消功能
- 使用硬编码的模拟数据,没有实际的网络请求
- 定义了
-
存在问题:
- 订单数据没有持久化存储,应用重启后数据会丢失
- 没有实现完整的订单状态流转
- 没有实现订单历史记录的管理
- 没有针对 OpenHarmony 平台的特殊适配
订单模块优化方案
1. 订单流程设计
1.1 订单状态流转
创建订单 → 待付款 → 待发货 → 待收货 → 已完成
↓
已取消
1.2 订单操作流程
-
创建订单:
- 从购物车选择商品
- 确认收货地址和支付方式
- 生成订单
-
支付订单:
- 选择支付方式
- 完成支付
- 更新订单状态为待发货
-
取消订单:
- 用户主动取消
- 超时自动取消
- 更新订单状态为已取消
-
确认收货:
- 用户确认收到商品
- 更新订单状态为已完成
-
订单售后:
- 申请退款/退货
- 处理售后请求
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 平台,我们需要进行以下适配:
-
存储适配:
- OpenHarmony 平台的存储机制与其他平台有所不同,需要使用特定的存储 API
- 实现平台感知的存储策略
-
性能优化:
- 针对 OpenHarmony 平台的性能特性,优化订单数据的加载和更新
- 减少不必要的 UI 重建
-
平台感知实现:
// 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 平台限制更小
}
}
- 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. 订单功能测试
-
功能测试:
- 测试订单创建流程
- 测试订单支付功能
- 测试订单取消功能
- 测试订单确认收货功能
- 测试订单状态流转
-
数据持久化测试:
- 测试应用重启后订单数据是否保留
- 测试订单数据的增删改查操作
- 测试不同状态订单的存储和读取
-
跨平台测试:
- 确保在所有平台上订单功能表现一致
- 特别测试 OpenHarmony 平台的适配情况
2. 调试工具
-
日志调试:
- 添加订单操作的详细日志,便于调试
- 使用不同级别的日志,区分正常操作和错误情况
-
性能分析:
- 使用 Flutter DevTools 分析订单操作的性能
- 监控内存使用和 UI 渲染性能
-
存储调试:
- 添加存储操作的日志,了解数据存储情况
- 提供查看当前存储内容的工具
总结与展望
通过本文介绍的订单模块优化方案,我们可以:
- 提高代码可维护性:使用 Riverpod 进行状态管理,代码结构更清晰
- 增强数据持久性:实现订单数据的本地缓存,确保应用重启后数据不丢失
- 提升用户体验:优化订单操作的响应速度和流畅度
- 增强跨平台兼容性:针对 OpenHarmony 平台进行专门的适配
- 简化开发流程:封装订单服务,减少重复代码
未来,可以考虑:
- 订单同步:实现订单数据的云端同步,支持多设备共享订单信息
- 订单分析:添加订单数据分析功能,帮助用户了解消费情况
- 智能推荐:基于订单历史提供个性化商品推荐
- 多语言支持:添加订单相关的多语言支持,提升国际化体验
Flutter for OpenHarmony 为跨平台应用开发提供了新的可能性,通过合理的订单模块设计和跨平台适配,可以构建出在所有平台上表现出色的应用。
欢迎加入开源鸿蒙跨平台社区:开源鸿蒙跨平台开发者社区
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)