qrcode_scan_page.dart 5.8 KB

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