diff --git a/android/app/src/main/kotlin/com/example/pj_supermarket_cloud/MainActivity.kt b/android/app/src/main/kotlin/com/example/pj_supermarket_cloud/MainActivity.kt index ac7a6a9..4ca4f2e 100644 --- a/android/app/src/main/kotlin/com/example/pj_supermarket_cloud/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/pj_supermarket_cloud/MainActivity.kt @@ -10,7 +10,7 @@ class MainActivity : FlutterActivity() { // 人脸识别插件 val flutterFaceDiscernPlugin = FlutterFaceDiscernPlugin() flutterEngine.plugins.add(flutterFaceDiscernPlugin) - - // 箭头全局键盘插件 + + // 键盘全局键盘插件 } } diff --git a/lib/common/models/api/hard_api_models.dart b/lib/common/models/api/hard_api_models.dart index 4ad059a..ddecc63 100644 --- a/lib/common/models/api/hard_api_models.dart +++ b/lib/common/models/api/hard_api_models.dart @@ -174,10 +174,18 @@ class ServiceQRCode { final String? userId; /// 订单类型 - final String? orderType; + @JsonKey( + fromJson: JsonTool.stringToOrderType, + toJson: JsonTool.orderTypeToString, + ) + final OrderType? orderType; /// 支付类型 - final String? payType; + @JsonKey( + fromJson: JsonTool.stringToOrderPayType, + toJson: JsonTool.orderPayTypeToString, + ) + final OrderPayType? payType; /// 过期时间 -1 代表没有限制 final int? exceedTime; diff --git a/lib/common/models/api/hard_api_models.g.dart b/lib/common/models/api/hard_api_models.g.dart index 00e9c7e..3cd1992 100644 --- a/lib/common/models/api/hard_api_models.g.dart +++ b/lib/common/models/api/hard_api_models.g.dart @@ -101,8 +101,8 @@ ServiceQRCode _$ServiceQRCodeFromJson(Map json) => itemId: JsonTool.intToString((json['itemId'] as num?)?.toInt()), typeId: JsonTool.intToString((json['typeId'] as num?)?.toInt()), userId: JsonTool.intToString((json['userId'] as num?)?.toInt()), - orderType: json['orderType'] as String?, - payType: json['payType'] as String?, + orderType: JsonTool.stringToOrderType(json['orderType'] as String?), + payType: JsonTool.stringToOrderPayType(json['payType'] as String?), exceedTime: (json['exceedTime'] as num?)?.toInt(), extra: json['extra'] as String?, ); @@ -113,8 +113,8 @@ Map _$ServiceQRCodeToJson(ServiceQRCode instance) => 'itemId': JsonTool.stringToInt(instance.itemId), 'typeId': JsonTool.stringToInt(instance.typeId), 'userId': JsonTool.stringToInt(instance.userId), - 'orderType': instance.orderType, - 'payType': instance.payType, + 'orderType': JsonTool.orderTypeToString(instance.orderType), + 'payType': JsonTool.orderPayTypeToString(instance.payType), 'exceedTime': instance.exceedTime, 'extra': instance.extra, }; diff --git a/lib/common/utils/index.dart b/lib/common/utils/index.dart index 6c5b872..0f44e50 100644 --- a/lib/common/utils/index.dart +++ b/lib/common/utils/index.dart @@ -17,6 +17,7 @@ export './keyboard/keyboard_tool.dart'; export './logger/logger_tool.dart'; +export './manage/barcode_scan_manage.dart'; export './manage/base/serial_base.dart'; export './manage/base/base_facility_manage.dart'; export './manage/tool/serial_read_card_tool.dart'; diff --git a/lib/common/utils/json/json_tool.dart b/lib/common/utils/json/json_tool.dart index 7ea6fe6..7b8d916 100644 --- a/lib/common/utils/json/json_tool.dart +++ b/lib/common/utils/json/json_tool.dart @@ -1,3 +1,5 @@ +import 'package:pj_supermarket_cloud/common/index.dart'; + abstract class JsonTool { static bool stringToBoolean(String value) { return value == '1'; @@ -27,4 +29,22 @@ abstract class JsonTool { if (value == null) return null; return dynamic as Map?; } + + static OrderType? stringToOrderType(String? value) { + return OrderType.values.fromCode(value); + } + + static String? orderTypeToString(OrderType? value) { + if (value == null) return null; + return value.toString(); + } + + static OrderPayType? stringToOrderPayType(String? value) { + return OrderPayType.values.fromCode(value); + } + + static String? orderPayTypeToString(OrderPayType? value) { + if (value == null) return null; + return value.toString(); + } } diff --git a/lib/common/utils/manage/barcode_scan_manage.dart b/lib/common/utils/manage/barcode_scan_manage.dart new file mode 100644 index 0000000..ad401db --- /dev/null +++ b/lib/common/utils/manage/barcode_scan_manage.dart @@ -0,0 +1,177 @@ +import 'dart:async'; +import 'dart:convert'; +import 'package:common_utils/common_utils.dart'; +import 'package:flutter/services.dart'; + +import 'package:pj_supermarket_cloud/common/index.dart'; + +class BarcodeScanManage { + static const String _tag = "条码扫描管理"; + + BarcodeScanManage._privateConstructor(); + + static final BarcodeScanManage _instance = + BarcodeScanManage._privateConstructor(); + + static BarcodeScanManage get instance => _instance; + + bool _isListening = false; + String _buffer = ''; + Timer? _timer; + final StreamController _scanController = + StreamController.broadcast(); + + Stream get scanStream => _scanController.stream; + + // 开始监听USB读头输入 + void startListening() { + if (_isListening) return; + _isListening = true; + RawKeyboard.instance.addListener(_handleKeyEvent); + logger.i("|$_tag|开始监听USB读头输入"); + } + + // 停止监听 + void stopListening() { + if (!_isListening) return; + RawKeyboard.instance.removeListener(_handleKeyEvent); + _timer?.cancel(); + _isListening = false; + logger.i("|$_tag|停止监听USB读头输入"); + } + + // 处理键盘事件 + void _handleKeyEvent(RawKeyEvent event) { + if (event is! RawKeyDownEvent) return; + // 重置定时器 + _timer?.cancel(); + // 处理回车键,表示扫码结束 + if (event.logicalKey == LogicalKeyboardKey.enter) { + if (_buffer.isNotEmpty) { + logger.i("|$_tag|扫码结果: $_buffer"); + // 清理和验证 base64 字符串 + final cleanedBase64 = _cleanBase64(_buffer); + _scanController.add(cleanedBase64); + _buffer = ''; + } + return; + } + + // 获取字符 + final character = _getCharacter(event); + if (character != null) { + _buffer += character; + // 设置超时定时器,如果超过一定时间没有新输入,则清空缓冲区 + _timer = Timer(Duration(milliseconds: 100), () { + _buffer = ''; + }); + } + } + + // 清理和验证 base64 字符串 + String _cleanBase64(String input) { + String cleaned = input.trim(); + cleaned = cleaned.replaceAll(RegExp(r'[^A-Za-z0-9+/=]'), ''); + while (cleaned.length % 4 != 0) { + cleaned += '='; + } + return cleaned; + } + + // 从键盘事件中获取字符 + String? _getCharacter(RawKeyEvent event) { + // 处理数字键 + if (event.logicalKey.keyId >= LogicalKeyboardKey.digit0.keyId && + event.logicalKey.keyId <= LogicalKeyboardKey.digit9.keyId) { + return String.fromCharCode( + event.logicalKey.keyId - LogicalKeyboardKey.digit0.keyId + 48); + } + + // 处理小写字母键 + if (event.logicalKey.keyId >= LogicalKeyboardKey.keyA.keyId && + event.logicalKey.keyId <= LogicalKeyboardKey.keyZ.keyId) { + // 检查是否按下了Shift键,决定返回大写还是小写字母 + final isShiftPressed = event.isShiftPressed; + final charCode = event.logicalKey.keyId - + LogicalKeyboardKey.keyA.keyId + + (isShiftPressed ? 65 : 97); + return String.fromCharCode(charCode); + } + + // 处理其他常见字符 + switch (event.logicalKey) { + case LogicalKeyboardKey.minus: + return event.isShiftPressed ? '_' : '-'; + case LogicalKeyboardKey.equal: + return event.isShiftPressed ? '+' : '='; + case LogicalKeyboardKey.bracketLeft: + return '['; + case LogicalKeyboardKey.bracketRight: + return ']'; + case LogicalKeyboardKey.backslash: + return '\\'; + case LogicalKeyboardKey.semicolon: + return ';'; + case LogicalKeyboardKey.quote: + return '\''; + case LogicalKeyboardKey.comma: + return ','; + case LogicalKeyboardKey.period: + return '.'; + case LogicalKeyboardKey.slash: + return event.isShiftPressed ? '?' : '/'; + case LogicalKeyboardKey.add: + return '+'; + case LogicalKeyboardKey.underscore: + return '_'; + default: + return null; + } + } + + // 尝试解码 base64 字符串 + Future getCodeInfo(String base64Str) async { + try { + final cleanedBase64 = _cleanBase64(base64Str); + final json = EncryptUtil.decodeBase64(cleanedBase64); + if (ObjectUtil.isEmpty(json)) { + logger.e("|$_tag|二维码解析错误base64|$json|"); + await TtsManage.speak("扫码失败请重试,base64解析错误"); + return null; + } + final qrCode = ServiceQRCode.fromJson(jsonDecode(json)); + if (ObjectUtil.isEmpty(qrCode)) { + logger.e("|$_tag|无效的二维码,json|$json|"); + await TtsManage.speak("无效的二维码"); + return null; + } + // 支付方式 + if (ObjectUtil.isEmpty(qrCode.payType) || + ObjectUtil.isEmpty(qrCode.orderType)) { + logger.e("|$_tag|无效的二维码,支付方式或者订单类型错误,json|$json|"); + await TtsManage.speak("无效的二维码"); + return null; + } + return qrCode; + } catch (e) { + logger.e("|$_tag|二维码解析错误: $e"); + return null; + } + } + + // 尝试解析 JSON + Map? parseJson(String jsonStr) { + try { + return json.decode(jsonStr) as Map; + } catch (e) { + logger.e("|$_tag|JSON解析错误: $e"); + return null; + } + } + + // 释放资源 + void dispose() { + stopListening(); + _scanController.close(); + } +} diff --git a/lib/common/widgets/order/select_pay_type_dialog.dart b/lib/common/widgets/order/select_pay_type_dialog.dart index b2817d1..79de611 100644 --- a/lib/common/widgets/order/select_pay_type_dialog.dart +++ b/lib/common/widgets/order/select_pay_type_dialog.dart @@ -195,25 +195,6 @@ class SelectPayTypeDialogController extends GetxController { } } globalQrCode = qrCode; - // 解析为enum 支付类型 - if (ObjectUtil.isNotEmpty(qrCode.payType)) { - final OrderPayType? type = - OrderPayType.values.fromCode(qrCode.payType!); - if (ObjectUtil.isNotEmpty(type)) { - orderPayType.value = type!; - } - } - // 解析为enum 订单类型 - if (ObjectUtil.isNotEmpty(qrCode.orderType)) { - final OrderType? type = OrderType.values.fromCode(qrCode.orderType!); - if (ObjectUtil.isNotEmpty(type)) { - orderType.value = type!; - } - } - if (orderPayType.value == null || orderType.value == null) { - logger.e("|$_tag|二维码识别,订单类型或者支付类型解析错误:|$str|"); - return; - } if (!_validateQrCodeType(orderPayType.value!)) { logger.e("|$_tag|二维码识别,无效的二维码json:|$str|"); Toast.error(msg: "识别错误,无效的二维码"); diff --git a/lib/pages/panel/controller.dart b/lib/pages/panel/controller.dart index 6641bdc..3badd1c 100644 --- a/lib/pages/panel/controller.dart +++ b/lib/pages/panel/controller.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:common_utils/common_utils.dart'; import 'package:get/get.dart'; @@ -75,8 +77,9 @@ class PanelController extends GetxController { Get.offAndToNamed(RouteNames.login); break; case PanelType.test: - await TtsManage.initialize(); - await TtsManage.speak("购买成功1"); + // tts测试 成功 + // await TtsManage.initialize(); + // await TtsManage.speak("购买成功1"); break; default: break; diff --git a/lib/pages/take_food/controller.dart b/lib/pages/take_food/controller.dart index a239d4e..39f33f4 100644 --- a/lib/pages/take_food/controller.dart +++ b/lib/pages/take_food/controller.dart @@ -95,39 +95,12 @@ class TakeFoodController extends GetxController { /// 开启扫码 Future startQrcode() async { try { - final isOpen = await appC.scanCodeManage.open(); - if (!isOpen) return; - appC.scanCodeManage.listen((str) async { - if (ObjectUtil.isNotEmpty(str)) { - str = EncryptUtil.decodeBase64(str); - final qrCode = ServiceQRCode.fromJson(json.decode(str)); - if (ObjectUtil.isEmpty(qrCode)) { - Toast.error(msg: "识别错误,无效的二维码"); - return; - } - globalQrCode = qrCode; - // 二维码支付渠道 - if (ObjectUtil.isNotEmpty(qrCode.payType)) { - final OrderPayType? type = OrderPayType.values.fromCode( - qrCode.payType!, - ); - if (ObjectUtil.isNotEmpty(type)) { - orderPayType = type!; - } - } - if (ObjectUtil.isNotEmpty(qrCode.orderType)) { - final OrderType? type = OrderType.values.fromCode( - qrCode.orderType!, - ); - if (ObjectUtil.isNotEmpty(type)) { - orderType = type!; - } - } - orderId = qrCode.id; - await getOrderDetail(); - await getCarList(); - Toast.success(msg: "识别二维码成功"); - } + // 监听二维码测试 + BarcodeScanManage.instance.startListening(); + BarcodeScanManage.instance.scanStream.listen((event) async { + final serviceCode = await BarcodeScanManage.instance.getCodeInfo(event); + if (serviceCode == null) return; + globalQrCode = serviceCode; }); } catch (e) { doCancelPay();