flutter/lib/pages/order/seller_detail.dart

572 lines
18 KiB
Dart
Raw Normal View History

2025-09-12 17:23:08 +08:00
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';
2025-09-13 16:14:27 +08:00
import 'package:loopin/components/my_toast.dart';
2025-09-12 17:23:08 +08:00
import '../../behavior/custom_scroll_behavior.dart';
class SellerOrderDetail extends StatefulWidget {
const SellerOrderDetail({super.key});
@override
State<SellerOrderDetail> createState() => _SellerOrderDetailState();
}
class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTickerProviderStateMixin {
2025-09-13 16:14:27 +08:00
late String ? _orderId;
late String ?_writeOffCodeId;
2025-09-12 17:23:08 +08:00
dynamic orderGoodsInfo;
bool _isLoading = true; // 添加加载状态
@override
void initState() {
super.initState();
2025-09-13 16:14:27 +08:00
_orderId = Get.arguments['orderId'] ?? ''; // 从商家订单列表进入此页面此时带着订单id
_writeOffCodeId = Get.arguments['writeOffCodeId'] ?? ''; // 从扫码核销进入此页面,此时带着核销码
if(_orderId != null){
getOrderDetailByOrderId(_orderId);
}else if(_writeOffCodeId != null){
getOrderDetailByWriteOffId(_writeOffCodeId);
}
2025-09-12 17:23:08 +08:00
}
@override
void dispose() {
super.dispose();
}
2025-09-13 16:14:27 +08:00
// 获取订单详情信息根据订单id
void getOrderDetailByOrderId(orderId) async {
2025-09-12 17:23:08 +08:00
try {
2025-09-13 16:14:27 +08:00
setState(() {
_isLoading = true;
});
final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId');
debugPrint(res['data'].toString(), wrapWidth: 600);
setState(() {
orderGoodsInfo = res['data'];
_isLoading = false;
});
2025-09-12 17:23:08 +08:00
} catch (e) {
2025-09-13 16:14:27 +08:00
setState(() {
_isLoading = false;
});
MyDialog.toast('获取订单详情失败');
2025-09-12 17:23:08 +08:00
}
}
2025-09-13 16:14:27 +08:00
// 获取订单详情信息,根据核销码
void getOrderDetailByWriteOffId(code) async {
2025-09-12 17:23:08 +08:00
try {
setState(() {
_isLoading = true;
});
2025-09-13 16:14:27 +08:00
final res = await Http.get('${ShopApi.getWriteOffDetail}?code=$code');
2025-09-12 17:23:08 +08:00
print('订单详情-------------->${res['data']}');
setState(() {
orderGoodsInfo = res['data'];
_isLoading = false;
});
} catch (e) {
setState(() {
_isLoading = false;
});
MyDialog.toast('获取订单详情失败');
}
}
2025-09-13 16:14:27 +08:00
// 确认核销订单
void _confirmVerifyCode () async {
late String writeOffCode;
if(_orderId != null){ // 商家可以直接从订单详情获取核销码,并过滤后进行核销
var verificationCodesList = orderGoodsInfo['verificationCodes'];
if (verificationCodesList != null && verificationCodesList.isNotEmpty) {
// 过滤可用的核销码status为0
List<dynamic> newVerifyList = verificationCodesList.where((item) => item['status'] == 0).toList();
if (newVerifyList.isNotEmpty) {
writeOffCode = newVerifyList[0]['code'] ?? '';
} else {
return MyToast().tip(
title: '暂无可用的核销码',
position: 'center',
type: 'error',
);
}
} else {
return MyToast().tip(
title: '暂无可用的核销码',
position: 'center',
type: 'error',
);
}
}else if(_writeOffCodeId != null){
writeOffCode = _writeOffCodeId?? '';
2025-09-12 17:23:08 +08:00
}
2025-09-13 16:14:27 +08:00
try {
final res = await Http.get('${ShopApi.confirmWriteOff}?code=$writeOffCode');
debugPrint(res['data'].toString(), wrapWidth: 600);
MyToast().tip(
title: '核销成功',
position: 'center',
type: 'error',
2025-09-12 17:23:08 +08:00
);
2025-09-13 16:14:27 +08:00
} catch (e) {
}
2025-09-12 17:23:08 +08:00
}
// 获取订单状态文本
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<dynamic> 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,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
case 1: // 待核销
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
const SizedBox(width: 10.0),
ElevatedButton(
2025-09-13 16:14:27 +08:00
onPressed: () {
_confirmVerifyCode();
},
2025-09-12 17:23:08 +08:00
style: ButtonStyle(
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
foregroundColor: WidgetStateProperty.all(Colors.white),
),
2025-09-13 16:14:27 +08:00
child: const Text('确认核销'),
2025-09-12 17:23:08 +08:00
),
],
);
case 2: // 已完成
return Row(
mainAxisAlignment: MainAxisAlignment.end,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
case 3: // 已关闭
return Row(
mainAxisAlignment: MainAxisAlignment.end,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
case 4: // 退款中
return Row(
mainAxisAlignment: MainAxisAlignment.end,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
case 5: // 已退款
return Row(
mainAxisAlignment: MainAxisAlignment.end,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
case 6: // 已取消
return Row(
mainAxisAlignment: MainAxisAlignment.end,
2025-09-13 16:14:27 +08:00
children: [],
2025-09-12 17:23:08 +08:00
);
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: [
2025-09-13 16:14:27 +08:00
if (orderGoodsInfo?['status'] == 0)
2025-09-12 17:23:08 +08:00
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),
2025-09-13 16:14:27 +08:00
2025-09-12 17:23:08 +08:00
],
),
SizedBox(height: 4),
],
),
),
// 商品信息
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 {
2025-09-13 16:14:27 +08:00
await Clipboard.setData(ClipboardData(text: _orderId??''));
2025-09-12 17:23:08 +08:00
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),
2025-09-13 16:14:27 +08:00
// child: buildBottomButtons(),
2025-09-12 17:23:08 +08:00
),
),
);
}
// 计算总购买数量
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)),
],
),
);
}
}