diff --git a/lib/common/values/constants.dart b/lib/common/values/constants.dart index a35825b..d6c0f43 100644 --- a/lib/common/values/constants.dart +++ b/lib/common/values/constants.dart @@ -10,9 +10,12 @@ class Constants { static const pwdEncKey = 'pigxpigxpigxpigx'; /// 服务 url 线上 - // static const apiUrl = 'https://stgl.pj.gov.cn/api'; + static const apiUrl = 'https://stgl.pj.gov.cn/api'; - static const apiUrl = 'http://192.168.101.196:9999'; + // static const apiUrl = 'http://192.168.101.196:9999'; + + /// h5 支付页面 + static const h5PayUrl = "https://stgl.pj.gov.cn/h5/#/pages/pay/scanPay"; /// 静态资源 url static const ossUrl = apiUrl; diff --git a/lib/common/widgets/app/app_qr_code_dialog.dart b/lib/common/widgets/app/app_qr_code_dialog.dart new file mode 100644 index 0000000..e520eca --- /dev/null +++ b/lib/common/widgets/app/app_qr_code_dialog.dart @@ -0,0 +1,171 @@ +import 'dart:async'; + +import 'package:ducafe_ui_core/ducafe_ui_core.dart'; +import 'package:flutter/material.dart'; +import 'package:forui/forui.dart'; +import 'package:get/get.dart'; +import 'package:pretty_qr_code/pretty_qr_code.dart'; + +Future showQrCodeDialog( + BuildContext context, { + required String qrData, + int countDownSeconds = 30, + required VoidCallback onFinished, +}) { + return showDialog( + context: context, + barrierDismissible: false, + builder: (BuildContext context) { + return AppQrCodeDialog( + qrData: qrData, + countDownSeconds: countDownSeconds, + onFinished: onFinished, + ); + }, + ); +} + +// 二维码弹窗 +class AppQrCodeDialog extends StatefulWidget { + const AppQrCodeDialog({ + super.key, + required this.qrData, + required this.countDownSeconds, + required this.onFinished, + }); + + final String qrData; + final int countDownSeconds; + final VoidCallback onFinished; + + @override + State createState() => _AppQrCodeDialogState(); +} + +class _AppQrCodeDialogState extends State { + // 当前的倒计时秒数 + late int _currentSeconds; + // 倒计时 + Timer? _countdownTimer; + // 倒计时是否运行中 + bool _isRunning = false; + + @override + void initState() { + super.initState(); + _currentSeconds = widget.countDownSeconds; + // 创建倒计时 + _createCountDown(); + } + + @override + void dispose() { + _destroyCountDown(); + super.dispose(); + } + + // 创建倒计时 + void _createCountDown() { + if (_isRunning) return; + _isRunning = true; + _countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) { + if (_currentSeconds <= 0) { + _countdownTimer?.cancel(); + _isRunning = false; + // 倒计时结束回调 + widget.onFinished.call(); + Navigator.of(context).pop(); + return; + } + setState(() { + _currentSeconds--; + }); + }); + } + + // 销毁倒计时 + void _destroyCountDown() { + _countdownTimer?.cancel(); + _countdownTimer = null; + } + + @override + Widget build(BuildContext context) { + final theme = FTheme.of(context); + final qrCode = QrCode( + 16, + QrErrorCorrectLevel.H, + )..addData(widget.qrData); + + // 宽高 + final dialogWidth = MediaQuery.of(context).size.width * 0.5; + final dialogHeight = MediaQuery.of(context).size.height * 0.7; + return FDialog( + title: Text( + "扫一扫支付", + style: theme.typography.xl3, + ).center().marginOnly(bottom: 20.h), + style: theme.dialogStyle.copyWith( + insetPadding: EdgeInsets.zero, + maxWidth: dialogWidth, + minWidth: dialogHeight, + horizontalStyle: theme.dialogStyle.horizontalStyle.copyWith( + padding: EdgeInsets.all(20.w), + ), + ), + body: [ + Text( + '请打开"浙政钉"或"诗画浦江"点击右上角扫一扫图标', + style: theme.typography.xl.copyWith( + height: 1, + ), + ), + Stack( + children: [ + PrettyQrView( + qrImage: QrImage(qrCode), + decoration: const PrettyQrDecoration(), + ), + Positioned( + left: 0, + top: 0, + right: 0, + bottom: 0, + child: [ + FIcon( + FAssets.icons.check, + size: theme.typography.xl4.fontSize, + color: Colors.white, + ) + .paddingAll(20.w) + .decorated( + color: Colors.greenAccent[200], + ) + .clipOval(), + Text( + "扫码成功", + style: theme.typography.xl3.copyWith( + color: Colors.greenAccent[200], + fontWeight: FontWeight.bold, + ), + ), + ] + .toColumn(mainAxisAlignment: MainAxisAlignment.center) + .center() + .decorated(color: Colors.black45) + .offstage(offstage: true), + ), + ], + ).marginSymmetric(horizontal: 100.w, vertical: 50.h), + Text( + '请在$_currentSeconds秒内完成扫码支付', + style: theme.typography.xl2.copyWith( + color: theme.colorScheme.error, + height: 1, + ), + ), + ].toColumn(), + actions: [], + ); + } +} diff --git a/lib/common/widgets/index.dart b/lib/common/widgets/index.dart index d0ecf00..30d1006 100644 --- a/lib/common/widgets/index.dart +++ b/lib/common/widgets/index.dart @@ -14,6 +14,7 @@ export './app/app_logo.dart'; export './app/app_message_dialog.dart'; export './app/app_page.dart'; export './app/app_price.dart'; +export './app/app_qr_code_dialog.dart'; export './app/app_radio_hour_type_dialog.dart'; export './app/app_title.dart'; export './app/app_wallet_selector.dart'; diff --git a/lib/pages/panel/controller.dart b/lib/pages/panel/controller.dart index 5ae30f1..41e5c6b 100644 --- a/lib/pages/panel/controller.dart +++ b/lib/pages/panel/controller.dart @@ -21,7 +21,7 @@ class PanelController extends GetxController { PanelItem(title: "开卡管理", visible: true, type: PanelType.cardActive), PanelItem(title: "设置", visible: true, type: PanelType.setting), PanelItem(title: "退出登录", visible: true, type: PanelType.logout), - // PanelItem(title: "测试", visible: true, type: PanelType.test), + PanelItem(title: "测试", visible: true, type: PanelType.test), ].obs; final canteenMenus = [ @@ -142,13 +142,13 @@ class PanelController extends GetxController { Get.offAndToNamed(RouteNames.login); break; case PanelType.test: - // await CashBoxManage.openCT1(); - // await CashBoxManage.openCT2(); - // final status = await CashBoxManage.checkStatus(); - // logger.e(status); - String phon1 = TtsManage.numberToChineseReading("3144"); - String phon2 = TtsManage.numberToChineseReading("3155"); - TtsManage.speak("请手机尾号,$phon1、$phon2,的用户取餐"); + final qrData = + "${Constants.h5PayUrl}?action=hardQrCodePay&orderId=123&mchId=123"; + showQrCodeDialog( + Get.context!, + qrData: qrData, + onFinished: () {}, + ); break; default: break; diff --git a/lib/pages/panel/view.dart b/lib/pages/panel/view.dart index 93aa653..baff0ae 100644 --- a/lib/pages/panel/view.dart +++ b/lib/pages/panel/view.dart @@ -1,5 +1,4 @@ import 'package:ducafe_ui_core/ducafe_ui_core.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:forui/forui.dart'; import 'package:get/get.dart'; diff --git a/pubspec.lock b/pubspec.lock index 7761784..72e827b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1026,6 +1026,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "6.0.1" + pretty_qr_code: + dependency: "direct main" + description: + name: pretty_qr_code + sha256: "2291db3f68d70a3dcd46c6bd599f30991ae4c02f27f36215fbb3f4865a609259" + url: "https://pub.flutter-io.cn" + source: hosted + version: "3.5.0" printing: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index d74137a..526b0d3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -38,6 +38,8 @@ dependencies: syncfusion_flutter_datepicker: ^28.2.11 # tts转语音 flutter_tts: ^4.2.2 + # 二维码 + pretty_qr_code: ^3.5.0 # 权限判断 permission_handler: ^11.4.0