feat:二维码支付
This commit is contained in:
1 parent
2f1c98392f
commit
c94a909bfe
7 files changed
+195
-11
No files matched your search
@@ -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;
|
||||
|
||||
@@ -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<T?> showQrCodeDialog<T>(
|
||||
BuildContext context, {
|
||||
required String qrData,
|
||||
int countDownSeconds = 30,
|
||||
required VoidCallback onFinished,
|
||||
}) {
|
||||
return showDialog<T?>(
|
||||
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<AppQrCodeDialog> createState() => _AppQrCodeDialogState();
|
||||
}
|
||||
|
||||
class _AppQrCodeDialogState extends State<AppQrCodeDialog> {
|
||||
// 当前的倒计时秒数
|
||||
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: <Widget>[
|
||||
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: <Widget>[
|
||||
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: [],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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';
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user