|
|
@@ -18,6 +18,10 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
String? _targetCageId;
|
|
|
final List<String> _rfids = [];
|
|
|
|
|
|
+ // 添加FocusNode用于控制焦点
|
|
|
+ final FocusNode _sourceCageFocusNode = FocusNode();
|
|
|
+ final FocusNode _targetCageFocusNode = FocusNode();
|
|
|
+
|
|
|
// 扫描状态
|
|
|
bool _isScanningSource = false;
|
|
|
bool _isScanningTarget = false;
|
|
|
@@ -28,6 +32,19 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
void initState() {
|
|
|
super.initState();
|
|
|
|
|
|
+ // 监听焦点变化以更新_scanTag值
|
|
|
+ _sourceCageFocusNode.addListener(() {
|
|
|
+ if (_sourceCageFocusNode.hasFocus) {
|
|
|
+ _scanTag = 1;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
+ _targetCageFocusNode.addListener(() {
|
|
|
+ if (_targetCageFocusNode.hasFocus) {
|
|
|
+ _scanTag = 2;
|
|
|
+ }
|
|
|
+ });
|
|
|
+
|
|
|
ScanChannel.openScanHead().then((success) {
|
|
|
if (success) {
|
|
|
logger.d("扫描头已打开");
|
|
|
@@ -45,6 +62,12 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
_sourceCageId = result;
|
|
|
_isScanningSource = false;
|
|
|
});
|
|
|
+ // 源笼号扫描成功后自动延时扫描目标笼号
|
|
|
+ WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
+ _sourceCageFocusNode.requestFocus();
|
|
|
+ logger.d("开始自动扫描目标笼号");
|
|
|
+ _dealyScanCode(2);
|
|
|
+ });
|
|
|
} else if (_scanTag == 2) {
|
|
|
// 目标笼号
|
|
|
setState(() {
|
|
|
@@ -62,10 +85,19 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
});
|
|
|
},
|
|
|
);
|
|
|
+
|
|
|
+ // 进入页面默认使原笼号获取到焦点
|
|
|
+ WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
+ _sourceCageFocusNode.requestFocus();
|
|
|
+ });
|
|
|
}
|
|
|
|
|
|
@override
|
|
|
void dispose() {
|
|
|
+ // 释放FocusNode
|
|
|
+ _sourceCageFocusNode.dispose();
|
|
|
+ _targetCageFocusNode.dispose();
|
|
|
+
|
|
|
// 释放RFID
|
|
|
_rfidManager.disposeRfid();
|
|
|
// 手动关闭扫描头,立即释放资源
|
|
|
@@ -79,84 +111,62 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
Widget build(BuildContext context) {
|
|
|
return Scaffold(
|
|
|
appBar: const VberAppBar(title: '换笼管理', showLeftButton: true),
|
|
|
- body: Padding(
|
|
|
- padding: const EdgeInsets.all(16.0),
|
|
|
- child: Column(
|
|
|
- crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
- children: [
|
|
|
- // 源笼号区域
|
|
|
- _buildCageSection(
|
|
|
- title: '源笼号',
|
|
|
- value: _sourceCageId,
|
|
|
- isScanning: _isScanningSource,
|
|
|
- onScanPressed: _scanSourceCage,
|
|
|
- onChangePressed: _handleChangeSourceCage,
|
|
|
- ),
|
|
|
+ body: SingleChildScrollView(
|
|
|
+ child: Padding(
|
|
|
+ padding: const EdgeInsets.all(16.0),
|
|
|
+ child: Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ // 源笼号区域
|
|
|
+ _buildCageSection(1),
|
|
|
|
|
|
- const SizedBox(height: 15),
|
|
|
+ const SizedBox(height: 15),
|
|
|
|
|
|
- // 目标笼号区域
|
|
|
- _buildCageSection(
|
|
|
- title: '目标笼号',
|
|
|
- value: _targetCageId,
|
|
|
- isScanning: _isScanningTarget,
|
|
|
- onScanPressed: _scanTargetCage,
|
|
|
- onChangePressed: _handleChangeTargetCage,
|
|
|
- ),
|
|
|
- const SizedBox(height: 15),
|
|
|
- // 电子编号区域
|
|
|
- VberRfidField(
|
|
|
- rfids: _rfids,
|
|
|
- onRfidScanned: (rfid) {
|
|
|
- setState(() {
|
|
|
- _rfids.insert(0, rfid);
|
|
|
- });
|
|
|
- ToastUtil.success("标签已添加");
|
|
|
- },
|
|
|
- multiple: true,
|
|
|
- label: '鸡数量',
|
|
|
- multiplePlaceholder: '未扫描',
|
|
|
- multipleFormat: '已扫描 %d 只鸡',
|
|
|
- ),
|
|
|
- const SizedBox(height: 15),
|
|
|
- // 提交按钮
|
|
|
- SizedBox(
|
|
|
- width: double.infinity,
|
|
|
- child: ElevatedButton(
|
|
|
- onPressed:
|
|
|
- _sourceCageId != null &&
|
|
|
- _targetCageId != null &&
|
|
|
- _rfids.isNotEmpty
|
|
|
- ? _handleSubmit
|
|
|
- : null,
|
|
|
- style: ElevatedButton.styleFrom(
|
|
|
- backgroundColor:
|
|
|
- (_sourceCageId != null &&
|
|
|
+ // 目标笼号区域
|
|
|
+ _buildCageSection(2),
|
|
|
+ const SizedBox(height: 15),
|
|
|
+ // 电子编号区域
|
|
|
+ _buildRfidSection(),
|
|
|
+ const SizedBox(height: 15),
|
|
|
+ // 提交按钮
|
|
|
+ SizedBox(
|
|
|
+ width: double.infinity,
|
|
|
+ child: ElevatedButton(
|
|
|
+ onPressed:
|
|
|
+ _sourceCageId != null &&
|
|
|
_targetCageId != null &&
|
|
|
- _rfids.isNotEmpty)
|
|
|
- ? Colors.blue
|
|
|
- : Colors.grey,
|
|
|
- foregroundColor: Colors.white,
|
|
|
+ _rfids.isNotEmpty
|
|
|
+ ? _handleSubmit
|
|
|
+ : null,
|
|
|
+ style: ElevatedButton.styleFrom(
|
|
|
+ backgroundColor:
|
|
|
+ (_sourceCageId != null &&
|
|
|
+ _targetCageId != null &&
|
|
|
+ _rfids.isNotEmpty)
|
|
|
+ ? Colors.blue
|
|
|
+ : Colors.grey,
|
|
|
+ foregroundColor: Colors.white,
|
|
|
+ ),
|
|
|
+ child: const Text('提交'),
|
|
|
),
|
|
|
- child: const Text('提交'),
|
|
|
- ),
|
|
|
- ),
|
|
|
- const SizedBox(height: 20),
|
|
|
- // 已扫描的电子编号列表
|
|
|
- if (_rfids.isNotEmpty) ...[
|
|
|
- const Text(
|
|
|
- '已扫描的电子编号',
|
|
|
- style: TextStyle(fontWeight: FontWeight.bold),
|
|
|
),
|
|
|
- const SizedBox(height: 10),
|
|
|
- Expanded(
|
|
|
- child: Container(
|
|
|
+ const SizedBox(height: 20),
|
|
|
+ // 已扫描的电子编号列表
|
|
|
+ if (_rfids.isNotEmpty) ...[
|
|
|
+ const Text(
|
|
|
+ '已扫描的电子编号',
|
|
|
+ style: TextStyle(fontWeight: FontWeight.bold),
|
|
|
+ ),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Container(
|
|
|
padding: const EdgeInsets.all(10),
|
|
|
decoration: BoxDecoration(
|
|
|
border: Border.all(color: Colors.grey),
|
|
|
borderRadius: BorderRadius.circular(8),
|
|
|
),
|
|
|
child: ListView.builder(
|
|
|
+ shrinkWrap: true,
|
|
|
+ physics: const NeverScrollableScrollPhysics(),
|
|
|
padding: EdgeInsets.zero,
|
|
|
itemCount: _rfids.length,
|
|
|
itemBuilder: (context, index) {
|
|
|
@@ -179,22 +189,27 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
},
|
|
|
),
|
|
|
),
|
|
|
- ),
|
|
|
+ ],
|
|
|
+ const SizedBox(height: 20),
|
|
|
],
|
|
|
- const SizedBox(height: 20),
|
|
|
- ],
|
|
|
+ ),
|
|
|
),
|
|
|
),
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- Widget _buildCageSection({
|
|
|
- required String title,
|
|
|
- String? value,
|
|
|
- required bool isScanning,
|
|
|
- required VoidCallback onScanPressed,
|
|
|
- required VoidCallback onChangePressed,
|
|
|
- }) {
|
|
|
+ Widget _buildCageSection(int tag) {
|
|
|
+ String title = '源笼号';
|
|
|
+ String? value = _sourceCageId;
|
|
|
+ bool isScanning = _isScanningSource;
|
|
|
+ FocusNode focusNode = _sourceCageFocusNode;
|
|
|
+ if (tag != 1) {
|
|
|
+ tag = 2;
|
|
|
+ title = '目标笼号';
|
|
|
+ value = _targetCageId;
|
|
|
+ isScanning = _isScanningTarget;
|
|
|
+ focusNode = _targetCageFocusNode;
|
|
|
+ }
|
|
|
return Column(
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
children: [
|
|
|
@@ -209,18 +224,42 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
child: Row(
|
|
|
children: [
|
|
|
Expanded(
|
|
|
- child: Text(
|
|
|
- value ?? '未扫描',
|
|
|
+ // 将Text替换为TextField
|
|
|
+ child: TextField(
|
|
|
+ focusNode: focusNode,
|
|
|
+ controller: TextEditingController(text: value),
|
|
|
+ decoration: InputDecoration(
|
|
|
+ border: InputBorder.none,
|
|
|
+ hintText: value ?? '未扫描',
|
|
|
+ hintStyle: TextStyle(
|
|
|
+ color: value != null ? Colors.black : Colors.grey,
|
|
|
+ fontSize: 16,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
style: TextStyle(
|
|
|
color: value != null ? Colors.black : Colors.grey,
|
|
|
fontSize: 16,
|
|
|
),
|
|
|
+ onChanged: (text) {
|
|
|
+ // 根据标题判断是哪个输入框
|
|
|
+ if (title == '源笼号') {
|
|
|
+ setState(() {
|
|
|
+ _sourceCageId = text.isEmpty ? null : text;
|
|
|
+ });
|
|
|
+ } else if (title == '目标笼号') {
|
|
|
+ setState(() {
|
|
|
+ _targetCageId = text.isEmpty ? null : text;
|
|
|
+ });
|
|
|
+ }
|
|
|
+ },
|
|
|
),
|
|
|
),
|
|
|
if (value != null) ...[
|
|
|
IconButton(
|
|
|
icon: const Icon(Icons.refresh, size: 20),
|
|
|
- onPressed: onChangePressed,
|
|
|
+ onPressed: () {
|
|
|
+ _handleChangeCageCode(tag);
|
|
|
+ },
|
|
|
),
|
|
|
] else ...[
|
|
|
IconButton(
|
|
|
@@ -231,7 +270,9 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
child: CircularProgressIndicator(strokeWidth: 2),
|
|
|
)
|
|
|
: const Icon(Icons.qr_code_scanner, size: 20),
|
|
|
- onPressed: onScanPressed,
|
|
|
+ onPressed: () {
|
|
|
+ _handleScanCageCode(tag);
|
|
|
+ },
|
|
|
),
|
|
|
],
|
|
|
],
|
|
|
@@ -241,48 +282,65 @@ class _CageChangePageState extends State<CageChangePage> {
|
|
|
);
|
|
|
}
|
|
|
|
|
|
- // 扫描源笼号
|
|
|
- void _scanSourceCage() async {
|
|
|
- if (_isScanningSource) return;
|
|
|
+ Widget _buildRfidSection() {
|
|
|
+ return Column(
|
|
|
+ crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
+ children: [
|
|
|
+ const Text('电子编号', style: TextStyle(fontWeight: FontWeight.bold)),
|
|
|
+ const SizedBox(height: 10),
|
|
|
+ Container(
|
|
|
+ padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
|
|
|
+ decoration: BoxDecoration(),
|
|
|
+ ),
|
|
|
+ ],
|
|
|
+ );
|
|
|
+ // return VberRfidField(
|
|
|
+ // rfids: _rfids,
|
|
|
+ // onRfidScanned: (rfid) {
|
|
|
+ // setState(() {
|
|
|
+ // _rfids.insert(0, rfid);
|
|
|
+ // });
|
|
|
+ // ToastUtil.success("标签已添加");
|
|
|
+ // },
|
|
|
+ // multiple: true,
|
|
|
+ // label: '鸡数量',
|
|
|
+ // multiplePlaceholder: '未扫描',
|
|
|
+ // multipleFormat: '已扫描 %d 只鸡',
|
|
|
+ // );
|
|
|
+ }
|
|
|
|
|
|
- setState(() {
|
|
|
- _isScanningSource = true;
|
|
|
- });
|
|
|
+ void _dealyScanCode(int scanTag, {int? dealy}) async {
|
|
|
+ dealy ??= 800;
|
|
|
+ _scanTag = scanTag;
|
|
|
|
|
|
- _scanTag = 1;
|
|
|
+ await Future.delayed(Duration(milliseconds: dealy));
|
|
|
bool success = await ScanChannel.startScan();
|
|
|
if (!success) {
|
|
|
ToastUtil.error("扫码失败");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 扫描目标笼号
|
|
|
- void _scanTargetCage() async {
|
|
|
- if (_isScanningTarget) return;
|
|
|
-
|
|
|
+ void _handleScanCageCode(int tag) async {
|
|
|
+ if (_isScanningTarget || _isScanningSource) return;
|
|
|
setState(() {
|
|
|
- _isScanningTarget = true;
|
|
|
+ if (tag == 1) {
|
|
|
+ _isScanningSource = true;
|
|
|
+ } else if (tag == 2) {
|
|
|
+ _isScanningTarget = true;
|
|
|
+ }
|
|
|
});
|
|
|
-
|
|
|
- _scanTag = 2;
|
|
|
+ _scanTag = tag;
|
|
|
bool success = await ScanChannel.startScan();
|
|
|
if (!success) {
|
|
|
ToastUtil.error("扫码失败");
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // 重新扫描源笼号
|
|
|
- void _handleChangeSourceCage() {
|
|
|
+ void _handleChangeCageCode(int tag) {
|
|
|
setState(() {
|
|
|
_sourceCageId = null;
|
|
|
});
|
|
|
- }
|
|
|
-
|
|
|
- // 重新扫描目标笼号
|
|
|
- void _handleChangeTargetCage() {
|
|
|
- setState(() {
|
|
|
- _targetCageId = null;
|
|
|
- });
|
|
|
+ _dealyScanCode(tag);
|
|
|
}
|
|
|
|
|
|
// 移除指定索引的电子编号
|