qrcode_scan_page.dart 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. import 'dart:io';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:lszlgl/page/sample_task/reap_sample_detail/reap_sample_task_page.dart';
  5. import 'package:qr_code_scanner/qr_code_scanner.dart';
  6. import '../../base/base_lifecycle_state.dart';
  7. import '../../widget/button.dart';
  8. class QrCodeScanPage extends StatefulWidget {
  9. const QrCodeScanPage({super.key});
  10. @override
  11. State<QrCodeScanPage> createState() => _QrCodeScanPageState();
  12. }
  13. class _QrCodeScanPageState extends BaseLifecycleState<QrCodeScanPage> with SingleTickerProviderStateMixin {
  14. final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
  15. Barcode? result;
  16. QRViewController? controller;
  17. late AnimationController _ctrl;
  18. late Animation<Offset> animation;
  19. void _onQRViewCreated(QRViewController controller) {
  20. this.controller = controller;
  21. controller.scannedDataStream.listen((scanData) {
  22. debugPrint('code:${scanData.code} format:${scanData.format} rawBytes:${scanData.rawBytes}');
  23. controller.pauseCamera();
  24. parseCode(scanData);
  25. });
  26. }
  27. void parseCode(Barcode data) {
  28. String code = data.code ?? '';
  29. if (code.isEmpty) {
  30. showErrorDialog('内容为空,请扫描正确二维码');
  31. return;
  32. }
  33. // 库房详情 http://121.36.17.6:18089/?ajbm=3291653123710827520U010011
  34. if(code.contains('?ajbm=')){
  35. List<String> list = code.split('ajbm=');
  36. if(list.last.isEmpty){
  37. showErrorDialog(code);
  38. return;
  39. }else{
  40. MyRouter.startStoreHouse(list.last);
  41. return;
  42. }
  43. }
  44. // 121.36.17.6:19090/admin-api/zj/code-sampling-task-details-sgjc/getSamplingTaskDetails?id=47106
  45. List<String> split = code.split('?');
  46. if (!code.contains('?') || split.length <= 1 || !split[0].contains('/')) {
  47. showErrorDialog(code);
  48. return;
  49. }
  50. String api = split[0].split('/').last;
  51. Map<String, String> params = {};
  52. for (String value in split[1].split('&')) {
  53. List<String> kv = value.split('=');
  54. params[kv[0]] = kv[1];
  55. }
  56. switch (api) {
  57. case 'getSamplingTaskDetails':
  58. // 收获扦样详情
  59. if (params['id'] == null) {
  60. showErrorDialog(code);
  61. return;
  62. }
  63. MyRouter.startReapSampleTask(
  64. args: ReapSampleTaskPageArgs(id: num.parse(params['id']!), detail: true),
  65. replace: true,
  66. );
  67. default:
  68. showErrorDialog(code);
  69. }
  70. }
  71. void showErrorDialog(String msg) async {
  72. await showDialog(
  73. context: context,
  74. builder: (_) => AlertDialog(
  75. title: Text(msg),
  76. actions: [MyButton('确定', alignment: null, onTap: () => MyNavigator.pop())],
  77. ),
  78. );
  79. controller?.resumeCamera();
  80. }
  81. // In order to get hot reload to work we need to pause the camera if the platform
  82. // is android, or resume the camera if the platform is iOS.
  83. @override
  84. void reassemble() {
  85. super.reassemble();
  86. if (Platform.isAndroid) {
  87. controller!.pauseCamera();
  88. } else if (Platform.isIOS) {
  89. controller!.resumeCamera();
  90. }
  91. }
  92. @override
  93. void dispose() {
  94. controller?.dispose();
  95. _ctrl.dispose();
  96. super.dispose();
  97. }
  98. @override
  99. void initState() {
  100. super.initState();
  101. // 创建动画控制器
  102. _ctrl = AnimationController(
  103. vsync: this,
  104. duration: const Duration(seconds: 2),
  105. );
  106. animation = Tween<Offset>(
  107. begin: const Offset(0, -0.25),
  108. end: const Offset(0, 0.25),
  109. ).animate(_ctrl);
  110. _ctrl.repeat();
  111. }
  112. @override
  113. Widget build(BuildContext context) {
  114. return myScaffold(child: buildBody());
  115. }
  116. Widget buildBody() {
  117. return AnnotatedRegion<SystemUiOverlayStyle>(
  118. value: SystemUiOverlayStyle.light,
  119. child: Stack(
  120. fit: StackFit.expand,
  121. children: [
  122. // myAppBar(
  123. // title: '扫一扫',
  124. // actions: [buildFlash()],
  125. // ),
  126. Positioned.fill(
  127. child: QRView(
  128. key: qrKey,
  129. onQRViewCreated: _onQRViewCreated,
  130. ),
  131. ),
  132. Positioned(
  133. top: 0,
  134. left: 0,
  135. right: 0,
  136. child: buildAppBar(),
  137. ),
  138. SlideTransition(
  139. position: animation,
  140. child: Image.asset(imgScanScanning, width: double.infinity),
  141. ),
  142. ],
  143. ),
  144. );
  145. }
  146. Widget buildAppBar() {
  147. return Padding(
  148. padding: EdgeInsets.only(top: MediaQuery.of(context).padding.top),
  149. child: Stack(
  150. alignment: Alignment.center,
  151. children: [
  152. Positioned(left: 0, child: buildBack()),
  153. const Text(
  154. '扫一扫',
  155. textAlign: TextAlign.center,
  156. style: TextStyle(color: Colors.white, fontSize: 20),
  157. ),
  158. Positioned(
  159. right: 0,
  160. child: buildFlash(),
  161. ),
  162. ],
  163. ),
  164. );
  165. }
  166. Widget buildBack() {
  167. return GestureDetector(
  168. onTap: () => MyNavigator.pop(),
  169. child: Padding(
  170. padding: const EdgeInsets.symmetric(horizontal: 16),
  171. child: Image.asset(imgScanBack, width: 24, height: 24),
  172. ),
  173. );
  174. }
  175. Widget buildFlash() {
  176. return GestureDetector(
  177. onTap: () => controller?.toggleFlash(),
  178. behavior: HitTestBehavior.opaque,
  179. child: Padding(
  180. padding: const EdgeInsets.symmetric(horizontal: 16),
  181. child: Row(
  182. children: [
  183. Image.asset(imgScanFlash, width: 24, height: 24),
  184. const Text(
  185. '闪光灯',
  186. textAlign: TextAlign.center,
  187. style: TextStyle(color: Colors.white, fontSize: 14),
  188. ),
  189. ],
  190. ),
  191. ),
  192. );
  193. }
  194. }