Flutter for OpenHarmony 商城App实战 - 订单列表实现
本文介绍了Flutter for OpenHarmony项目中订单列表页面的实现方案。订单列表包含分类筛选、状态显示和操作功能,采用Tab栏组织不同状态订单(全部、待付款、待发货、待收货、已完成)。消息系统定义了四种消息类型(系统、订单、促销、客服),包含基础属性、阅读状态和时间标记。订单卡片展示订单号、状态和商品信息,支持用户交互操作。页面采用响应式设计,空状态时显示友好提示。该实现方案兼顾了功

订单列表是用户查看购买历史和订单状态的重要页面。用户在这里可以查看所有订单、按状态筛选、查看订单详情、进行售后操作等。一个好的订单列表实现需要清晰的分类、准确的状态显示和便捷的操作方式。本文将详细讲解如何在 Flutter for OpenHarmony 项目中实现一个功能完整的订单列表页面,包括订单分类、状态筛选、订单展示和交互操作等功能。
消息数据模型
消息系统是用户与应用交互的重要方式。Message 类定义了消息的结构。
// 消息类型枚举
enum MessageType {
system, // 系统消息
order, // 订单消息
promotion, // 促销活动
service, // 客服消息
}
class Message {
const Message({
required this.id, // 消息ID
required this.title, // 消息标题
required this.content, // 消息内容
required this.type, // 消息类型
required this.createdAt, // 创建时间
this.isRead = false, // 是否已读
this.imageUrl, // 消息图片URL
});
final String id;
final String title;
final String content;
final MessageType type;
final DateTime createdAt;
final bool isRead;
final String? imageUrl;
// 获取消息类型的显示文本
String get typeText {
switch (type) {
case MessageType.system:
return '系统消息';
case MessageType.order:
return '订单消息';
case MessageType.promotion:
return '促销活动';
case MessageType.service:
return '客服消息';
}
}
}
这个消息模型展示了如何管理消息:
消息类型:
- 系统消息:应用系统通知
- 订单消息:订单状态更新
- 促销活动:营销推广信息
- 客服消息:客服支持信息
消息属性:
- 包含消息的基本信息(ID、标题、内容)
- 记录消息的创建时间
- 标记消息是否已读
- 支持消息配图
显示优化:
typeText属性返回用户友好的消息类型文本
订单列表页面结构
订单列表页面需要支持多种视图和筛选方式。
class OrdersPage extends StatefulWidget {
const OrdersPage({super.key});
State<OrdersPage> createState() => _OrdersPageState();
}
class _OrdersPageState extends State<OrdersPage>
with SingleTickerProviderStateMixin {
// Tab控制器
late TabController _tabController;
// 订单状态过滤
OrderStatus? _selectedStatus;
void initState() {
super.initState();
// 初始化Tab控制器,共5个Tab
_tabController = TabController(length: 5, vsync: this);
}
void dispose() {
_tabController.dispose();
super.dispose();
}
Widget build(BuildContext context) {
final appState = AppStateScope.of(context);
return Scaffold(
appBar: AppBar(
title: const Text('我的订单'),
// Tab栏
bottom: TabBar(
controller: _tabController,
tabs: const [
Tab(text: '全部'),
Tab(text: '待付款'),
Tab(text: '待发货'),
Tab(text: '待收货'),
Tab(text: '已完成'),
],
),
),
body: AnimatedBuilder(
animation: appState,
builder: (context, _) {
return TabBarView(
controller: _tabController,
children: [
// 全部订单
_buildOrderList(appState.orders),
// 待付款订单
_buildOrderList(
appState.orders
.where((o) => o.status == OrderStatus.pending)
.toList(),
),
// 待发货订单
_buildOrderList(
appState.orders
.where((o) => o.status == OrderStatus.paid)
.toList(),
),
// 待收货订单
_buildOrderList(
appState.orders
.where((o) => o.status == OrderStatus.shipped)
.toList(),
),
// 已完成订单
_buildOrderList(
appState.orders
.where((o) => o.status == OrderStatus.delivered)
.toList(),
),
],
);
},
),
);
}
// 构建订单列表
Widget _buildOrderList(List<Order> orders) {
if (orders.isEmpty) {
return const Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.shopping_bag_outlined, size: 64, color: Colors.grey),
SizedBox(height: 16),
Text('暂无订单'),
],
),
);
}
return ListView.builder(
padding: const EdgeInsets.all(12),
itemCount: orders.length,
itemBuilder: (context, index) {
final order = orders[index];
return _buildOrderCard(order);
},
);
}
// 构建订单卡片
Widget _buildOrderCard(Order order) {
return Card(
margin: const EdgeInsets.only(bottom: 12),
child: Padding(
padding: const EdgeInsets.all(12),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 订单头部:订单号和状态
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'订单号:${order.id}',
style: Theme.of(context).textTheme.bodySmall,
),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: _getStatusColor(order.status),
borderRadius: BorderRadius.circular(4),
),
child: Text(
order.statusText,
style: const TextStyle(
color: Colors.white,
fontSize: 12,
),
),
),
],
),
const SizedBox(height: 12),
// 订单项目
if (order.items.isNotEmpty)
Column(
children: order.items.map((item) {
return Padding(
padding: const EdgeInsets.only(bottom: 8),
child: Row(
children: [
// 商品图片
ClipRRect(
borderRadius: BorderRadius.circular(4),
child: Image.network(
item.product.imageUrl,
width: 48,
height: 48,
fit: BoxFit.contain,
errorBuilder: (_, __, ___) =>
const SizedBox(width: 48, height: 48),
),
),
const SizedBox(width: 8),
// 商品信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
item.product.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.bodySmall,
),
Text(
'¥${item.priceUsd.toStringAsFixed(2)} x${item.quantity}',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
),
],
),
);
}).toList(),
),
const Divider(),
// 订单总价
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'合计:',
style: Theme.of(context).textTheme.bodySmall,
),
Text(
'¥${order.totalUsd.toStringAsFixed(2)}',
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontWeight: FontWeight.bold,
),
),
],
),
const SizedBox(height: 12),
// 操作按钮
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {
// 查看订单详情
},
child: const Text('详情'),
),
const SizedBox(width: 8),
if (order.status == OrderStatus.pending)
ElevatedButton(
onPressed: () {
// 去支付
},
child: const Text('支付'),
),
if (order.status == OrderStatus.shipped)
ElevatedButton(
onPressed: () {
// 确认收货
},
child: const Text('确认收货'),
),
],
),
],
),
),
);
}
// 获取订单状态对应的颜色
Color _getStatusColor(OrderStatus status) {
switch (status) {
case OrderStatus.pending:
return Colors.orange;
case OrderStatus.paid:
return Colors.blue;
case OrderStatus.shipped:
return Colors.purple;
case OrderStatus.delivered:
return Colors.green;
case OrderStatus.cancelled:
return Colors.grey;
case OrderStatus.refunding:
return Colors.red;
case OrderStatus.refunded:
return Colors.red;
}
}
}
这个订单列表页面展示了如何组织和展示订单:
Tab分类:
- 全部订单
- 待付款订单
- 待发货订单
- 待收货订单
- 已完成订单
订单筛选:
- 使用
where方法按状态筛选 - 动态生成不同状态的订单列表
- 支持多种筛选维度
空状态处理:
- 当没有订单时显示友好提示
- 显示购物袋图标和"暂无订单"文本
- 改善用户体验
订单卡片设计
订单卡片需要清晰地展示订单信息和操作选项。
// 订单卡片的关键部分
// 1. 订单头部
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 订单号
Text('订单号:${order.id}'),
// 订单状态标签
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
decoration: BoxDecoration(
color: _getStatusColor(order.status),
borderRadius: BorderRadius.circular(4),
),
child: Text(
order.statusText,
style: const TextStyle(color: Colors.white, fontSize: 12),
),
),
],
)
// 2. 订单项目列表
Column(
children: order.items.map((item) {
return Row(
children: [
// 商品图片
Image.network(item.product.imageUrl, width: 48, height: 48),
// 商品信息
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(item.product.title),
Text('¥${item.priceUsd} x${item.quantity}'),
],
),
),
],
);
}).toList(),
)
// 3. 订单总价
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text('合计:'),
Text('¥${order.totalUsd.toStringAsFixed(2)}'),
],
)
// 4. 操作按钮
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(onPressed: () {}, child: const Text('详情')),
if (order.status == OrderStatus.pending)
ElevatedButton(onPressed: () {}, child: const Text('支付')),
],
)
这个订单卡片设计展示了如何组织订单信息:
信息层次:
- 订单号和状态在顶部,便于快速识别
- 订单项目在中间,显示购买的商品
- 订单总价在下方,突出重要信息
- 操作按钮在底部,便于用户操作
视觉设计:
- 使用颜色标签表示订单状态
- 使用分隔线分隔不同部分
- 使用合理的间距提高可读性
交互设计:
- 提供查看详情的选项
- 根据订单状态显示不同的操作按钮
- 待付款订单显示支付按钮
- 待收货订单显示确认收货按钮
订单状态管理
订单状态需要在应用状态中管理。
// 在AppState中管理订单
class AppState extends ChangeNotifier {
// 订单列表
final List<Order> _orders = [];
List<Order> get orders => List.unmodifiable(_orders);
// 添加订单
void addOrder(Order order) {
_orders.insert(0, order); // 新订单插入到列表开头
notifyListeners();
}
// 更新订单状态
void updateOrderStatus(String orderId, OrderStatus status) {
final index = _orders.indexWhere((o) => o.id == orderId);
if (index >= 0) {
final order = _orders[index];
// 创建新的订单对象(不可变性)
_orders[index] = Order(
id: order.id,
items: order.items,
status: status,
createdAt: order.createdAt,
totalUsd: order.totalUsd,
shippingAddress: order.shippingAddress,
trackingNumber: order.trackingNumber,
paidAt: order.paidAt,
shippedAt: order.shippedAt,
deliveredAt: order.deliveredAt,
);
notifyListeners();
}
}
// 获取特定状态的订单
List<Order> getOrdersByStatus(OrderStatus status) {
return _orders.where((o) => o.status == status).toList();
}
// 获取订单统计信息
Map<OrderStatus, int> getOrderStats() {
final stats = <OrderStatus, int>{};
for (final order in _orders) {
stats[order.status] = (stats[order.status] ?? 0) + 1;
}
return stats;
}
}
这个订单状态管理展示了如何管理订单:
订单操作:
addOrder添加新订单到列表开头updateOrderStatus更新订单状态getOrdersByStatus按状态获取订单getOrderStats获取订单统计信息
不可变性:
- 创建新的订单对象而不是修改现有对象
- 确保状态的可追踪性
- 支持时间旅行调试
通知机制:
- 每次修改后调用
notifyListeners() - 所有监听的组件自动更新
订单筛选和搜索
用户可能需要按多个条件筛选订单。
// 订单筛选逻辑
class OrderFilter {
// 按状态筛选
static List<Order> filterByStatus(
List<Order> orders,
OrderStatus status,
) {
return orders.where((o) => o.status == status).toList();
}
// 按日期范围筛选
static List<Order> filterByDateRange(
List<Order> orders,
DateTime startDate,
DateTime endDate,
) {
return orders
.where((o) => o.createdAt.isAfter(startDate) &&
o.createdAt.isBefore(endDate))
.toList();
}
// 按金额范围筛选
static List<Order> filterByAmountRange(
List<Order> orders,
double minAmount,
double maxAmount,
) {
return orders
.where((o) => o.totalUsd >= minAmount && o.totalUsd <= maxAmount)
.toList();
}
// 搜索订单号
static List<Order> searchByOrderId(
List<Order> orders,
String keyword,
) {
return orders
.where((o) => o.id.contains(keyword))
.toList();
}
// 组合筛选
static List<Order> filter(
List<Order> orders, {
OrderStatus? status,
DateTime? startDate,
DateTime? endDate,
double? minAmount,
double? maxAmount,
String? keyword,
}) {
var result = orders;
if (status != null) {
result = filterByStatus(result, status);
}
if (startDate != null && endDate != null) {
result = filterByDateRange(result, startDate, endDate);
}
if (minAmount != null && maxAmount != null) {
result = filterByAmountRange(result, minAmount, maxAmount);
}
if (keyword != null && keyword.isNotEmpty) {
result = searchByOrderId(result, keyword);
}
return result;
}
}
这个订单筛选展示了如何实现灵活的筛选:
单一筛选:
- 按状态筛选
- 按日期范围筛选
- 按金额范围筛选
- 按订单号搜索
组合筛选:
- 支持多个条件同时筛选
- 链式调用实现复杂筛选
- 灵活的筛选组合
订单统计和分析
应用可以提供订单统计信息。
// 订单统计
class OrderStats {
// 计算订单总数
static int getTotalOrders(List<Order> orders) {
return orders.length;
}
// 计算待付款订单数
static int getPendingOrders(List<Order> orders) {
return orders.where((o) => o.status == OrderStatus.pending).length;
}
// 计算总消费金额
static double getTotalSpent(List<Order> orders) {
return orders.fold(0, (sum, o) => sum + o.totalUsd);
}
// 计算平均订单金额
static double getAverageOrderAmount(List<Order> orders) {
if (orders.isEmpty) return 0;
return getTotalSpent(orders) / orders.length;
}
// 获取最近30天的订单
static List<Order> getRecentOrders(List<Order> orders, int days) {
final cutoffDate = DateTime.now().subtract(Duration(days: days));
return orders.where((o) => o.createdAt.isAfter(cutoffDate)).toList();
}
}
这个订单统计展示了如何分析订单数据:
统计指标:
- 订单总数
- 待付款订单数
- 总消费金额
- 平均订单金额
- 最近订单
数据分析:
- 帮助用户了解购买情况
- 为营销提供数据支持
- 改善用户体验
总结
订单列表的实现涉及多个重要的技术点。首先是消息系统的设计,支持多种消息类型。其次是订单列表页面的实现,支持Tab分类和状态筛选。再次是订单卡片的设计,清晰地展示订单信息。最后是订单状态管理和筛选功能,提供灵活的订单查询和分析。
这种设计确保了订单列表的功能完整性和用户体验的流畅性。用户可以轻松查看订单、筛选订单、进行订单操作,整个流程自然而直观。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net
更多推荐
所有评论(0)