/// 商家的订单 library; import 'package:flutter/material.dart'; import 'package:get/get.dart'; import 'package:loopin/utils/wxsdk.dart'; import 'package:loopin/api/shop_api.dart'; import 'package:loopin/components/my_toast.dart'; import 'package:loopin/service/http.dart'; import '../../behavior/custom_scroll_behavior.dart'; class Seller extends StatefulWidget { const Seller({super.key}); @override State createState() => _SellerState(); } class _SellerState extends State with SingleTickerProviderStateMixin { GlobalKey scaffoldKey = GlobalKey(); // 分页内容 - 为每个Tab单独存储数据 final int pageSize = 10; bool isLoadingMore = false; bool isRefreshing = false; // 为每个Tab单独存储状态 List> _allOrders = []; List> _pendingPaymentOrders = []; List> _pendingVerificationOrders = []; List> _completedOrders = []; List> _closedOrders = []; List> _refundingOrders = []; List> _refundedOrders = []; List> _cancelledOrders = []; // 每个Tab的分页状态 Map _pageNums = {}; Map _totalCounts = {}; Map _hasMoreData = {}; Map _isLoading = {}; // 订单状态:0->待付款;1->待核销;2->已完成;3->已关闭;4->退款中;5->已退款 6->已取消 精确匹配 List tabList = [ {'id': '', 'name': "全部", 'index': 0}, {'id': 0, 'name': "待付款", 'index': 1}, {'id': 1, 'name': "待核销", 'index': 2}, {'id': 2, 'name': "已完成", 'index': 3}, {'id': 3, 'name': "已关闭", 'index': 4}, {'id': 4, 'name': "退款中", 'index': 5}, {'id': 5, 'name': "已退款", 'index': 6}, {'id': 6, 'name': "已取消", 'index': 7} ]; late ScrollController scrollController = ScrollController(); late TabController tabController = TabController(initialIndex: 0, length: tabList.length, vsync: this); @override void initState() { super.initState(); // 初始化分页状态 for (var tab in tabList) { _pageNums[tab['index']] = 1; _totalCounts[tab['index']] = 0; _hasMoreData[tab['index']] = true; _isLoading[tab['index']] = false; } // 监听滚动事件 scrollController.addListener(_scrollListener); // 监听tab切换事件 tabController.addListener(_tabChanged); // 获取初始订单列表 getOrderList(false); } @override void dispose() { scrollController.removeListener(_scrollListener); scrollController.dispose(); tabController.removeListener(_tabChanged); tabController.dispose(); super.dispose(); } // 获取当前Tab的订单列表 List> _getCurrentOrderList() { final currentIndex = tabController.index; switch (currentIndex) { case 0: return _allOrders; case 1: return _pendingPaymentOrders; case 2: return _pendingVerificationOrders; case 3: return _completedOrders; case 4: return _closedOrders; case 5: return _refundingOrders; case 6: return _refundedOrders; case 7: return _cancelledOrders; default: return _allOrders; } } // 设置当前Tab的订单列表 void _setCurrentOrderList(List> orders, bool loadMore) { final currentIndex = tabController.index; setState(() { switch (currentIndex) { case 0: if (loadMore) { _allOrders.addAll(orders); } else { _allOrders = orders; } break; case 1: if (loadMore) { _pendingPaymentOrders.addAll(orders); } else { _pendingPaymentOrders = orders; } break; case 2: if (loadMore) { _pendingVerificationOrders.addAll(orders); } else { _pendingVerificationOrders = orders; } break; case 3: if (loadMore) { _completedOrders.addAll(orders); } else { _completedOrders = orders; } break; case 4: if (loadMore) { _closedOrders.addAll(orders); } else { _closedOrders = orders; } break; case 5: if (loadMore) { _refundingOrders.addAll(orders); } else { _refundingOrders = orders; } break; case 6: if (loadMore) { _refundedOrders.addAll(orders); } else { _refundedOrders = orders; } break; case 7: if (loadMore) { _cancelledOrders.addAll(orders); } else { _cancelledOrders = orders; } break; } }); } // 滚动监听 void _scrollListener() { final currentIndex = tabController.index; if (scrollController.position.pixels == scrollController.position.maxScrollExtent && !_isLoading[currentIndex]! && _hasMoreData[currentIndex]!) { getOrderList(true); } } // Tab切换监听 void _tabChanged() { if (tabController.index != tabController.previousIndex) { // 如果当前Tab没有数据,则加载数据 final currentOrders = _getCurrentOrderList(); if (currentOrders.isEmpty) { getOrderList(false); } } } // 获取订单列表 void getOrderList(bool loadMore) async { final currentIndex = tabController.index; final currentTab = tabList[currentIndex]; if (_isLoading[currentIndex]! || isRefreshing) return; setState(() { if (!loadMore) { _pageNums[currentIndex] = 1; isRefreshing = true; } else { _isLoading[currentIndex] = true; } }); try { final status = currentTab['id']; final res = await Http.post(ShopApi.myOrderList, data: { 'current': _pageNums[currentIndex], // 当前页码 'size': pageSize, 'status': status == '' ? '' : status.toString(), }); if (res['code'] == 200 && res['data'] != null) { final data = res['data']; final List> newOrders = List>.from(data['records'] ?? []); final int total = data['total'] ?? 0; debugPrint(data.toString(), wrapWidth: 1024); // 更新当前Tab的数据 _setCurrentOrderList(newOrders, loadMore); // 更新分页状态 - 使用total总数判断 setState(() { // 更新总数 _totalCounts[currentIndex] = total; // 判断是否还有更多数据 final currentOrderCount = _getCurrentOrderList().length; _hasMoreData[currentIndex] = currentOrderCount < total; // 如果有更多数据,增加页码 if (_hasMoreData[currentIndex]!) { _pageNums[currentIndex] = _pageNums[currentIndex]! + 1; } }); } } catch (e) { print('获取订单列表失败: $e'); setState(() { _hasMoreData[currentIndex] = false; }); } finally { setState(() { isRefreshing = false; _isLoading[currentIndex] = false; }); } } // 刷新数据时重置分页状态 void _refreshData() { final currentIndex = tabController.index; setState(() { _pageNums[currentIndex] = 1; _totalCounts[currentIndex] = 0; _isLoading[currentIndex] = false; _hasMoreData[currentIndex] = true; }); getOrderList(false); } // 获取付款文案 String _getPaymentText(dynamic status) { int statusCode = status is String ? int.tryParse(status) ?? 0 : (status is int ? status : 0); switch (statusCode) { case 0: // 待付款 return '待付款: '; case 1: // 待核销 return '已付款: '; case 2: // 已完成 return '实付款: '; case 3: // 已关闭 return '订单金额: '; case 4: // 退款中 return '实付款: '; case 5: // 已退款 return '退款金额: '; case 6: // 已取消 return '订单金额: '; default: return '金额: '; } } // 构建订单项Widget Widget _buildOrderItem(Map order) { return GestureDetector( child: Container( margin: EdgeInsets.only(bottom: 10.0), padding: EdgeInsets.all(10.0), decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(10), offset: Offset(0.0, 1.0), blurRadius: 1.0, spreadRadius: 0.0, ), ], ), child: Column( children: [ Row( children: [ Wrap( crossAxisAlignment: WrapCrossAlignment.center, spacing: 5.0, children: [ ClipOval( child: Image.asset( 'assets/images/avatar/img11.jpg', width: 25.0, ), ), Text(order['items'][0]['tenantName'] ?? '商家名称'), Icon( Icons.arrow_forward_ios_rounded, color: Colors.grey, size: 12.0, ), ], ), Spacer(), Text( _getStatusText(order['status']), style: TextStyle(color: _getStatusColor(order['status'])), ) ], ), SizedBox(height: 10), // 商品信息 if (order['items'] != null && order['items'].isNotEmpty) ...order['items'].map((item) => Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: 80.0, height: 80.0, decoration: BoxDecoration( color: Colors.grey[200], borderRadius: BorderRadius.circular(4.0), ), child: order['items'][0]['pic'] != null && order['items'][0]['pic'].isNotEmpty ? Image.network( order['items'][0]['pic'], width: 80.0, height: 80.0, fit: BoxFit.cover, ) : Icon( Icons.shopping_bag_outlined, size: 40.0, color: Colors.grey[400], ), ), SizedBox(width: 10), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item['productName'] ?? '商品名称', maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 14), ), SizedBox(height: 5), Row( children: [ Text( '¥${item['salePrice'] ?? '0'}', style: TextStyle(color: Colors.red, fontSize: 16), ), Spacer(), Text( 'x${item['quantity'] ?? '1'}', style: TextStyle(color: Colors.grey), ), ], ), ], ), ) ], )).toList(), SizedBox(height: 10), // 金额信息 Container( padding: EdgeInsets.all(5.0), decoration: BoxDecoration( color: Colors.grey[50], borderRadius: BorderRadius.circular(5.0), ), child: Row( children: [ Spacer(), Text.rich( TextSpan(children: [ TextSpan(text: _getPaymentText(order['status'])), // 根据状态获取文案 TextSpan( text: '¥${order['totalAmount'] ?? '0'}', style: TextStyle(color: Colors.red, fontSize: 16), ), ]), ), ], ), ), SizedBox(height: 10), // 根据状态显示不同的按钮 _buildActionButtons(order), ], ), ), onTap: () { Get.toNamed('/order/detail', arguments: {'orderId': order['id']}); }, ); } // 获取状态文本 String _getStatusText(dynamic status) { // 处理字符串或数字类型的状态 int statusCode = status is String ? int.tryParse(status) ?? 0 : (status is int ? status : 0); switch (statusCode) { case 0: return '待付款'; case 1: return '待核销'; case 2: return '已完成'; case 3: return '已关闭'; case 4: return '退款中'; case 5: return '已退款'; case 6: return '已取消'; default: return '未知状态'; } } // 获取状态颜色 Color _getStatusColor(dynamic status) { int statusCode = status is String ? int.tryParse(status) ?? 0 : (status is int ? status : 0); switch (statusCode) { case 0: return Colors.grey; case 1: return Colors.blue; case 2: return Colors.green; case 3: return Colors.red; case 4: return Colors.orange; case 5: return Colors.grey; case 6: return Colors.grey; default: return Colors.black; } } // 构建操作按钮 Widget _buildActionButtons(dynamic orderObject) { // 处理字符串或数字类型的状态 var status = orderObject['status']; var orderId = orderObject['id']; int statusCode = status is String ? int.tryParse(status) ?? 0 : (status is int ? status : 0); switch (statusCode) { case 0: // 待付款 return Row( mainAxisAlignment: MainAxisAlignment.end, children: [ ElevatedButton( onPressed: () => _cancelOrder(orderId), style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)), child: Text('取消订单'), ), SizedBox(width: 10), ElevatedButton( onPressed: () => _payOrder(orderId), style: ButtonStyle( backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), foregroundColor: WidgetStateProperty.all(Colors.white), ), child: Text('去支付'), ), ], ); case 1: // 待核销 return Row( mainAxisAlignment: MainAxisAlignment.end, ); case 2: // 已完成 return Row( mainAxisAlignment: MainAxisAlignment.end, ); default: return SizedBox.shrink(); } } // 订单操作的方法 void _cancelOrder(String orderId) async { try { final res = await Http.post('${ShopApi.cancelGoodsOrder}/$orderId'); print('取消订单成功-------------->${res}'); if (res['code'] == 200) { MyToast().tip( title: '订单已取消', position: 'center', type: 'success', ); // 刷新所有相关的tab _refreshAllRelatedTabs(); } } catch (e) { print('取消订单失败-------------->${e}'); } } // 刷新所有相关的tab void _refreshAllRelatedTabs() { // 需要刷新的tab索引:全部(0)、待付款(1)、已取消(7) List tabsToRefresh = [0, 1, 7]; for (int tabIndex in tabsToRefresh) { _resetTabData(tabIndex); // 如果当前正在查看这个tab,立即刷新数据 if (tabController.index == tabIndex) { getOrderList(false); } } } void _payOrder(_orderId) { // 打开微信小程序的某个页面地址,如pages/index/index Wxsdk.openMiniApp(orderId: _orderId); } // 重置指定tab的数据 void _resetTabData(int index) { setState(() { _pageNums[index] = 1; _totalCounts[index] = 0; _isLoading[index] = false; _hasMoreData[index] = true; switch (index) { case 0: _allOrders = []; break; case 1: _pendingPaymentOrders = []; break; case 2: _pendingVerificationOrders = []; break; case 3: _completedOrders = []; break; case 4: _closedOrders = []; break; case 5: _refundingOrders = []; break; case 6: _refundedOrders = []; break; case 7: _cancelledOrders = []; break; } }); } @override Widget build(BuildContext context) { return Scaffold( key: scaffoldKey, backgroundColor: Colors.white, appBar: AppBar( titleSpacing: 1.0, title: Text( '我的订单', style: TextStyle(fontSize: 18), ), bottom: PreferredSize( preferredSize: Size.fromHeight(45.0), child: Container( height: 45.0, alignment: Alignment.centerLeft, child: TabBar( controller: tabController, tabAlignment: TabAlignment.start, isScrollable: true, padding: EdgeInsets.only(left: 0), indicatorPadding: EdgeInsets.zero, labelPadding: EdgeInsets.symmetric(horizontal: 10.0), tabs: tabList .map((item) => Container( constraints: BoxConstraints(minWidth: 70), alignment: Alignment.center, child: Badge.count( backgroundColor: Colors.red, offset: Offset(14, -4), count: item['badge'] ?? 0, isLabelVisible: item['badge'] != null && item['badge'] > 0, child: Text( item['name'], style: TextStyle(fontSize: 16), overflow: TextOverflow.ellipsis, ), ), )) .toList(), overlayColor: WidgetStateProperty.all(Colors.transparent), unselectedLabelColor: Colors.black87, labelColor: Color(0xFFFF5000), indicator: UnderlineTabIndicator( borderRadius: BorderRadius.circular(10.0), borderSide: BorderSide(color: Color(0xFFFF5000), width: 2.0), ), indicatorSize: TabBarIndicatorSize.label, unselectedLabelStyle: TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'), labelStyle: TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w700), dividerHeight: 0, ), ), ), ), body: TabBarView( controller: tabController, children: List.generate(tabList.length, (index) { return RefreshIndicator( onRefresh: () async { _refreshData(); }, child: ScrollConfiguration( behavior: CustomScrollBehavior().copyWith(scrollbars: false), child: Container( color: Colors.grey[50], child: Builder( builder: (context) { final currentOrders = _getOrderListByIndex(index); final isLoading = _isLoading[index] ?? false; final hasMoreData = _hasMoreData[index] ?? false; return currentOrders.isEmpty && !isRefreshing ? emptyTip() : ListView.builder( controller: scrollController, physics: AlwaysScrollableScrollPhysics(), padding: EdgeInsets.all(10.0), itemCount: currentOrders.length + (hasMoreData ? 1 : 0), itemBuilder: (context, itemIndex) { if (itemIndex == currentOrders.length) { return _buildLoadMoreIndicator(isLoading); } return _buildOrderItem(currentOrders[itemIndex]); }, ); } ), ), ), ); }), ), ); } // 根据索引获取订单列表 List> _getOrderListByIndex(int index) { switch (index) { case 0: return _allOrders; case 1: return _pendingPaymentOrders; case 2: return _pendingVerificationOrders; case 3: return _completedOrders; case 4: return _closedOrders; case 5: return _refundingOrders; case 6: return _refundedOrders; case 7: return _cancelledOrders; default: return _allOrders; } } // 加载更多指示器 Widget _buildLoadMoreIndicator(bool isLoading) { return Padding( padding: EdgeInsets.symmetric(vertical: 15.0), child: Center( child: isLoading ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ), SizedBox(width: 10), Text('加载中...', style: TextStyle(color: Colors.grey)), ], ) : Text('没有更多数据了', style: TextStyle(color: Colors.grey)), ), ); } Widget emptyTip() { return Container( width: double.infinity, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/images/empty.png', width: 100.0, ), SizedBox(height: 10), Text( '还没有相关订单~', style: TextStyle(color: Colors.grey, fontSize: 12.0), ) ], ), ); } }