订单联调

This commit is contained in:
cuiyouliang 2025-09-12 15:45:53 +08:00
parent 6350b43b1c
commit c23f939c49
5 changed files with 714 additions and 441 deletions

View File

@ -28,7 +28,7 @@ class ShopApi {
static const String cancelGoodsOrder= '/app/order/cancel';
// app端我的订单
static const String myOrderList= '/oms/order/list';
static const String myOrderList= '/app/order/page';
//
static const String revenueInfo= '/app/merchant/account/statistic';

View File

@ -675,7 +675,7 @@ class _GoodsState extends State<Goods> {
// String orderId = '1958380183857659904'; //
String orderId = await createOrder(shopObj['skuList'][0]['id']);
if (orderId.isNotEmpty) {
Get.toNamed('/order/detail', arguments: orderId);
Get.toNamed('/order/detail', arguments: {'orderId': orderId});
} else {
MyDialog.toast('生成订单失败', icon: const Icon(Icons.warning), style: ToastStyle(backgroundColor: Colors.red.withAlpha(200)));
}

View File

@ -160,7 +160,7 @@ class _IndexPageState extends State<IndexPage> with SingleTickerProviderStateMix
}
},
onTabChanged: (index) {
logger.w("当前选中tab: $index");
logger.w("当前选中ssssstab: $index");
},
dynamicTabs: tabs,
tabAlignment: TabAlignment.start,

View File

