From c6c6acf9dc540f071a2bd74f8cea04912b6539cf Mon Sep 17 00:00:00 2001 From: cuiyouliang <799699717@qq.com> Date: Fri, 12 Sep 2025 17:23:08 +0800 Subject: [PATCH] =?UTF-8?q?=E8=AE=A2=E5=8D=95=E8=81=94=E8=B0=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/api/shop_api.dart | 3 + lib/pages/my/all_function.dart | 3 +- lib/pages/my/index.dart | 2 +- lib/pages/my/merchant/order.dart | 0 lib/pages/order/detail.dart | 38 +- .../order/{seller.dart => my_order.dart} | 8 +- lib/pages/order/seller_detail.dart | 751 ++++++++++++++++++ lib/pages/order/seller_order.dart | 728 +++++++++++++++++ lib/router/index.dart | 12 +- 9 files changed, 1522 insertions(+), 23 deletions(-) delete mode 100644 lib/pages/my/merchant/order.dart rename lib/pages/order/{seller.dart => my_order.dart} (99%) create mode 100644 lib/pages/order/seller_detail.dart create mode 100644 lib/pages/order/seller_order.dart diff --git a/lib/api/shop_api.dart b/lib/api/shop_api.dart index 1521438..f3e8c3d 100644 --- a/lib/api/shop_api.dart +++ b/lib/api/shop_api.dart @@ -30,6 +30,9 @@ class ShopApi { // app端我的订单 static const String myOrderList= '/app/order/page'; + // app商家订单 + static const String sellerOrderList= '/app/merchant/order/page'; + // 商家营收摘要 static const String revenueInfo= '/app/merchant/account/statistic'; diff --git a/lib/pages/my/all_function.dart b/lib/pages/my/all_function.dart index 210a2fa..ee1a9f0 100644 --- a/lib/pages/my/all_function.dart +++ b/lib/pages/my/all_function.dart @@ -173,7 +173,7 @@ class _AllFunctionsPageState extends State { void _handleFunctionTap(String functionId) { switch (functionId) { case 'home_order': - Get.toNamed('/sellerOrder'); + Get.toNamed('/myOrder'); break; case 'home_balance': showLogoutDialog(context); @@ -184,6 +184,7 @@ class _AllFunctionsPageState extends State { case 'home_promo': break; case 'more_seller_order': + Get.toNamed('/sellerOrder'); break; case 'more_seller_income': Get.toNamed('/merchant/income'); diff --git a/lib/pages/my/index.dart b/lib/pages/my/index.dart index 34ccc2e..13ffb12 100644 --- a/lib/pages/my/index.dart +++ b/lib/pages/my/index.dart @@ -856,7 +856,7 @@ class MyPageState extends State with SingleTickerProviderStateMixin { mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _buildOrderIcon('assets/images/ico_order.png', '订单', () { - Get.toNamed('/sellerOrder'); + Get.toNamed('/myOrder'); }), _buildOrderIcon('assets/images/ico_dhx.png', '余额logout', () { showLogoutDialog(context); diff --git a/lib/pages/my/merchant/order.dart b/lib/pages/my/merchant/order.dart deleted file mode 100644 index e69de29..0000000 diff --git a/lib/pages/order/detail.dart b/lib/pages/order/detail.dart index 9f0bc9b..2352397 100644 --- a/lib/pages/order/detail.dart +++ b/lib/pages/order/detail.dart @@ -48,7 +48,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat void getOrderRealStatus({required String orderId}) async { try { final res = await Http.get('${ShopApi.goodsOrderStatus}/$orderId'); - Get.toNamed('/sellerOrder'); + Get.toNamed('/myOrder'); } catch (e) { print('报错-------------->${e}'); } @@ -61,7 +61,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat _isLoading = true; }); final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId'); - print('订单详情-------------->${res['data']}'); + debugPrint('订单详情-------------->${res['data']}'); setState(() { orderGoodsInfo = res['data']; _isLoading = false; @@ -193,6 +193,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat // 获取订单状态文本 String getOrderStatusText(int status) { + print('111111111111$status'); switch (status) { case 0: return '待付款'; @@ -235,9 +236,20 @@ class _OrderDetailState extends State with SingleTickerProviderStat } } + // 获取第一个商品信息 + dynamic _getFirstProductInfo() { + if (orderGoodsInfo == null || + orderGoodsInfo['items'] == null || + orderGoodsInfo['items'] is! List || + orderGoodsInfo['items'].isEmpty) { + return {}; + } + return orderGoodsInfo['items'][0]; + } + // 构建商品图片 Widget _buildProductImage() { - final productInfo = orderGoodsInfo?['productInfo'][0]; + final productInfo = _getFirstProductInfo(); final picUrl = productInfo?['pic']; if (picUrl == null || picUrl.isEmpty) { @@ -301,7 +313,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat Widget buildBottomButtons() { if (orderGoodsInfo == null) return SizedBox.shrink(); - int orderStatus = orderGoodsInfo?['orderStatus'] ?? 0; + int orderStatus = orderGoodsInfo?['status'] ?? 0; switch (orderStatus) { case 0: // 待付款 @@ -455,6 +467,8 @@ class _OrderDetailState extends State with SingleTickerProviderStat @override Widget build(BuildContext context) { + final productInfo = _getFirstProductInfo(); + return Scaffold( backgroundColor: Colors.grey[50], appBar: AppBar( @@ -473,7 +487,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat physics: BouncingScrollPhysics(), padding: EdgeInsets.all(10.0), children: [ - if (orderGoodsInfo?['orderStatus'] == 0) + if (orderGoodsInfo?['status'] == 0) Container( padding: EdgeInsets.all(12.0), margin: EdgeInsets.only(bottom: 10.0), @@ -501,7 +515,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat ), SizedBox(width: 4), Text( - getOrderStatusText(orderGoodsInfo?['orderStatus']), + getOrderStatusText(orderGoodsInfo?['status']), style: TextStyle(color: Colors.orange), ), SizedBox(width: 4), @@ -565,9 +579,9 @@ class _OrderDetailState extends State with SingleTickerProviderStat children: [ Spacer(), Text( - getOrderStatusText(orderGoodsInfo?['orderStatus']), + getOrderStatusText(orderGoodsInfo?['status']), style: TextStyle( - color: getOrderStatusColor(orderGoodsInfo?['orderStatus']), + color: getOrderStatusColor(orderGoodsInfo?['status']), fontWeight: FontWeight.bold, ), ) @@ -584,7 +598,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - '${orderGoodsInfo?['productInfo'][0]['productName']}', + productInfo['productName']?.toString() ?? '商品名称未知', maxLines: 2, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 14), @@ -593,12 +607,12 @@ class _OrderDetailState extends State with SingleTickerProviderStat Row( children: [ Text( - '¥${orderGoodsInfo?['productInfo'][0]['salePrice']}', + '¥${productInfo['salePrice']?.toString() ?? '0.00'}', style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), ), Spacer(), Text( - 'x${orderGoodsInfo?['productInfo'][0]['buyNum'] ?? 1}', + 'x${productInfo['buyNum']?.toString() ?? '1'}', style: TextStyle(color: Colors.grey), ), ], @@ -654,7 +668,7 @@ class _OrderDetailState extends State with SingleTickerProviderStat children: [ _buildOrderInfoRow('订单号', orderGoodsInfo?['orderId'] ?? ''), _buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime'] ?? ''), - _buildOrderInfoRow('购买数量', (orderGoodsInfo?['productInfo'][0]['buyNum'] ?? 0).toString()), + _buildOrderInfoRow('购买数量', (productInfo['buyNum'] ?? 0).toString()), _buildOrderInfoRow('订单金额', '¥${orderGoodsInfo?['totalAmount'] ?? '0.00'}'), _buildOrderInfoRow('实付金额', '¥${orderGoodsInfo?['payAmount'] ?? '0.00'}'), ], diff --git a/lib/pages/order/seller.dart b/lib/pages/order/my_order.dart similarity index 99% rename from lib/pages/order/seller.dart rename to lib/pages/order/my_order.dart index 87aebc6..cc44349 100644 --- a/lib/pages/order/seller.dart +++ b/lib/pages/order/my_order.dart @@ -10,14 +10,14 @@ import 'package:loopin/service/http.dart'; import '../../behavior/custom_scroll_behavior.dart'; -class Seller extends StatefulWidget { - const Seller({super.key}); +class MyOrder extends StatefulWidget { + const MyOrder({super.key}); @override - State createState() => _SellerState(); + State createState() => _MyOrderState(); } -class _SellerState extends State with SingleTickerProviderStateMixin { +class _MyOrderState extends State with SingleTickerProviderStateMixin { GlobalKey scaffoldKey = GlobalKey(); // 分页内容 - 为每个Tab单独存储数据 final int pageSize = 10; diff --git a/lib/pages/order/seller_detail.dart b/lib/pages/order/seller_detail.dart new file mode 100644 index 0000000..c7726ce --- /dev/null +++ b/lib/pages/order/seller_detail.dart @@ -0,0 +1,751 @@ +library; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:get/get.dart'; +import 'package:loopin/service/http.dart'; +import 'package:loopin/api/shop_api.dart'; +import 'package:shirne_dialog/shirne_dialog.dart'; +import 'package:timer_count_down/timer_count_down.dart'; +import 'package:loopin/utils/wxsdk.dart'; +import '../../behavior/custom_scroll_behavior.dart'; +import '../../utils/lifecycle_handler.dart'; + +class SellerOrderDetail extends StatefulWidget { + const SellerOrderDetail({super.key}); + + @override + State createState() => _SellerOrderDetailState(); +} + +class _SellerOrderDetailState extends State with SingleTickerProviderStateMixin { + late String _orderId; + dynamic orderGoodsInfo; + int _initialSeconds = 30 * 60; // 存储初始秒数 + bool _countdownFinished = false; // 新增标志位,用于跟踪倒计时是否结束 + bool _isLoading = true; // 添加加载状态 + + @override + void initState() { + super.initState(); + _orderId = Get.arguments['orderId'] ?? ''; + getOrderDetail(orderId: _orderId); + LifecycleHandler.onAppResumed = _onAppResumed; + } + + @override + void dispose() { + LifecycleHandler.onAppResumed = null; + super.dispose(); + } + + void _onAppResumed() { + print('App回到前台,刷新订单状态,订单Id${_orderId}'); + getOrderDetail(orderId: _orderId); // 刷新订单详情数据 + _showPaymentResultDialog(); // 展示支付结果弹框 + } + + // 获取订单状态 + void getOrderRealStatus({required String orderId}) async { + try { + final res = await Http.get('${ShopApi.goodsOrderStatus}/$orderId'); + Get.toNamed('/myOrder'); + } catch (e) { + print('报错-------------->${e}'); + } + } + + // 获取订单详情信息,包含商品参数 + void getOrderDetail({required String orderId}) async { + try { + setState(() { + _isLoading = true; + }); + final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId'); + print('订单详情-------------->${res['data']}'); + setState(() { + orderGoodsInfo = res['data']; + _isLoading = false; + }); + } catch (e) { + setState(() { + _isLoading = false; + }); + MyDialog.toast('获取订单详情失败'); + } + } + + // 取消订单 + void _cancelOrder() async { + try { + final res = await Http.post('${ShopApi.cancelGoodsOrder}/$_orderId'); + getOrderDetail(orderId: _orderId); // 刷新订单详情数据 + } catch (e) { + MyDialog.toast('取消订单失败'); + } + } + + // 显示支付结果弹框 + void _showPaymentResultDialog() { + showDialog( + context: context, + barrierDismissible: false, + barrierColor: Colors.black54, + builder: (BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16.0), + ), + child: Padding( + padding: const EdgeInsets.all(20.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // 图标 + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Color(0xFFFFF8E6), + shape: BoxShape.circle, + ), + child: Icon( + Icons.payment, + size: 32, + color: Color(0xFFFFA500), + ), + ), + SizedBox(height: 16), + + // 标题 + Text( + '支付确认', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: Colors.black87, + ), + ), + SizedBox(height: 8), + + // 描述 + Text( + '请确认您的支付状态', + style: TextStyle( + fontSize: 14, + color: Colors.grey[600], + ), + textAlign: TextAlign.center, + ), + SizedBox(height: 24), + + // 按钮区域 + Row( + children: [ + // 支付遇到问题按钮 + Expanded( + child: OutlinedButton( + onPressed: () { + Navigator.of(context).pop(); + getOrderRealStatus(orderId: _orderId); // 主动再次拉取订单状态 + }, + style: OutlinedButton.styleFrom( + backgroundColor: Colors.white, + foregroundColor: Colors.grey[700], + side: BorderSide(color: Colors.grey[300]!), + padding: EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('支付遇到问题'), + ), + ), + SizedBox(width: 12), + + // 支付完成按钮 + Expanded( + child: ElevatedButton( + onPressed: () { + Navigator.of(context).pop(); + getOrderRealStatus(orderId: _orderId); // 同时主动拉取订单状态 + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFFFF5000), + foregroundColor: Colors.white, + padding: EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Text('支付完成'), + ), + ), + ], + ), + ], + ), + ), + ); + }, + ); + } + + // 获取订单状态文本 + String getOrderStatusText(int status) { + switch (status) { + case 0: + return '待付款'; + case 1: + return '待核销'; + case 2: + return '已完成'; + case 3: + return '已关闭'; + case 4: + return '退款中'; + case 5: + return '已退款'; + case 6: + return '已取消'; + default: + return '未知状态'; + } + } + + // 获取订单状态颜色 + Color getOrderStatusColor(int status) { + switch (status) { + 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; + } + } + + // 获取商品信息列表 + List getProductInfoList() { + // 优先使用 items 字段 + if (orderGoodsInfo?['items'] != null && orderGoodsInfo!['items'] is List) { + return orderGoodsInfo!['items']; + } + // 如果 items 为空,使用 productInfo 字段 + if (orderGoodsInfo?['productInfo'] != null && orderGoodsInfo!['productInfo'] is List) { + return orderGoodsInfo!['productInfo']; + } + // 如果都为空,返回空列表 + return []; + } + + // 获取第一个商品信息 + dynamic getFirstProductInfo() { + final productList = getProductInfoList(); + return productList.isNotEmpty ? productList[0] : null; + } + + // 构建商品图片 + Widget _buildProductImage(dynamic productInfo) { + final picUrl = productInfo?['pic']; + + if (picUrl == null || picUrl.isEmpty) { + return Container( + width: 80.0, + height: 80.0, + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(8.0), + ), + child: Icon( + Icons.shopping_bag_outlined, + size: 40.0, + color: Colors.grey[400], + ), + ); + } + + return Image.network( + picUrl, + width: 80.0, + height: 80.0, + fit: BoxFit.cover, + errorBuilder: (context, error, stackTrace) { + return Container( + width: 80.0, + height: 80.0, + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(8.0), + ), + child: Icon( + Icons.shopping_bag_outlined, + size: 40.0, + color: Colors.grey[400], + ), + ); + }, + loadingBuilder: (context, child, loadingProgress) { + if (loadingProgress == null) return child; + return Container( + width: 80.0, + height: 80.0, + decoration: BoxDecoration( + color: Colors.grey[100], + borderRadius: BorderRadius.circular(8.0), + ), + child: Center( + child: CircularProgressIndicator( + value: loadingProgress.expectedTotalBytes != null + ? loadingProgress.cumulativeBytesLoaded / loadingProgress.expectedTotalBytes! + : null, + ), + ), + ); + }, + ); + } + + // 构建商品列表 + Widget _buildProductList() { + final productList = getProductInfoList(); + + if (productList.isEmpty) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 16.0), + child: Text( + '暂无商品信息', + style: TextStyle(color: Colors.grey, fontSize: 14), + ), + ); + } + + return Column( + children: productList.map((product) { + return Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _buildProductImage(product), + SizedBox(width: 10.0), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + product?['productName']?.toString() ?? '未知商品', + maxLines: 2, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 14), + ), + SizedBox(height: 8), + Row( + children: [ + Text( + '¥${product?['salePrice']?.toString() ?? '0.00'}', + style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), + ), + Spacer(), + Text( + 'x${product?['buyNum']?.toString() ?? '1'}', + style: TextStyle(color: Colors.grey), + ), + ], + ), + ], + ), + ) + ], + ), + ); + }).toList(), + ); + } + + // 构建底部按钮 + Widget buildBottomButtons() { + if (orderGoodsInfo == null) return SizedBox.shrink(); + + int orderStatus = orderGoodsInfo?['status'] ?? 0; + + switch (orderStatus) { + case 0: // 待付款 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + ElevatedButton( + onPressed: () { + // 取消订单逻辑 + _cancelOrder(); + }, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.white), + foregroundColor: WidgetStateProperty.all(Colors.black87), + side: WidgetStateProperty.all(BorderSide(color: Colors.grey[300]!)), + ), + child: const Text('取消订单'), + ), + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () { + // 打开微信小程序的某个页面地址,如pages/index/index + Wxsdk.openMiniApp(orderId: _orderId); + }, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Color(0xff07c160)), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('去支付'), + ), + ], + ); + + case 1: // 待核销 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('待核销'), + ), + ], + ); + + case 2: // 已完成 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.green), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('已完成'), + ), + ], + ); + + case 3: // 已关闭 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.grey), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('已关闭'), + ), + ], + ); + + case 4: // 退款中 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.orange), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('退款中'), + ), + ], + ); + + case 5: // 已退款 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.grey), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('已退款'), + ), + ], + ); + + case 6: // 已取消 + return Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const SizedBox(width: 10.0), + ElevatedButton( + onPressed: () {}, + style: ButtonStyle( + backgroundColor: WidgetStateProperty.all(Colors.grey), + foregroundColor: WidgetStateProperty.all(Colors.white), + ), + child: const Text('已取消'), + ), + ], + ); + + default: + return SizedBox.shrink(); + } + } + + Widget emptyTip() { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + 'assets/images/empty.png', + width: 100.0, + ), + SizedBox(height: 16), + Text( + '还没有订单信息~', + style: TextStyle(color: Colors.grey, fontSize: 12.0), + ) + ], + ); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.grey[50], + appBar: AppBar( + backgroundColor: Color(0xFFFF5000), + foregroundColor: Colors.white, + title: Text('订单详情'), + titleSpacing: 1.0, + ), + body: _isLoading + ? Center(child: CircularProgressIndicator()) + : orderGoodsInfo == null + ? emptyTip() + : ScrollConfiguration( + behavior: CustomScrollBehavior().copyWith(scrollbars: false), + child: ListView( + physics: BouncingScrollPhysics(), + padding: EdgeInsets.all(10.0), + children: [ + if (orderGoodsInfo?['status'] == 0) // 修正:应该是 status 而不是 orderStatus + Container( + padding: EdgeInsets.all(12.0), + margin: EdgeInsets.only(bottom: 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( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon( + Icons.info, + size: 16.0, + color: Colors.orange, + ), + SizedBox(width: 4), + Text( + getOrderStatusText(orderGoodsInfo?['status'] ?? 0), + style: TextStyle(color: Colors.orange), + ), + SizedBox(width: 4), + Text( + _countdownFinished ? '倒计时已结束' : '剩余 ', + style: TextStyle(color: Colors.grey), + ), + if (!_countdownFinished) + Countdown( + seconds: _initialSeconds, + build: (_, double time) { + int m = ((time % 3600) ~/ 60).toInt(); + int s = (time % 60).toInt(); + String formatted = "${m.toString().padLeft(2, '0')}:${s.toString().padLeft(2, '0')}"; + + return Text( + formatted, + style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold), + ); + }, + interval: Duration(seconds: 1), + onFinished: () { + print("倒计时结束"); + _cancelOrder(); + setState(() { + _countdownFinished = true; + }); + }, + ), + ], + ), + SizedBox(height: 4), + Text( + _countdownFinished + ? '订单已自动取消' + : '超过30分钟未支付,订单将自动取消', + style: TextStyle(color: Colors.grey, fontSize: 12.0), + ), + ], + ), + ), + // 商品信息 + 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: [ + Spacer(), + Text( + getOrderStatusText(orderGoodsInfo?['status'] ?? 0), + style: TextStyle( + color: getOrderStatusColor(orderGoodsInfo?['status'] ?? 0), + fontWeight: FontWeight.bold, + ), + ) + ], + ), + SizedBox(height: 10), + _buildProductList(), + ], + ), + ), + // 订单信息 + 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: [ + Text( + '订单信息', + style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.bold), + ), + Spacer(), + InkWell( + child: Icon( + Icons.copy, + color: Colors.grey, + size: 18.0, + ), + onTap: () async { + await Clipboard.setData(ClipboardData(text: _orderId)); + MyDialog.toast('订单已复制到剪切板', icon: Icon(Icons.check_circle)); + }, + ) + ], + ), + SizedBox(height: 10), + Column( + children: [ + _buildOrderInfoRow('订单号', orderGoodsInfo?['orderId']?.toString() ?? ''), + _buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime']?.toString() ?? ''), + _buildOrderInfoRow('购买数量', _calculateTotalQuantity().toString()), + _buildOrderInfoRow('订单金额', '¥${orderGoodsInfo?['totalAmount']?.toString() ?? '0.00'}'), + _buildOrderInfoRow('实付金额', '¥${orderGoodsInfo?['payAmount']?.toString() ?? '0.00'}'), + ], + ) + ], + ), + ), + ], + ), + ), + // 底部固定按钮 + bottomNavigationBar: orderGoodsInfo == null + ? null + : SafeArea( + minimum: const EdgeInsets.all(10), + child: Container( + height: 60.0, + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0), + child: buildBottomButtons(), + ), + ), + ); + } + + // 计算总购买数量 + int _calculateTotalQuantity() { + final productList = getProductInfoList(); + int total = 0; + for (var product in productList) { + total += (product?['buyNum'] as int? ?? 0); + } + return total; + } + + Widget _buildOrderInfoRow(String label, String value) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 6.0), + child: Row( + children: [ + Text( + label, + style: TextStyle(color: Colors.grey, fontSize: 13), + ), + Spacer(), + Text(value, style: TextStyle(fontSize: 13)), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/pages/order/seller_order.dart b/lib/pages/order/seller_order.dart new file mode 100644 index 0000000..651bff5 --- /dev/null +++ b/lib/pages/order/seller_order.dart @@ -0,0 +1,728 @@ +/// 商家的订单 +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 SellerOrder extends StatefulWidget { + const SellerOrder({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.sellerOrderList, 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('/sellerOrder/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), + ) + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/router/index.dart b/lib/router/index.dart index dae93df..38a92bc 100644 --- a/lib/router/index.dart +++ b/lib/router/index.dart @@ -22,8 +22,8 @@ import 'package:loopin/pages/my/user_info.dart'; import 'package:loopin/pages/my/vloger.dart'; import 'package:loopin/pages/my/all_function.dart'; import 'package:loopin/pages/my/merchant/income.dart'; -import 'package:loopin/pages/my/merchant/order.dart'; -import 'package:loopin/pages/order/seller.dart'; +import 'package:loopin/pages/order/my_order.dart'; +import 'package:loopin/pages/order/seller_order.dart'; import 'package:loopin/pages/search/index.dart'; import 'package:loopin/pages/search/search-result.dart'; import 'package:loopin/pages/video/commonVideo.dart'; @@ -35,6 +35,7 @@ import '../pages/auth/login.dart'; // 商品详细 import '../pages/goods/detail.dart'; import '../pages/order/detail.dart'; +import '../pages/order/seller_detail.dart'; // 订单 import '../pages/order/index.dart'; // 引入工具类 @@ -47,7 +48,9 @@ final Map routes = { // '/chatNoFriend': const ChatNoFriend(), // '/chatGroup': const ChatGroup(), '/order': const Order(), - '/sellerOrder': const Seller(), + '/sellerOrder': const SellerOrder(), + '/sellerOrder/detail': const SellerOrderDetail(), + '/myOrder': const MyOrder(), '/order/detail': const OrderDetail(), '/vloger': const Vloger(), '/report': const ReportPage(), @@ -57,8 +60,7 @@ final Map routes = { //settins '/setting': const Setting(), '/functions': const AllFunctionsPage(), - '/merchant/income': const SellerRevenue(), - //'/merchant/order': const SellerRevenue(), + '/merchant/income': const SellerRevenue(), '/userInfo': const UserInfo(), '/notifications': const Setting(), '/privacy': const Setting(),