import 'package:chicken_farm/apis/index.dart'; import 'package:flutter/material.dart'; import 'package:chicken_farm/components/vb_app_bar.dart'; import 'package:chicken_farm/core/utils/toast.dart'; import 'package:chicken_farm/components/vb_rfid_field.dart'; import 'package:chicken_farm/core/utils/logger.dart'; import 'dart:async'; class IndividualWeighingPage extends StatefulWidget { const IndividualWeighingPage({super.key}); @override State createState() => _IndividualWeighingPageState(); } class _IndividualWeighingPageState extends State { String? _rfid; double? _weight; bool _isReadingWeight = false; // 添加TextController和FocusNode用于重量输入框 final TextEditingController _weightController = TextEditingController(); final FocusNode _weightFocusNode = FocusNode(); // 添加Timer用于延迟处理输入 Timer? _inputDebounceTimer; // 添加超时Timer Timer? _timeoutTimer; @override void dispose() { // 释放TextEditingController和FocusNode _weightController.dispose(); _weightFocusNode.dispose(); // 取消定时器 _inputDebounceTimer?.cancel(); _timeoutTimer?.cancel(); super.dispose(); } @override 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: [ // 电子编号区域 _buildRfidSection(), const SizedBox(height: 20), // 重量区域 _buildWeightSection(), const SizedBox(height: 30), // 提交按钮 SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _rfid != null && _weight != null ? _handleSubmit : null, style: ElevatedButton.styleFrom( backgroundColor: _rfid != null && _weight != null ? Colors.blue : Colors.grey, foregroundColor: Colors.white, ), child: const Text('提交'), ), ), ], ), ), ); } Widget _buildRfidSection() { return VberRfidField( rfid: _rfid, onRfidScanned: (rfid) { setState(() { _rfid = rfid; }); ToastUtil.success('电子编号识别成功'); _handleReadWeight(); }, label: '电子编号', placeholder: '未识别', ); } Widget _buildWeightSection() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('重量(kg)', style: TextStyle(fontWeight: FontWeight.bold)), const SizedBox(height: 10), Container( padding: const EdgeInsets.fromLTRB(16, 2, 16, 2), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: Row( children: [ Expanded( child: TextField( focusNode: _weightFocusNode, controller: _weightController, enabled: _weight == null, decoration: InputDecoration( border: InputBorder.none, hintText: _weight != null ? null : _isReadingWeight ? "正在读取重量" : '请读取重量', hintStyle: TextStyle( color: _isReadingWeight ? Colors.red : _weight != null ? Colors.black : Colors.grey, fontSize: 16, ), ), style: TextStyle( color: _weight != null ? Colors.black : Colors.grey, fontSize: 16, ), keyboardType: TextInputType.numberWithOptions(decimal: true), onChanged: (text) { // 取消之前的定时器 _inputDebounceTimer?.cancel(); // 设置新的定时器,延时处理输入 _inputDebounceTimer = Timer( const Duration(milliseconds: 500), () { if (text.isEmpty) { setState(() { _weight = null; }); } else { try { final parsedValue = double.tryParse(text); if (parsedValue != null) { setState(() { _weight = parsedValue; }); ToastUtil.success('重量读取成功'); } _isReadingWeight = false; } catch (e) { // 输入无效时不更新_weight logger.e('解析重量值失败: $e'); } } }, ); }, ), ), if (_weight != null) ...[ IconButton( icon: const Icon(Icons.refresh, size: 20), onPressed: _handleReadWeight, ), ] else ...[ IconButton( icon: _isReadingWeight ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Icon(Icons.sync, size: 20), onPressed: _handleReadWeight, ), ], ], ), ), ], ); } void _handleReadWeight() { setState(() { _weight = null; _weightController.clear(); _isReadingWeight = true; }); // 重置后输入框获得焦点 WidgetsBinding.instance.addPostFrameCallback((_) { if (mounted) { _weightFocusNode.requestFocus(); } }); // 设置3秒超时 _timeoutTimer?.cancel(); // 取消之前的超时定时器 _timeoutTimer = Timer(const Duration(seconds: 15), () { if (mounted && _isReadingWeight == true) { setState(() { _weight = null; _isReadingWeight = false; _weightFocusNode.unfocus(); }); ToastUtil.error('读取重量超时'); } }); } // 提交数据 void _handleSubmit() { final data = {"rfid": _rfid, "weight": _weight}; apis.breeding.submitApi .weight(data) .then((_) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('称重提交成功'), backgroundColor: Colors.green, ), ); // 提交后重置表单 setState(() { _rfid = null; _weight = null; _weightController.clear(); }); } }) .catchError((err) { ToastUtil.error('称重提交失败'); if (mounted && err != null) { String errorMessage = err.toString(); if (err is Exception) { errorMessage = err.toString(); } ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(errorMessage), backgroundColor: Colors.red, ), ); } }); } }