@ -1,7 +1,4 @@
library;
import 'dart:async';
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:get/get.dart';
@ -10,8 +7,6 @@ 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 'package:loopin/utils/index.dart';
import '../../behavior/custom_scroll_behavior.dart';
import '../../utils/lifecycle_handler.dart';
@ -25,43 +20,35 @@ class OrderDetail extends StatefulWidget {
class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStateMixin {
late String _orderId;
dynamic orderGoodsInfo;
int _initialSeconds = 30 * 60;//
int _initialSeconds = 30 * 60; //
bool _countdownFinished = false; //
bool _isLoading = true; //
@override
void initState() {
super.initState();
_orderId = Get.arguments;
_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); //
getOrderRealStatus(orderId: _orderId); //
_showPaymentResultDialog(); //
}
//
void getOrderRealStatus({required String orderId}) async {
try {
final res = await Http.get('${ShopApi.goodsOrderStatus}/$orderId');
// transState
var orderStatus = res['data']['transState'];
print('状态-------------->${orderStatus}');
// orderStatus
setState(() {
orderGoodsInfo['orderStatus'] = orderStatus;
});
if (orderStatus == 2) { //
MyDialog.toast('支付成功');
}
Get.toNamed('/sellerOrder');
} catch (e) {
print('报错-------------->${e}');
}
@ -70,32 +57,35 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
//
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']; // data
orderGoodsInfo = res['data'];
_isLoading = false;
});
} catch (e) {
Get.back();
setState(() {
_isLoading = false;
});
MyDialog.toast('获取订单详情失败');
}
}
//
void _cancelOrder() async {
print('取消订单: $_orderId');
try {
final res = await Http.post('${ShopApi.cancelGoodsOrder}/$_orderId');
print('取消订单成功-------------->${res}');
getOrderDetail(orderId: _orderId); //
} catch (e) {
print('取消订单失败-------------->${e}');
MyDialog.toast('取消订单失败');
}
}
//
void _showPaymentResultDialog() {
showDialog(
context: context,
barrierDismissible: false,
@ -157,7 +147,6 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
child: OutlinedButton(
onPressed: () {
Navigator.of(context).pop();
// getOrderDetail(orderId: _orderId);
getOrderRealStatus(orderId: _orderId); //
},
style: OutlinedButton.styleFrom(
@ -199,26 +188,26 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
),
);
},
).then((value) {
});
);
}
//
String getOrderStatusText(int status) {
switch (status) {
case 0:
return '';
return '';
case 1:
return '支付中';
return '待核销';
case 2:
return '支付';
return '完成';
case 3:
return '取消';
return '关闭';
case 4:
return '退款中';
case 5:
return '已退款';
case 10:
return '无效订单';
case 6:
return '已取消';
default:
return '未知状态';
}
@ -228,20 +217,86 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
Color getOrderStatusColor(int status) {
switch (status) {
case 0:
return Colors.orange;
return Colors.grey;
case 1:
return Colors.blue;
case 2:
return Colors.green;
case 3:
return Colors.red;
case 4:
case 10:
return Colors.orange;
case 5:
return Colors.grey;
case 6:
return Colors.grey;
default:
return Colors.black;
}
}
//
Widget _buildProductImage() {
final productInfo = orderGoodsInfo?['productInfo'][0];
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 buildBottomButtons() {
if (orderGoodsInfo == null) return SizedBox.shrink();
@ -249,7 +304,7 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
int orderStatus = orderGoodsInfo?['orderStatus'] ?? 0;
switch (orderStatus) {
case 0: //
case 0: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
@ -261,6 +316,7 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Colors.white),
foregroundColor: WidgetStateProperty.all(Colors.black87),
side: WidgetStateProperty.all(BorderSide(color: Colors.grey[300]!)),
),
child: const Text('取消订单'),
),
@ -279,70 +335,79 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
],
);
case 1: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () {
//
getOrderDetail(orderId: _orderId);
},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Colors.blue),
foregroundColor: WidgetStateProperty.all(Colors.white),
),
child: const Text('支付中'),
),
],
);
case 2: //
case 1: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 10.0),
ElevatedButton(
onPressed: () {
},
onPressed: () {},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
foregroundColor: WidgetStateProperty.all(Colors.white),
),
child: const Text('已支付'),
child: const Text('待核销'),
),
],
);
case 3: //
case 10: //
case 2: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 10.0),
ElevatedButton(
onPressed: () {
},
onPressed: () {},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
backgroundColor: WidgetStateProperty.all(Colors.green),
foregroundColor: WidgetStateProperty.all(Colors.white),
),
child: const Text('取消'),
child: const Text('完成'),
),
],
);
case 4: // 退
case 3: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 10.0),
ElevatedButton(
onPressed: () {
},
onPressed: () {},
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
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('已退款'),
@ -350,6 +415,22 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
],
);
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();
}
@ -358,12 +439,12 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
Widget emptyTip() {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
spacing: 5.0,
children: [
Image.asset(
'assets/images/empty.png',
width: 100.0,
),
SizedBox(height: 16),
Text(
'还没有订单信息~',
style: TextStyle(color: Colors.grey, fontSize: 12.0),
@ -374,7 +455,6 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
@override
Widget build(BuildContext context) {
if (orderGoodsInfo == null) {
return Scaffold(
backgroundColor: Colors.grey[50],
appBar: AppBar(
@ -383,125 +463,138 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
title: Text('订单详情'),
titleSpacing: 1.0,
),
body: Center(child: CircularProgressIndicator()),
);
}
int orderStatus = orderGoodsInfo?['orderStatus'] ?? 0;
bool showCountdown = orderStatus == 0; //
return Scaffold(
backgroundColor: Colors.grey[50],
appBar: AppBar(
backgroundColor: Color(0xFFFF5000),
foregroundColor: Colors.white,
title: Text('订单详情'),
titleSpacing: 1.0,
),
body: ScrollConfiguration(
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 (showCountdown)
Column(
spacing: 5.0,
children: [
Text.rich(
TextSpan(style: TextStyle(fontFamily: 'Arial'), children: [
WidgetSpan(
child: Icon(
Icons.info,
size: 16.0,
)),
TextSpan(text: getOrderStatusText(orderStatus)),
TextSpan(text: _countdownFinished ? '倒计时已结束' : ' 剩余 '),
if (!_countdownFinished)
WidgetSpan(
alignment: PlaceholderAlignment.middle,
child: Countdown(
seconds: _initialSeconds, // 使30
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: const TextStyle(color: Colors.red),
);
},
interval: const Duration(seconds: 1),
onFinished: () {
print("倒计时结束");
_cancelOrder();
setState(() {
_countdownFinished = true; //
});
},
),
),
]),
),
Text(
_countdownFinished
? '订单已自动取消'
: '超过30分钟未支付订单将自动取消',
style: TextStyle(color: Colors.grey, fontSize: 12.0),
),
SizedBox(
height: 10.0,
),
],
),
//
if (orderGoodsInfo?['orderStatus'] == 0)
Container(
padding: EdgeInsets.all(12.0),
margin: EdgeInsets.only(bottom: 10.0),
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
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?['orderStatus']),
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(
spacing: 10.0,
children: [
Row(
children: [
Spacer(),
Text(
getOrderStatusText(orderStatus),
style: TextStyle(color: getOrderStatusColor(orderStatus)),
getOrderStatusText(orderGoodsInfo?['orderStatus']),
style: TextStyle(
color: getOrderStatusColor(orderGoodsInfo?['orderStatus']),
fontWeight: FontWeight.bold,
),
)
],
),
SizedBox(height: 10),
Row(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 10.0,
children: [
Image.network(
'${orderGoodsInfo?['productInfo'][0]['pic']}',
width: 80.0,
),
_buildProductImage(),
SizedBox(width: 10.0),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
spacing: 5.0,
children: [
Text(
'${orderGoodsInfo?['productInfo'][0]['productName']}',
maxLines: 2,
overflow: TextOverflow.ellipsis,
style: TextStyle(fontSize: 14),
),
SizedBox(height: 8),
Row(
children: [
Text(
'¥${orderGoodsInfo?['productInfo'][0]['salePrice']}',
style: TextStyle(color: Colors.red),
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
),
Spacer(),
Text(
@ -522,16 +615,19 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
Container(
margin: EdgeInsets.only(bottom: 10.0),
padding: EdgeInsets.all(10.0),
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(15.0), boxShadow: [
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(
spacing: 10.0,
children: [
Row(
children: [
@ -544,69 +640,23 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
child: Icon(
Icons.copy,
color: Colors.grey,
size: 14.0,
size: 18.0,
),
onTap: ()async {
onTap: () async {
await Clipboard.setData(ClipboardData(text: _orderId));
MyDialog.toast('订单已复制到剪切板', icon: Icon(Icons.check_circle));
},
)
],
),
SizedBox(height: 10),
Column(
spacing: 5.0,
children: [
Row(
children: [
Text(
'订单号',
style: TextStyle(color: Colors.grey),
),
Spacer(),
Text(orderGoodsInfo?['orderId'] ?? '', style: TextStyle(fontSize: 12.0)),
],
),
Row(
children: [
Text(
'下单时间',
style: TextStyle(color: Colors.grey),
),
Spacer(),
Text(orderGoodsInfo?['createTime'] ?? '', style: TextStyle(fontSize: 12.0)),
],
),
Row(
children: [
Text(
'购买数量',
style: TextStyle(color: Colors.grey),
),
Spacer(),
Text((orderGoodsInfo?['productInfo'][0]['buyNum'] ?? 0).toString(),
style: TextStyle(fontSize: 12.0)),
],
),
Row(
children: [
Text(
'订单金额',
style: TextStyle(color: Colors.grey),
),
Spacer(),
Text('¥${orderGoodsInfo?['totalAmount']??'0.00'}', style: TextStyle(fontSize: 12.0)),
],
),
Row(
children: [
Text(
'实付金额',
style: TextStyle(color: Colors.grey),
),
Spacer(),
Text('¥${orderGoodsInfo?['payAmount']??'0.00'}', style: TextStyle(fontSize: 12.0)),
],
),
_buildOrderInfoRow('订单号', orderGoodsInfo?['orderId'] ?? ''),
_buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime'] ?? ''),
_buildOrderInfoRow('购买数量', (orderGoodsInfo?['productInfo'][0]['buyNum'] ?? 0).toString()),
_buildOrderInfoRow('订单金额', '¥${orderGoodsInfo?['totalAmount'] ?? '0.00'}'),
_buildOrderInfoRow('实付金额', '¥${orderGoodsInfo?['payAmount'] ?? '0.00'}'),
],
)
],
@ -616,10 +666,12 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
),
),
//
bottomNavigationBar: SafeArea(
bottomNavigationBar: orderGoodsInfo == null
? null
: SafeArea(
minimum: const EdgeInsets.all(10),
child: Container(
height: 50.0,
height: 60.0,
color: Colors.white,
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
child: buildBottomButtons(),
@ -627,4 +679,20 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
),
);
}
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)),
],
),
);
}
}

View File

@ -3,7 +3,9 @@ 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';
@ -17,19 +19,37 @@ class Seller extends StatefulWidget {
class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
GlobalKey<ScaffoldState> scaffoldKey = GlobalKey();
//
int pageNum = 1;
// - Tab单独存储数据
final int pageSize = 10;
bool isLoadingMore = false;
bool isRefreshing = false;
List<Map<String, dynamic>> pageOrderList = [];
// Tab单独存储状态
List<Map<String, dynamic>> _allOrders = [];
List<Map<String, dynamic>> _pendingPaymentOrders = [];
List<Map<String, dynamic>> _pendingVerificationOrders = [];
List<Map<String, dynamic>> _completedOrders = [];
List<Map<String, dynamic>> _closedOrders = [];
List<Map<String, dynamic>> _refundingOrders = [];
List<Map<String, dynamic>> _refundedOrders = [];
List<Map<String, dynamic>> _cancelledOrders = [];
// Tab的分页状态
Map<int, int> _pageNums = {};
Map<int, int> _totalCounts = {};
Map<int, bool> _hasMoreData = {};
Map<int, bool> _isLoading = {};
// 0->1->2->3->4->退5->退 6->
List tabList = [
{'id': 0, 'name': "全部"}, // 0
{'id': 4, 'name': "已退款", 'badge': 1}, // 4退
{'id': 2, 'name': "待核销", 'badge': 1}, // 2
{'id': 3, 'name': "已完成"}, // 3
{'id': 5, 'name': "取消"} // 5
{'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();
@ -38,6 +58,14 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
@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切换事件
@ -55,89 +83,207 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
super.dispose();
}
// Tab的订单列表
List<Map<String, dynamic>> _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<Map<String, dynamic>> 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() {
if (scrollController.position.pixels == scrollController.position.maxScrollExtent && !isLoadingMore) {
final currentIndex = tabController.index;
if (scrollController.position.pixels == scrollController.position.maxScrollExtent &&
!_isLoading[currentIndex]! &&
_hasMoreData[currentIndex]!) {
getOrderList(true);
}
}
// Tab切换监听
void _tabChanged() {
if (tabController.indexIsChanging) {
// tab时重新加载数据
if (tabController.index != tabController.previousIndex) {
// Tab没有数据
final currentOrders = _getCurrentOrderList();
if (currentOrders.isEmpty) {
getOrderList(false);
}
}
}
//
void getOrderList(bool loadMore) async {
if (isLoadingMore || isRefreshing) return;
final currentIndex = tabController.index;
final currentTab = tabList[currentIndex];
if (_isLoading[currentIndex]! || isRefreshing) return;
setState(() {
if (!loadMore) {
pageNum = 1; //
_pageNums[currentIndex] = 1;
isRefreshing = true;
pageOrderList = [];
} else {
isLoadingMore = true;
_isLoading[currentIndex] = true;
}
});
try {
final currentTab = tabList[tabController.index];
final status = currentTab['id'];
final res = await Http.post(ShopApi.myOrderList, data: {
'current': pageNum, //
'current': _pageNums[currentIndex], //
'size': pageSize,
// 'orderStatus': status == 0 ? '' : status.toString(), // 0
'status': status == '' ? '' : status.toString(),
});
if (res['code'] == 200 && res['data'] != null) {
final data = res['data'];
final List<Map<String, dynamic>> newOrders = List<Map<String, dynamic>>.from(data['records'] ?? []);
final int total = data['total'] ?? 0;
final int currentPage = data['current'] ?? 1;
final int pages = data['pages'] ?? 1;
debugPrint(data.toString(), wrapWidth: 1024);
// Tab的数据
_setCurrentOrderList(newOrders, loadMore);
// - 使total总数判断
setState(() {
if (loadMore) {
pageOrderList.addAll(newOrders);
} else {
pageOrderList = newOrders;
}
//
_totalCounts[currentIndex] = total;
//
if (newOrders.isNotEmpty && currentPage < pages) {
pageNum = currentPage + 1; //
isLoadingMore = true;
} else {
isLoadingMore = false; //
//
final currentOrderCount = _getCurrentOrderList().length;
_hasMoreData[currentIndex] = currentOrderCount < total;
//
if (_hasMoreData[currentIndex]!) {
_pageNums[currentIndex] = _pageNums[currentIndex]! + 1;
}
});
}
} catch (e) {
print('获取订单列表失败: $e');
setState(() {
isLoadingMore = false;
_hasMoreData[currentIndex] = false;
});
} finally {
setState(() {
isRefreshing = false;
_isLoading[currentIndex] = false;
});
}
}
//
void _refreshData() {
final currentIndex = tabController.index;
setState(() {
pageNum = 1;
isLoadingMore = false;
_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<String, dynamic> order) {
return GestureDetector(
@ -170,7 +316,7 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
width: 25.0,
),
),
Text(order['shopName'] ?? '商家名称'),
Text(order['items'][0]['tenantName'] ?? '商家名称'),
Icon(
Icons.arrow_forward_ios_rounded,
color: Colors.grey,
@ -198,9 +344,9 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
color: Colors.grey[200],
borderRadius: BorderRadius.circular(4.0),
),
child: item['image'] != null && item['image'].isNotEmpty
child: order['items'][0]['pic'] != null && order['items'][0]['pic'].isNotEmpty
? Image.network(
item['image'],
order['items'][0]['pic'],
width: 80.0,
height: 80.0,
fit: BoxFit.cover,
@ -226,7 +372,7 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
Row(
children: [
Text(
'¥${item['price'] ?? '0'}',
'¥${item['salePrice'] ?? '0'}',
style: TextStyle(color: Colors.red, fontSize: 16),
),
Spacer(),
@ -254,7 +400,7 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
Spacer(),
Text.rich(
TextSpan(children: [
TextSpan(text: '实付款: '),
TextSpan(text: _getPaymentText(order['status'])), //
TextSpan(
text: '¥${order['totalAmount'] ?? '0'}',
style: TextStyle(color: Colors.red, fontSize: 16),
@ -266,7 +412,7 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
),
SizedBox(height: 10),
//
_buildActionButtons(order['status']),
_buildActionButtons(order),
],
),
),
@ -282,15 +428,19 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
int statusCode = status is String ? int.tryParse(status) ?? 0 : (status is int ? status : 0);
switch (statusCode) {
case 1:
case 0:
return '待付款';
case 2:
case 1:
return '待核销';
case 3:
case 2:
return '已完成';
case 3:
return '已关闭';
case 4:
return '已退款';
return '退款';
case 5:
return '已退款';
case 6:
return '已取消';
default:
return '未知状态';
@ -302,39 +452,44 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
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.orange;
case 2:
return Colors.blue;
case 3:
case 2:
return Colors.green;
case 4:
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 status) {
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 1: //
case 0: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () => _cancelOrder(),
onPressed: () => _cancelOrder(orderId),
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
child: Text('取消订单'),
),
SizedBox(width: 10),
ElevatedButton(
onPressed: () => _payOrder(),
onPressed: () => _payOrder(orderId),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xff07c160)),
foregroundColor: WidgetStateProperty.all(Colors.white),
@ -343,30 +498,13 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
),
],
);
case 2: //
case 1: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () => _contactCustomerService(),
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xFFFCBE13)),
foregroundColor: WidgetStateProperty.all(Colors.white),
),
child: Text('联系客服'),
),
],
);
case 3: //
case 2: //
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
ElevatedButton(
onPressed: () => _deleteOrder(),
style: ButtonStyle(backgroundColor: WidgetStateProperty.all(Colors.white)),
child: Text('删除订单'),
),
],
);
default:
return SizedBox.shrink();
@ -374,20 +512,64 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
}
//
void _cancelOrder() {
//
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}');
}
}
void _payOrder() {
//
// tab
void _refreshAllRelatedTabs() {
// tab索引(0)(1)(7)
List<int> tabsToRefresh = [0, 1, 7];
for (int tabIndex in tabsToRefresh) {
_resetTabData(tabIndex);
// tab
if (tabController.index == tabIndex) {
getOrderList(false);
}
}
}
void _contactCustomerService() {
//
void _payOrder(_orderId) {
// pages/index/index
Wxsdk.openMiniApp(orderId: _orderId);
}
void _deleteOrder() {
//
// 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
@ -398,34 +580,38 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
appBar: AppBar(
titleSpacing: 1.0,
title: Text(
'商家订单',
'我的订单',
style: TextStyle(fontSize: 18),
),
bottom: PreferredSize(
preferredSize: Size.fromHeight(45.0),
child: Row(children: [
Expanded(
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,
height: 45.0,
child: Badge.count(
backgroundColor: Colors.red,
offset: Offset(14, -4),
count: item['badge'] ?? 0,
isLabelVisible: item['badge'] != null ? true : false,
isLabelVisible: item['badge'] != null && item['badge'] > 0,
child: Text(
item['name'],
style: TextStyle(fontSize: 16),
overflow: TextOverflow.ellipsis,
softWrap: false,
),
),
))
.toList(),
isScrollable: false,
overlayColor: WidgetStateProperty.all(Colors.transparent),
unselectedLabelColor: Colors.black87,
labelColor: Color(0xFFFF5000),
@ -433,16 +619,12 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
borderRadius: BorderRadius.circular(10.0),
borderSide: BorderSide(color: Color(0xFFFF5000), width: 2.0),
),
indicatorSize: TabBarIndicatorSize.tab,
indicatorSize: TabBarIndicatorSize.label,
unselectedLabelStyle: TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei'),
labelStyle: TextStyle(fontSize: 18.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w700),
labelStyle: TextStyle(fontSize: 16.0, fontFamily: 'Microsoft YaHei', fontWeight: FontWeight.w700),
dividerHeight: 0,
padding: EdgeInsets.symmetric(horizontal: 10.0),
labelPadding: EdgeInsets.symmetric(horizontal: 10.0),
indicatorPadding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 5.0),
),
),
]),
),
),
body: TabBarView(
@ -456,19 +638,27 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
child: Container(
color: Colors.grey[50],
child: pageOrderList.isEmpty && !isRefreshing
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: pageOrderList.length + (isLoadingMore ? 1 : 0),
itemBuilder: (context, index) {
if (index == pageOrderList.length) {
return _buildLoadMoreIndicator();
itemCount: currentOrders.length + (hasMoreData ? 1 : 0),
itemBuilder: (context, itemIndex) {
if (itemIndex == currentOrders.length) {
return _buildLoadMoreIndicator(isLoading);
}
return _buildOrderItem(pageOrderList[index]);
return _buildOrderItem(currentOrders[itemIndex]);
},
);
}
),
),
),
@ -478,12 +668,27 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
);
}
//
List<Map<String, dynamic>> _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() {
Widget _buildLoadMoreIndicator(bool isLoading) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 15.0),
child: Center(
child: isLoadingMore
child: isLoading
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
@ -503,7 +708,7 @@ class _SellerState extends State<Seller> with SingleTickerProviderStateMixin {
Widget emptyTip() {
return Container(
width: double.infinity, //
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [