import 'package:flutter/material.dart'; import 'package:loopin/api/shop_api.dart'; import 'package:loopin/service/http.dart'; import '../../../behavior/custom_scroll_behavior.dart'; class SellerRevenue extends StatefulWidget { const SellerRevenue({super.key}); @override State createState() => _SellerRevenueState(); } class _SellerRevenueState extends State { // 分页内容 int pageNum = 1; final int pageSize = 10; bool isLoadingMore = false; bool isRefreshing = false; List> revenueList = []; int totalRecords = 0; // 添加总记录数 // 营收统计数据 double totalRevenue = 1000.00; double pendingCount = 17; double settledCount = 30; late ScrollController scrollController = ScrollController(); @override void initState() { super.initState(); // 监听滚动事件 scrollController.addListener(_scrollListener); // 获取营收摘要 getRevenueInfo(); // 获取初始流水列表 getRevenueList(false); } @override void dispose() { scrollController.removeListener(_scrollListener); scrollController.dispose(); super.dispose(); } // 滚动监听 void _scrollListener() { if (scrollController.position.pixels >= scrollController.position.maxScrollExtent - 50 && // 添加一个阈值,提前加载 !isLoadingMore && !isRefreshing && revenueList.isNotEmpty && revenueList.length < totalRecords) { // 确保有数据且未加载完所有数据时才加载更多 getRevenueList(true); } } // 获取营收摘要 void getRevenueInfo() async { try { final res = await Http.post(ShopApi.revenueList, data: {}); if (res['code'] == 200 && res['data'] != null) { final data = res['data']; totalRevenue = data['moneyIn'] ?? 0.00; pendingCount = data['credited']?? 0.00; settledCount = data['pending'] ?? 0.00; } } catch (e) { print('获取营收摘要: $e'); } } // 获取流水列表 void getRevenueList(bool loadMore) async { if (isLoadingMore || isRefreshing) return; setState(() { if (!loadMore) { pageNum = 1; // 重置为第一页 isRefreshing = true; revenueList = []; totalRecords = 0; // 重置总记录数 } else { isLoadingMore = true; } }); try { final res = await Http.post(ShopApi.revenueList, data: { 'current': pageNum, // 当前页码 'size': pageSize, }); if (res['code'] == 200 && res['data'] != null) { final data = res['data']; final List> newRevenues = List>.from(data['records'] ?? []); final int total = data['total']; debugPrint(data.toString(), wrapWidth: 1024); setState(() { if (loadMore) { revenueList.addAll(newRevenues); } else { revenueList = newRevenues; } totalRecords = total; if (newRevenues.isNotEmpty && revenueList.length < total) { pageNum++; // 增加页码 isLoadingMore = false; // 重置加载状态,允许再次加载 } else { isLoadingMore = false; // 没有更多数据 } isRefreshing = false; }); } } catch (e) { print('获取营收列表失败: $e'); setState(() { isLoadingMore = false; isRefreshing = false; }); } } // 刷新数据时重置分页状态 void _refreshData() { setState(() { pageNum = 1; isLoadingMore = false; totalRecords = 0; }); getRevenueList(false); } // 构建营收项 Widget _buildRevenueItem(Map revenue) { return Container( margin: EdgeInsets.only(bottom: 10.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ // 第一列:用户 Expanded( flex: 1, child: Text( revenue['changeDesc']??'未知', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.black, ), overflow: TextOverflow.ellipsis, ), ), // 第二列:流水明细 Expanded( flex: 1, child: Text( '${revenue['changeType'] == '1' ? '+' : '-'}${revenue['changeAmount']}', style: TextStyle( fontSize: 14, color: revenue['changeType'] == '1' ? Colors.red : Colors.green, ), overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, ), ), // 第三列:流水日期 Expanded( flex: 1, child: Text( revenue['createTime'] ?? '日期', style: TextStyle( fontSize: 12, color: Colors.black, ), textAlign: TextAlign.right, ), ), ], ), ); } // 构建顶部营收面板 Widget _buildRevenuePanel() { return Container( margin: EdgeInsets.symmetric(horizontal: 12.0), padding: EdgeInsets.all(20), decoration: BoxDecoration( color: Color(0xFF4477FC), borderRadius: BorderRadius.circular(6), boxShadow: [ BoxShadow( color: Colors.black.withAlpha(15), blurRadius: 10, offset: Offset(0, 2), ), ], ), child: Column( children: [ // 总入账 Text( '总入账', style: TextStyle( fontSize: 14, color: Colors.white, ), ), SizedBox(height: 8), Text( '¥$totalRevenue', style: TextStyle( fontSize: 28, fontWeight: FontWeight.bold, color: Colors.white, ), ), SizedBox(height: 20), // 待入账和已入账 Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( children: [ Text( '待入账', style: TextStyle( fontSize: 14, color: Colors.white, ), ), SizedBox(height: 4), Text( '$pendingCount', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), Container( width: 1, height: 30, color: Colors.white, ), Column( children: [ Text( '已入账', style: TextStyle( fontSize: 14, color: Colors.white, ), ), SizedBox(height: 4), Text( '$settledCount', style: TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.white, ), ), ], ), ], ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor:Color(0xFFF8F8F8), body: Stack( children: [ // 背景图片 - 从顶部开始 Positioned.fill( child: Image.asset( 'assets/images/income_bg.png', fit: BoxFit.contain, alignment: Alignment.topCenter, ), ), // 主要内容区域 Column( children: [ // AppBar区域 Container( height: kToolbarHeight + MediaQuery.of(context).padding.top, child: AppBar( title: Text( '商家营收', style: TextStyle( fontSize: 18, color: Colors.white, ), ), centerTitle: true, backgroundColor: Colors.transparent, elevation: 0, iconTheme: IconThemeData(color: Colors.white), ), ), // 营收面板 SizedBox(height: 10), _buildRevenuePanel(), SizedBox(height: 10), // 流水明细 Expanded( child: Container( color: Colors.white, margin: EdgeInsets.symmetric(horizontal: 12.0), child: Column( children: [ // 流水明细标题 Container( padding: EdgeInsets.only( left: 12.0, right: 12.0, top: 10.0, ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( flex: 1, child: Text( '来源', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black, ), ), ), Expanded( flex: 1, child: Text( '流水明细', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black, ), textAlign: TextAlign.center, ), ), Expanded( flex: 1, child: Text( '流水日期', style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, color: Colors.black, ), textAlign: TextAlign.right, ), ), ], ), ), SizedBox(height: 10), // 流水列表区域 Expanded( child: Container( margin: EdgeInsets.symmetric(horizontal: 12.0), child: RefreshIndicator( onRefresh: () async { _refreshData(); }, child: ScrollConfiguration( behavior: CustomScrollBehavior().copyWith(scrollbars: false), child: revenueList.isEmpty && !isRefreshing ? emptyTip() : Container( child: ListView.builder( padding: EdgeInsets.zero, controller: scrollController, physics: AlwaysScrollableScrollPhysics(), itemCount: revenueList.length + (isLoadingMore ? 1 : 0), itemBuilder: (context, index) { if (index == revenueList.length) { return _buildLoadMoreIndicator(); } return _buildRevenueItem(revenueList[index]); }, ), ), ), ), ), ), ], ), ), ), ], ), ], ), ); } // 加载更多指示器 Widget _buildLoadMoreIndicator() { return Padding( padding: EdgeInsets.symmetric(vertical: 15.0), child: Center( child: isLoadingMore ? Row( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ), SizedBox(width: 10), Text('加载中...', style: TextStyle(color: Colors.grey)), ], ) : revenueList.length >= totalRecords ? Text('没有更多数据了', style: TextStyle(color: Colors.grey)) : SizedBox(), // 如果还有数据但不在加载中,不显示任何内容 ), ); } Widget emptyTip() { return Container( width: double.infinity, padding: EdgeInsets.all(12.0), color: Colors.white, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'assets/images/empty.png', width: 100.0, errorBuilder: (context, error, stackTrace) { return Icon(Icons.receipt_long, size: 60, color: Colors.grey); }, ), SizedBox(height: 10), Text( '还没有营收记录~', style: TextStyle(color: Colors.grey, fontSize: 12.0), ) ], ), ); } }