核销联调
This commit is contained in:
parent
c6c6acf9dc
commit
09f0048b67
@ -39,4 +39,9 @@ class ShopApi {
|
|||||||
// 商家营收分页
|
// 商家营收分页
|
||||||
static const String revenueList= '/app/merchant/account/bill/page';
|
static const String revenueList= '/app/merchant/account/bill/page';
|
||||||
|
|
||||||
|
// 根据核销码查询详情
|
||||||
|
static const String getWriteOffDetail= '/app/merchant/order/scan';
|
||||||
|
|
||||||
|
// 确认核销
|
||||||
|
static const String confirmWriteOff= '/app/merchant/order/verify';
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ import 'package:loopin/components/scan_util.dart';
|
|||||||
import 'package:loopin/models/conversation_type.dart';
|
import 'package:loopin/models/conversation_type.dart';
|
||||||
import 'package:loopin/models/conversation_view_model.dart';
|
import 'package:loopin/models/conversation_view_model.dart';
|
||||||
import 'package:loopin/utils/index.dart';
|
import 'package:loopin/utils/index.dart';
|
||||||
|
import 'package:loopin/utils/scan_code_type.dart'; // 导入外部枚举
|
||||||
import 'package:loopin/utils/parse_message_summary.dart';
|
import 'package:loopin/utils/parse_message_summary.dart';
|
||||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||||
|
|
||||||
@ -51,7 +52,55 @@ class ChatPageState extends State<ChatPage> {
|
|||||||
await Future.delayed(Duration(seconds: 1));
|
await Future.delayed(Duration(seconds: 1));
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
// 处理扫码结果
|
||||||
|
void handleScanResult(String code) {
|
||||||
|
print('扫码结果11111111111111111111111:$code');
|
||||||
|
|
||||||
|
// 使用外部枚举的方法检查扫码类型
|
||||||
|
final scanType = ScanCodeType.fromCode(code);
|
||||||
|
if (scanType != null) {
|
||||||
|
final value = code.substring(scanType.prefix.length + 1); // 获取后缀值
|
||||||
|
_processScanCode(scanType, value);
|
||||||
|
} else {
|
||||||
|
// 未知类型的码
|
||||||
|
Get.snackbar('未知的二维码类型', '无法识别此二维码: $code');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理不同类型的扫码结果
|
||||||
|
void _processScanCode(ScanCodeType type, String value) {
|
||||||
|
switch (type) {
|
||||||
|
case ScanCodeType.verification:
|
||||||
|
_handleVerificationCode(value);
|
||||||
|
break;
|
||||||
|
case ScanCodeType.friend:
|
||||||
|
_handleFriendCode(value);
|
||||||
|
break;
|
||||||
|
case ScanCodeType.promotion:
|
||||||
|
_handlePromotionCode(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理核销码
|
||||||
|
void _handleVerificationCode (String value) async {
|
||||||
|
print('处理核销码: $value');
|
||||||
|
// 带着核销码,跳转到商家的商品详情页面,引导商家去手动点击核销按钮
|
||||||
|
Get.toNamed('/sellerOrder/detail', arguments: {'writeOffCodeId':value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理好友码
|
||||||
|
void _handleFriendCode(String value) {
|
||||||
|
print('处理好友码: $value');
|
||||||
|
// 模仿抖音,去个人页面手动点击关注
|
||||||
|
Get.toNamed('/vloger', arguments: {'memberId':value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理推广码
|
||||||
|
void _handlePromotionCode(String value) {
|
||||||
|
print('处理推广码: $value');
|
||||||
|
Get.toNamed('/vloger', arguments: {'memberId':value});
|
||||||
|
}
|
||||||
// 长按菜单
|
// 长按菜单
|
||||||
void showContextMenu(BuildContext context, ConversationViewModel item) {
|
void showContextMenu(BuildContext context, ConversationViewModel item) {
|
||||||
bool isLeft = posDX > MediaQuery.of(context).size.width / 2 ? false : true;
|
bool isLeft = posDX > MediaQuery.of(context).size.width / 2 ? false : true;
|
||||||
@ -240,11 +289,7 @@ class ChatPageState extends State<ChatPage> {
|
|||||||
break;
|
break;
|
||||||
case 'scan':
|
case 'scan':
|
||||||
logger.w('点击了扫一扫');
|
logger.w('点击了扫一扫');
|
||||||
ScanUtil.openScanner(onResult: (code) {
|
ScanUtil.openScanner(onResult: handleScanResult);
|
||||||
logger.w('扫码结果:$code');
|
|
||||||
Get.snackbar('扫码成功', code);
|
|
||||||
// 执行业务逻辑
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,16 +4,19 @@ library;
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
|
import 'package:loopin/service/http.dart';
|
||||||
import 'package:loopin/IM/controller/chat_controller.dart';
|
import 'package:loopin/IM/controller/chat_controller.dart';
|
||||||
import 'package:loopin/IM/global_badge.dart';
|
import 'package:loopin/IM/global_badge.dart';
|
||||||
import 'package:loopin/IM/im_service.dart';
|
import 'package:loopin/IM/im_service.dart';
|
||||||
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
import 'package:loopin/behavior/custom_scroll_behavior.dart';
|
||||||
|
import 'package:loopin/api/shop_api.dart';
|
||||||
import 'package:loopin/components/network_or_asset_image.dart';
|
import 'package:loopin/components/network_or_asset_image.dart';
|
||||||
import 'package:loopin/components/scan_util.dart';
|
import 'package:loopin/components/scan_util.dart';
|
||||||
import 'package:loopin/models/conversation_type.dart';
|
import 'package:loopin/models/conversation_type.dart';
|
||||||
import 'package:loopin/models/conversation_view_model.dart';
|
import 'package:loopin/models/conversation_view_model.dart';
|
||||||
import 'package:loopin/styles/index.dart';
|
import 'package:loopin/styles/index.dart';
|
||||||
import 'package:loopin/utils/parse_message_summary.dart';
|
import 'package:loopin/utils/parse_message_summary.dart';
|
||||||
|
import 'package:loopin/utils/scan_code_type.dart'; // 导入外部枚举
|
||||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||||
|
|
||||||
// systemNotify, // 系统->通知
|
// systemNotify, // 系统->通知
|
||||||
@ -30,7 +33,7 @@ class System extends StatefulWidget {
|
|||||||
|
|
||||||
class SystemState extends State<System> {
|
class SystemState extends State<System> {
|
||||||
late final ChatController controller;
|
late final ChatController controller;
|
||||||
|
dynamic writeOffInfo;
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -121,6 +124,56 @@ class SystemState extends State<System> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 处理扫码结果
|
||||||
|
void handleScanResult(String code) {
|
||||||
|
print('扫码结果:$code');
|
||||||
|
|
||||||
|
// 使用外部枚举的方法检查扫码类型
|
||||||
|
final scanType = ScanCodeType.fromCode(code);
|
||||||
|
if (scanType != null) {
|
||||||
|
final value = code.substring(scanType.prefix.length + 1); // 获取后缀值
|
||||||
|
_processScanCode(scanType, value);
|
||||||
|
} else {
|
||||||
|
// 未知类型的码
|
||||||
|
Get.snackbar('未知的二维码类型', '无法识别此二维码: $code');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理不同类型的扫码结果
|
||||||
|
void _processScanCode(ScanCodeType type, String value) {
|
||||||
|
switch (type) {
|
||||||
|
case ScanCodeType.verification:
|
||||||
|
_handleVerificationCode(value);
|
||||||
|
break;
|
||||||
|
case ScanCodeType.friend:
|
||||||
|
_handleFriendCode(value);
|
||||||
|
break;
|
||||||
|
case ScanCodeType.promotion:
|
||||||
|
_handlePromotionCode(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理核销码
|
||||||
|
void _handleVerificationCode (String value) async {
|
||||||
|
print('处理核销码: $value');
|
||||||
|
// 带着核销码,跳转到商家的商品详情页面,引导商家去手动点击核销按钮
|
||||||
|
Get.toNamed('/sellerOrder/detail', arguments: {'writeOffCodeId':value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理好友码
|
||||||
|
void _handleFriendCode(String value) {
|
||||||
|
print('处理好友码: $value');
|
||||||
|
// 模仿抖音,去个人页面手动点击关注
|
||||||
|
Get.toNamed('/vloger', arguments: {'memberId':value});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理推广码
|
||||||
|
void _handlePromotionCode(String value) {
|
||||||
|
print('处理推广码: $value');
|
||||||
|
Get.toNamed('/vloger', arguments: {'memberId':value});
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
@ -242,11 +295,7 @@ class SystemState extends State<System> {
|
|||||||
break;
|
break;
|
||||||
case 'scan':
|
case 'scan':
|
||||||
print('点击了扫一扫');
|
print('点击了扫一扫');
|
||||||
ScanUtil.openScanner(onResult: (code) {
|
ScanUtil.openScanner(onResult: handleScanResult);
|
||||||
print('扫码结果:$code');
|
|
||||||
Get.snackbar('扫码成功', code);
|
|
||||||
// 在这里继续你的业务逻辑,比如跳转页面、请求接口等
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -441,4 +490,4 @@ class SystemState extends State<System> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -78,6 +78,7 @@ class MyPageState extends State<Vloger> with SingleTickerProviderStateMixin {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
args = Get.arguments ?? {};
|
args = Get.arguments ?? {};
|
||||||
|
print('argsssssssssssssssssssssss${args}');
|
||||||
itemsParams = PageParams();
|
itemsParams = PageParams();
|
||||||
favoriteParams = PageParams();
|
favoriteParams = PageParams();
|
||||||
selfInfo();
|
selfInfo();
|
||||||
|
@ -4,9 +4,11 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:get/get.dart';
|
import 'package:get/get.dart';
|
||||||
import 'package:loopin/service/http.dart';
|
import 'package:loopin/service/http.dart';
|
||||||
import 'package:loopin/api/shop_api.dart';
|
import 'package:loopin/api/shop_api.dart';
|
||||||
|
import 'package:loopin/components/my_toast.dart';
|
||||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||||
import 'package:timer_count_down/timer_count_down.dart';
|
import 'package:timer_count_down/timer_count_down.dart';
|
||||||
import 'package:loopin/utils/wxsdk.dart';
|
import 'package:loopin/utils/wxsdk.dart';
|
||||||
|
import 'package:qr_flutter/qr_flutter.dart';
|
||||||
import '../../behavior/custom_scroll_behavior.dart';
|
import '../../behavior/custom_scroll_behavior.dart';
|
||||||
import '../../utils/lifecycle_handler.dart';
|
import '../../utils/lifecycle_handler.dart';
|
||||||
|
|
||||||
@ -18,16 +20,17 @@ class OrderDetail extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStateMixin {
|
class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStateMixin {
|
||||||
late String _orderId;
|
final String _orderId = Get.arguments['orderId'] ?? '';
|
||||||
dynamic orderGoodsInfo;
|
dynamic orderGoodsInfo;
|
||||||
int _initialSeconds = 30 * 60; // 存储初始秒数
|
int _initialSeconds = 30 * 60; // 存储初始秒数
|
||||||
bool _countdownFinished = false; // 新增标志位,用于跟踪倒计时是否结束
|
bool _countdownFinished = false; // 新增标志位,用于跟踪倒计时是否结束
|
||||||
bool _isLoading = true; // 添加加载状态
|
bool _isLoading = true; // 添加加载状态
|
||||||
|
bool _showQrCodeDialog = false;
|
||||||
|
String _qrCodeUrl = '';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_orderId = Get.arguments['orderId'] ?? '';
|
|
||||||
getOrderDetail(orderId: _orderId);
|
getOrderDetail(orderId: _orderId);
|
||||||
LifecycleHandler.onAppResumed = _onAppResumed;
|
LifecycleHandler.onAppResumed = _onAppResumed;
|
||||||
}
|
}
|
||||||
@ -61,7 +64,7 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId');
|
final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId');
|
||||||
debugPrint('订单详情-------------->${res['data']}');
|
debugPrint(res['data'].toString(), wrapWidth: 600);
|
||||||
setState(() {
|
setState(() {
|
||||||
orderGoodsInfo = res['data'];
|
orderGoodsInfo = res['data'];
|
||||||
_isLoading = false;
|
_isLoading = false;
|
||||||
@ -84,6 +87,41 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 核销
|
||||||
|
void _writeOffQrCode(verificationCodes) async {
|
||||||
|
if (verificationCodes != null && verificationCodes.isNotEmpty) {
|
||||||
|
// 过滤可用的核销码(status为0)
|
||||||
|
List<dynamic> newVerifyList = verificationCodes.where((item) => item['status'] == 0).toList();
|
||||||
|
|
||||||
|
if (newVerifyList.isNotEmpty) {
|
||||||
|
setState(() {
|
||||||
|
_showQrCodeDialog = true;
|
||||||
|
_qrCodeUrl = newVerifyList[0]['code'] ?? '';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
MyToast().tip(
|
||||||
|
title: '暂无可用的核销码',
|
||||||
|
position: 'center',
|
||||||
|
type: 'error',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
MyToast().tip(
|
||||||
|
title: '暂无可用的核销码',
|
||||||
|
position: 'center',
|
||||||
|
type: 'error',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 关闭二维码弹框
|
||||||
|
void _closeQrCodeDialog() {
|
||||||
|
setState(() {
|
||||||
|
_showQrCodeDialog = false;
|
||||||
|
_qrCodeUrl = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 显示支付结果弹框
|
// 显示支付结果弹框
|
||||||
void _showPaymentResultDialog() {
|
void _showPaymentResultDialog() {
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -314,7 +352,7 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
if (orderGoodsInfo == null) return SizedBox.shrink();
|
if (orderGoodsInfo == null) return SizedBox.shrink();
|
||||||
|
|
||||||
int orderStatus = orderGoodsInfo?['status'] ?? 0;
|
int orderStatus = orderGoodsInfo?['status'] ?? 0;
|
||||||
|
List verificationCodes = orderGoodsInfo?['verificationCodes'] ?? [];
|
||||||
switch (orderStatus) {
|
switch (orderStatus) {
|
||||||
case 0: // 待付款
|
case 0: // 待付款
|
||||||
return Row(
|
return Row(
|
||||||
@ -353,12 +391,12 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 10.0),
|
const SizedBox(width: 10.0),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {},
|
onPressed: () => _writeOffQrCode(verificationCodes),
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
|
backgroundColor: WidgetStateProperty.all(Colors.green),
|
||||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||||
),
|
),
|
||||||
child: const Text('待核销'),
|
child: const Text('核销码'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -465,232 +503,118 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
Widget _buildQrCodeDialog() {
|
||||||
Widget build(BuildContext context) {
|
return GestureDetector(
|
||||||
final productInfo = _getFirstProductInfo();
|
onTap: _closeQrCodeDialog,
|
||||||
|
child: Container(
|
||||||
return Scaffold(
|
color: Colors.black54,
|
||||||
backgroundColor: Colors.grey[50],
|
child: Center(
|
||||||
appBar: AppBar(
|
child: GestureDetector(
|
||||||
backgroundColor: Color(0xFFFF5000),
|
onTap: () {}, // 阻止点击内容区域关闭
|
||||||
foregroundColor: Colors.white,
|
child: Container(
|
||||||
title: Text('订单详情'),
|
width: MediaQuery.of(context).size.width * 0.8,
|
||||||
titleSpacing: 1.0,
|
padding: EdgeInsets.all(20),
|
||||||
),
|
decoration: BoxDecoration(
|
||||||
body: _isLoading
|
color: Colors.white,
|
||||||
? Center(child: CircularProgressIndicator())
|
borderRadius: BorderRadius.circular(15),
|
||||||
: orderGoodsInfo == null
|
boxShadow: [
|
||||||
? emptyTip()
|
BoxShadow(
|
||||||
: ScrollConfiguration(
|
color: Colors.black26,
|
||||||
behavior: CustomScrollBehavior().copyWith(scrollbars: false),
|
blurRadius: 10,
|
||||||
child: ListView(
|
offset: Offset(0, 4),
|
||||||
physics: BouncingScrollPhysics(),
|
),
|
||||||
padding: EdgeInsets.all(10.0),
|
],
|
||||||
children: [
|
),
|
||||||
if (orderGoodsInfo?['status'] == 0)
|
child: Column(
|
||||||
Container(
|
mainAxisSize: MainAxisSize.min,
|
||||||
padding: EdgeInsets.all(12.0),
|
children: [
|
||||||
margin: EdgeInsets.only(bottom: 10.0),
|
Text(
|
||||||
|
'核销二维码',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: Colors.black87,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 20),
|
||||||
|
_qrCodeUrl.isNotEmpty
|
||||||
|
? Container(
|
||||||
|
padding: EdgeInsets.all(15),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(15.0),
|
border: Border.all(color: Colors.grey[300]!),
|
||||||
boxShadow: [
|
borderRadius: BorderRadius.circular(8),
|
||||||
BoxShadow(
|
|
||||||
color: Colors.black.withAlpha(10),
|
|
||||||
offset: Offset(0.0, 1.0),
|
|
||||||
blurRadius: 1.0,
|
|
||||||
spreadRadius: 0.0,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
child: Column(
|
child: QrImageView(
|
||||||
children: [
|
data: _qrCodeUrl,
|
||||||
Row(
|
version: QrVersions.auto,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
size: 180,
|
||||||
children: [
|
foregroundColor: Colors.black,
|
||||||
Icon(
|
backgroundColor: Colors.white,
|
||||||
Icons.info,
|
errorStateBuilder: (cxt, err) {
|
||||||
size: 16.0,
|
return Container(
|
||||||
color: Colors.orange,
|
width: 180,
|
||||||
),
|
height: 180,
|
||||||
SizedBox(width: 4),
|
color: Colors.grey[200],
|
||||||
Text(
|
child: Center(
|
||||||
getOrderStatusText(orderGoodsInfo?['status']),
|
|
||||||
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']),
|
|
||||||
style: TextStyle(
|
|
||||||
color: getOrderStatusColor(orderGoodsInfo?['status']),
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
SizedBox(height: 10),
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_buildProductImage(),
|
|
||||||
SizedBox(width: 10.0),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
productInfo['productName']?.toString() ?? '商品名称未知',
|
|
||||||
maxLines: 2,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
style: TextStyle(fontSize: 14),
|
|
||||||
),
|
|
||||||
SizedBox(height: 8),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'¥${productInfo['salePrice']?.toString() ?? '0.00'}',
|
|
||||||
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
Spacer(),
|
|
||||||
Text(
|
|
||||||
'x${productInfo['buyNum']?.toString() ?? '1'}',
|
|
||||||
style: TextStyle(color: Colors.grey),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// 订单信息
|
|
||||||
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(
|
child: Icon(
|
||||||
Icons.copy,
|
Icons.error_outline,
|
||||||
color: Colors.grey,
|
color: Colors.grey[400],
|
||||||
size: 18.0,
|
size: 40,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
),
|
||||||
await Clipboard.setData(ClipboardData(text: _orderId));
|
);
|
||||||
MyDialog.toast('订单已复制到剪切板', icon: Icon(Icons.check_circle));
|
},
|
||||||
},
|
),
|
||||||
)
|
)
|
||||||
],
|
: Container(
|
||||||
|
width: 180,
|
||||||
|
height: 180,
|
||||||
|
color: Colors.grey[200],
|
||||||
|
child: Center(
|
||||||
|
child: CircularProgressIndicator(
|
||||||
|
color: Color(0xff07c160),
|
||||||
),
|
),
|
||||||
SizedBox(height: 10),
|
),
|
||||||
Column(
|
|
||||||
children: [
|
|
||||||
_buildOrderInfoRow('订单号', orderGoodsInfo?['orderId'] ?? ''),
|
|
||||||
_buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime'] ?? ''),
|
|
||||||
_buildOrderInfoRow('购买数量', (productInfo['buyNum'] ?? 0).toString()),
|
|
||||||
_buildOrderInfoRow('订单金额', '¥${orderGoodsInfo?['totalAmount'] ?? '0.00'}'),
|
|
||||||
_buildOrderInfoRow('实付金额', '¥${orderGoodsInfo?['payAmount'] ?? '0.00'}'),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 15),
|
||||||
],
|
Text(
|
||||||
|
'订单号: $_orderId',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.grey[600],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
),
|
SizedBox(height: 10),
|
||||||
// 底部固定按钮
|
Text(
|
||||||
bottomNavigationBar: orderGoodsInfo == null
|
'核销码: $_qrCodeUrl',
|
||||||
? null
|
style: TextStyle(
|
||||||
: SafeArea(
|
fontSize: 12,
|
||||||
minimum: const EdgeInsets.all(10),
|
color: Colors.grey[500],
|
||||||
child: Container(
|
fontFamily: 'monospace',
|
||||||
height: 60.0,
|
),
|
||||||
color: Colors.white,
|
textAlign: TextAlign.center,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
|
),
|
||||||
child: buildBottomButtons(),
|
SizedBox(height: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _closeQrCodeDialog,
|
||||||
|
style: ElevatedButton.styleFrom(
|
||||||
|
backgroundColor: Color(0xff07c160),
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
minimumSize: Size(120, 40),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Text('关闭'),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -709,4 +633,240 @@ class _OrderDetailState extends State<OrderDetail> with SingleTickerProviderStat
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final productInfo = _getFirstProductInfo();
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.grey[50],
|
||||||
|
appBar: AppBar(
|
||||||
|
backgroundColor: Color(0xFFFF5000),
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
title: Text('订单详情'),
|
||||||
|
titleSpacing: 1.0,
|
||||||
|
),
|
||||||
|
body: Stack(
|
||||||
|
children: [
|
||||||
|
// 主要内容
|
||||||
|
_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)
|
||||||
|
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']),
|
||||||
|
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']),
|
||||||
|
style: TextStyle(
|
||||||
|
color: getOrderStatusColor(orderGoodsInfo?['status']),
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
_buildProductImage(),
|
||||||
|
SizedBox(width: 10.0),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
productInfo['productName']?.toString() ?? '商品名称未知',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'¥${productInfo['salePrice']?.toString() ?? '0.00'}',
|
||||||
|
style: TextStyle(color: Colors.red, fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
Spacer(),
|
||||||
|
Text(
|
||||||
|
'x${productInfo['buyNum']?.toString() ?? '1'}',
|
||||||
|
style: TextStyle(color: Colors.grey),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// 订单信息
|
||||||
|
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'] ?? ''),
|
||||||
|
_buildOrderInfoRow('下单时间', orderGoodsInfo?['createTime'] ?? ''),
|
||||||
|
_buildOrderInfoRow('购买数量', (productInfo['buyNum'] ?? 0).toString()),
|
||||||
|
_buildOrderInfoRow('订单金额', '¥${orderGoodsInfo?['totalAmount'] ?? '0.00'}'),
|
||||||
|
_buildOrderInfoRow('实付金额', '¥${orderGoodsInfo?['payAmount'] ?? '0.00'}'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
// 二维码对话框(条件渲染)
|
||||||
|
if (_showQrCodeDialog) _buildQrCodeDialog(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
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(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
@ -665,6 +665,7 @@ class _MyOrderState extends State<MyOrder> with SingleTickerProviderStateMixin {
|
|||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,10 +5,8 @@ import 'package:get/get.dart';
|
|||||||
import 'package:loopin/service/http.dart';
|
import 'package:loopin/service/http.dart';
|
||||||
import 'package:loopin/api/shop_api.dart';
|
import 'package:loopin/api/shop_api.dart';
|
||||||
import 'package:shirne_dialog/shirne_dialog.dart';
|
import 'package:shirne_dialog/shirne_dialog.dart';
|
||||||
import 'package:timer_count_down/timer_count_down.dart';
|
import 'package:loopin/components/my_toast.dart';
|
||||||
import 'package:loopin/utils/wxsdk.dart';
|
|
||||||
import '../../behavior/custom_scroll_behavior.dart';
|
import '../../behavior/custom_scroll_behavior.dart';
|
||||||
import '../../utils/lifecycle_handler.dart';
|
|
||||||
|
|
||||||
class SellerOrderDetail extends StatefulWidget {
|
class SellerOrderDetail extends StatefulWidget {
|
||||||
const SellerOrderDetail({super.key});
|
const SellerOrderDetail({super.key});
|
||||||
@ -18,49 +16,54 @@ class SellerOrderDetail extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTickerProviderStateMixin {
|
class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTickerProviderStateMixin {
|
||||||
late String _orderId;
|
late String ? _orderId;
|
||||||
|
late String ?_writeOffCodeId;
|
||||||
dynamic orderGoodsInfo;
|
dynamic orderGoodsInfo;
|
||||||
int _initialSeconds = 30 * 60; // 存储初始秒数
|
|
||||||
bool _countdownFinished = false; // 新增标志位,用于跟踪倒计时是否结束
|
|
||||||
bool _isLoading = true; // 添加加载状态
|
bool _isLoading = true; // 添加加载状态
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_orderId = Get.arguments['orderId'] ?? '';
|
_orderId = Get.arguments['orderId'] ?? ''; // 从商家订单列表进入此页面,此时带着订单id
|
||||||
getOrderDetail(orderId: _orderId);
|
_writeOffCodeId = Get.arguments['writeOffCodeId'] ?? ''; // 从扫码核销进入此页面,此时带着核销码
|
||||||
LifecycleHandler.onAppResumed = _onAppResumed;
|
if(_orderId != null){
|
||||||
|
getOrderDetailByOrderId(_orderId);
|
||||||
|
}else if(_writeOffCodeId != null){
|
||||||
|
getOrderDetailByWriteOffId(_writeOffCodeId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
LifecycleHandler.onAppResumed = null;
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
// 获取订单详情信息,根据订单id
|
||||||
void _onAppResumed() {
|
void getOrderDetailByOrderId(orderId) async {
|
||||||
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 {
|
try {
|
||||||
setState(() {
|
setState(() {
|
||||||
_isLoading = true;
|
_isLoading = true;
|
||||||
});
|
});
|
||||||
final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId');
|
final res = await Http.get('${ShopApi.goodsOrderDetail}/$orderId');
|
||||||
|
debugPrint(res['data'].toString(), wrapWidth: 600);
|
||||||
|
setState(() {
|
||||||
|
orderGoodsInfo = res['data'];
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = false;
|
||||||
|
});
|
||||||
|
MyDialog.toast('获取订单详情失败');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 获取订单详情信息,根据核销码
|
||||||
|
void getOrderDetailByWriteOffId(code) async {
|
||||||
|
try {
|
||||||
|
setState(() {
|
||||||
|
_isLoading = true;
|
||||||
|
});
|
||||||
|
final res = await Http.get('${ShopApi.getWriteOffDetail}?code=$code');
|
||||||
print('订单详情-------------->${res['data']}');
|
print('订单详情-------------->${res['data']}');
|
||||||
setState(() {
|
setState(() {
|
||||||
orderGoodsInfo = res['data'];
|
orderGoodsInfo = res['data'];
|
||||||
@ -74,123 +77,44 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 取消订单
|
// 确认核销订单
|
||||||
void _cancelOrder() async {
|
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?? '';
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
final res = await Http.post('${ShopApi.cancelGoodsOrder}/$_orderId');
|
final res = await Http.get('${ShopApi.confirmWriteOff}?code=$writeOffCode');
|
||||||
getOrderDetail(orderId: _orderId); // 刷新订单详情数据
|
debugPrint(res['data'].toString(), wrapWidth: 600);
|
||||||
} catch (e) {
|
MyToast().tip(
|
||||||
MyDialog.toast('取消订单失败');
|
title: '核销成功',
|
||||||
|
position: 'center',
|
||||||
|
type: 'error',
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 显示支付结果弹框
|
|
||||||
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) {
|
String getOrderStatusText(int status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
@ -383,32 +307,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
case 0: // 待付款
|
case 0: // 待付款
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
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: // 待核销
|
case 1: // 待核销
|
||||||
@ -417,12 +316,14 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
children: [
|
children: [
|
||||||
const SizedBox(width: 10.0),
|
const SizedBox(width: 10.0),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
_confirmVerifyCode();
|
||||||
|
},
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
|
backgroundColor: WidgetStateProperty.all(Color(0xFFFF5000)),
|
||||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
foregroundColor: WidgetStateProperty.all(Colors.white),
|
||||||
),
|
),
|
||||||
child: const Text('待核销'),
|
child: const Text('确认核销'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -430,81 +331,31 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
case 2: // 已完成
|
case 2: // 已完成
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
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: // 已关闭
|
case 3: // 已关闭
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
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: // 退款中
|
case 4: // 退款中
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
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: // 已退款
|
case 5: // 已退款
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
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: // 已取消
|
case 6: // 已取消
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [],
|
||||||
const SizedBox(width: 10.0),
|
|
||||||
ElevatedButton(
|
|
||||||
onPressed: () {},
|
|
||||||
style: ButtonStyle(
|
|
||||||
backgroundColor: WidgetStateProperty.all(Colors.grey),
|
|
||||||
foregroundColor: WidgetStateProperty.all(Colors.white),
|
|
||||||
),
|
|
||||||
child: const Text('已取消'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -549,7 +400,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
physics: BouncingScrollPhysics(),
|
physics: BouncingScrollPhysics(),
|
||||||
padding: EdgeInsets.all(10.0),
|
padding: EdgeInsets.all(10.0),
|
||||||
children: [
|
children: [
|
||||||
if (orderGoodsInfo?['status'] == 0) // 修正:应该是 status 而不是 orderStatus
|
if (orderGoodsInfo?['status'] == 0)
|
||||||
Container(
|
Container(
|
||||||
padding: EdgeInsets.all(12.0),
|
padding: EdgeInsets.all(12.0),
|
||||||
margin: EdgeInsets.only(bottom: 10.0),
|
margin: EdgeInsets.only(bottom: 10.0),
|
||||||
@ -581,41 +432,11 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
style: TextStyle(color: Colors.orange),
|
style: TextStyle(color: Colors.orange),
|
||||||
),
|
),
|
||||||
SizedBox(width: 4),
|
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),
|
SizedBox(height: 4),
|
||||||
Text(
|
|
||||||
_countdownFinished
|
|
||||||
? '订单已自动取消'
|
|
||||||
: '超过30分钟未支付,订单将自动取消',
|
|
||||||
style: TextStyle(color: Colors.grey, fontSize: 12.0),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -686,7 +507,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
size: 18.0,
|
size: 18.0,
|
||||||
),
|
),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
await Clipboard.setData(ClipboardData(text: _orderId));
|
await Clipboard.setData(ClipboardData(text: _orderId??''));
|
||||||
MyDialog.toast('订单已复制到剪切板', icon: Icon(Icons.check_circle));
|
MyDialog.toast('订单已复制到剪切板', icon: Icon(Icons.check_circle));
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -717,7 +538,7 @@ class _SellerOrderDetailState extends State<SellerOrderDetail> with SingleTicker
|
|||||||
height: 60.0,
|
height: 60.0,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
|
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 5.0),
|
||||||
child: buildBottomButtons(),
|
// child: buildBottomButtons(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1136,7 +1136,8 @@ class _AttentionModuleState extends State<AttentionModule> {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
player.pause();
|
player.pause();
|
||||||
// 跳转到 Vloger 页面并等待返回结果
|
// 跳转到 Vloger 页面并等待返回结果
|
||||||
final result = await Get.toNamed('/vloger', arguments: videoList[videoModuleController.videoPlayIndex.value]);
|
final vloggerId = videoList[videoModuleController.videoPlayIndex.value]['memberId'];
|
||||||
|
final result = await Get.toNamed('/vloger', arguments: {'memberId':vloggerId});
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
// 处理返回的参数
|
// 处理返回的参数
|
||||||
print('返回的数据: ${result['followStatus']}');
|
print('返回的数据: ${result['followStatus']}');
|
||||||
|
@ -1141,7 +1141,8 @@ class _FriendModuleState extends State<FriendModule> {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
player.pause();
|
player.pause();
|
||||||
// 跳转到 Vloger 页面并等待返回结果
|
// 跳转到 Vloger 页面并等待返回结果
|
||||||
final result = await Get.toNamed('/vloger', arguments: videoList[videoModuleController.videoPlayIndex.value]);
|
final vloggerId = videoList[videoModuleController.videoPlayIndex.value]['memberId'];
|
||||||
|
final result = await Get.toNamed('/vloger', arguments: {'memberId':vloggerId});
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
// 处理返回的参数
|
// 处理返回的参数
|
||||||
print('返回的数据: ${result['followStatus']}');
|
print('返回的数据: ${result['followStatus']}');
|
||||||
|
@ -1125,7 +1125,8 @@ class _RecommendModuleState extends State<RecommendModule> {
|
|||||||
onTap: () async {
|
onTap: () async {
|
||||||
player.pause();
|
player.pause();
|
||||||
// 跳转到 Vloger 页面并等待返回结果
|
// 跳转到 Vloger 页面并等待返回结果
|
||||||
final result = await Get.toNamed('/vloger', arguments: videoList[videoModuleController.videoPlayIndex.value]);
|
final vloggerId = videoList[videoModuleController.videoPlayIndex.value]['memberId'];
|
||||||
|
final result = await Get.toNamed('/vloger', arguments: {'memberId':vloggerId});
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
// 处理返回的参数
|
// 处理返回的参数
|
||||||
print('返回的数据: ${result['followStatus']}');
|
print('返回的数据: ${result['followStatus']}');
|
||||||
|
29
lib/utils/scan_code_type.dart
Normal file
29
lib/utils/scan_code_type.dart
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// 扫码 类型
|
||||||
|
enum ScanCodeType {
|
||||||
|
verification('hxm'), // 核销码
|
||||||
|
friend('hym'), // 好友码
|
||||||
|
promotion('tgm'); // 推广码
|
||||||
|
|
||||||
|
final String prefix;
|
||||||
|
const ScanCodeType(this.prefix);
|
||||||
|
|
||||||
|
// 根据前缀获取对应的枚举值
|
||||||
|
static ScanCodeType? fromPrefix(String prefix) {
|
||||||
|
for (var type in ScanCodeType.values) {
|
||||||
|
if (type.prefix == prefix) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 根据完整code获取对应的枚举值
|
||||||
|
static ScanCodeType? fromCode(String code) {
|
||||||
|
for (var type in ScanCodeType.values) {
|
||||||
|
if (code.startsWith('${type.prefix}-')) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
16
pubspec.lock
16
pubspec.lock
@ -1093,6 +1093,22 @@ packages:
|
|||||||
url: "https://pub.flutter-io.cn"
|
url: "https://pub.flutter-io.cn"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.5"
|
version: "6.1.5"
|
||||||
|
qr:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: qr
|
||||||
|
sha256: "5a1d2586170e172b8a8c8470bbbffd5eb0cd38a66c0d77155ea138d3af3a4445"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "3.0.2"
|
||||||
|
qr_flutter:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: qr_flutter
|
||||||
|
sha256: "5095f0fc6e3f71d08adef8feccc8cea4f12eec18a2e31c2e8d82cb6019f4b097"
|
||||||
|
url: "https://pub.flutter-io.cn"
|
||||||
|
source: hosted
|
||||||
|
version: "4.1.0"
|
||||||
record:
|
record:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
|
@ -42,6 +42,8 @@ dependencies:
|
|||||||
card_swiper: ^3.0.1
|
card_swiper: ^3.0.1
|
||||||
flutter_svg: ^2.0.16
|
flutter_svg: ^2.0.16
|
||||||
easy_refresh: ^3.4.0
|
easy_refresh: ^3.4.0
|
||||||
|
# 二维码
|
||||||
|
qr_flutter: ^4.1.0
|
||||||
# 腾讯IM
|
# 腾讯IM
|
||||||
tencent_cloud_chat_sdk: ^8.6.7019+2
|
tencent_cloud_chat_sdk: ^8.6.7019+2
|
||||||
# 离线推送
|
# 离线推送
|
||||||
|
Loading…
x
Reference in New Issue
Block a user