vb_rfid_field.dart 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. import 'package:flutter/material.dart';
  2. import 'package:chicken_farm/core/services/pda/rfid_manager.dart';
  3. import 'package:chicken_farm/core/utils/toast.dart';
  4. /// RFID字段组件,支持单个或多个RFID显示
  5. ///
  6. /// 当[multiple]为true时,显示已扫描的RFID数量
  7. /// 当[multiple]为false时,显示单个RFID的具体值
  8. class VberRfidField extends StatefulWidget {
  9. final List<String>? rfids;
  10. final String? rfid;
  11. final ValueChanged<String>? onRfidScanned; // RFID扫描成功回调
  12. final bool multiple;
  13. final ValueChanged<int>? onDeleteRfid; // 仅在multiple模式下使用
  14. final String label; // 显示的标签文本
  15. final String placeholder; // 未扫描时显示的占位符文本
  16. final String multiplePlaceholder; // 多个模式下未扫描时显示的占位符文本
  17. final String multipleFormat; // 多个模式下有值时的显示格式,包含一个%d占位符表示数量
  18. const VberRfidField({
  19. super.key,
  20. this.rfids,
  21. this.rfid,
  22. this.onRfidScanned,
  23. this.multiple = false,
  24. this.onDeleteRfid,
  25. this.label = '电子编号',
  26. this.placeholder = '未扫描',
  27. this.multiplePlaceholder = '未扫描',
  28. this.multipleFormat = '已扫描 %d 只鸡',
  29. });
  30. @override
  31. State<VberRfidField> createState() => _VberRfidFieldState();
  32. }
  33. class _VberRfidFieldState extends State<VberRfidField> {
  34. late final RfidManager _rfidManager;
  35. bool _isScanning = false; // 内部管理扫描状态
  36. @override
  37. void initState() {
  38. super.initState();
  39. _rfidManager = RfidManager(_handleRfidScanned, null);
  40. _rfidManager.initRfid();
  41. }
  42. @override
  43. void dispose() {
  44. _rfidManager.disposeRfid();
  45. super.dispose();
  46. }
  47. void _handleRfidScanned(String rfid) {
  48. setState(() {
  49. _isScanning = false;
  50. });
  51. if (widget.onRfidScanned != null) {
  52. widget.onRfidScanned!(rfid);
  53. }
  54. }
  55. void _scanRfid() {
  56. setState(() {
  57. _isScanning = true;
  58. });
  59. ToastUtil.success('开始扫描RFID');
  60. _rfidManager.startScan();
  61. }
  62. @override
  63. Widget build(BuildContext context) {
  64. return Column(
  65. crossAxisAlignment: CrossAxisAlignment.start,
  66. children: [
  67. Text(widget.label, style: const TextStyle(fontWeight: FontWeight.bold)),
  68. const SizedBox(height: 10),
  69. Container(
  70. padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
  71. decoration: BoxDecoration(
  72. border: Border.all(color: Colors.grey),
  73. borderRadius: BorderRadius.circular(8),
  74. ),
  75. child: Row(
  76. children: [
  77. Expanded(
  78. child: Text(
  79. _getDisplayText(),
  80. style: TextStyle(
  81. color: _hasValue() ? Colors.black : Colors.grey,
  82. fontSize: 16,
  83. ),
  84. ),
  85. ),
  86. IconButton(
  87. icon: _isScanning
  88. ? const SizedBox(
  89. width: 20,
  90. height: 20,
  91. child: CircularProgressIndicator(strokeWidth: 2),
  92. )
  93. : Icon(
  94. widget.multiple ? Icons.add : Icons.qr_code_scanner,
  95. size: 20,
  96. ),
  97. onPressed: _isScanning ? null : _scanRfid,
  98. ),
  99. ],
  100. ),
  101. ),
  102. ],
  103. );
  104. }
  105. /// 获取显示的文本
  106. String _getDisplayText() {
  107. if (widget.multiple) {
  108. if (widget.rfids == null || widget.rfids!.isEmpty) {
  109. return widget.multiplePlaceholder;
  110. } else {
  111. return widget.multipleFormat.replaceAll(
  112. '%d',
  113. widget.rfids!.length.toString(),
  114. );
  115. }
  116. } else {
  117. return widget.rfid ?? widget.placeholder;
  118. }
  119. }
  120. /// 判断是否有值
  121. bool _hasValue() {
  122. if (widget.multiple) {
  123. return widget.rfids != null && widget.rfids!.isNotEmpty;
  124. } else {
  125. return widget.rfid != null;
  126. }
  127. }
  128. }