import 'package:chicken_farm/core/config/app_config.dart'; import 'package:chicken_farm/core/utils/datetime_util.dart'; import 'package:chicken_farm/core/utils/logger.dart'; import 'package:chicken_farm/apis/index.dart'; import 'package:chicken_farm/components/vb_rfid_field.dart'; import 'package:chicken_farm/components/vb_search_select.dart'; import 'package:chicken_farm/components/vb_select.dart'; import 'package:chicken_farm/modes/breeding/batch.dart'; import 'package:chicken_farm/modes/breeding/family.dart'; import 'package:chicken_farm/modes/rfid/rfid_model.dart'; import 'package:flutter/material.dart'; import 'package:chicken_farm/components/vb_app_bar.dart'; import 'package:chicken_farm/core/utils/toast.dart'; class BatchCreatePage extends StatefulWidget { const BatchCreatePage({super.key}); @override State createState() => _BatchCreatePageState(); } class _BatchCreatePageState extends State { final List _rfids = []; String? _batchNum; String? _familyId; @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: [ // 批次选择 _buildBatchInput(), const SizedBox(height: 10), // 家系号选择 _buildFamilyInput(), const SizedBox(height: 20), // 电子编号区域 _buildRfidSection(), const SizedBox(height: 20), // 提交按钮 SizedBox( width: double.infinity, child: ElevatedButton( onPressed: _rfids.isNotEmpty && _batchNum != null && _familyId != null ? _handleSubmit : null, style: ElevatedButton.styleFrom( backgroundColor: _rfids.isNotEmpty && _batchNum != null && _familyId != null ? Colors.blue : Colors.grey, foregroundColor: Colors.white, ), child: const Text('提交'), ), ), const SizedBox(height: 20), // 已识别的电子编号列表 if (_rfids.isNotEmpty) ...[ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( '已识别的电子编号', style: TextStyle(fontWeight: FontWeight.bold), ), IconButton( icon: const Icon(Icons.clear, size: 18), onPressed: _clearRfids, tooltip: '清空编号', ), ], ), const SizedBox(height: 10), Expanded( child: Container( padding: const EdgeInsets.all(10), decoration: BoxDecoration( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: ListView.builder( padding: EdgeInsets.zero, itemCount: _rfids.length, itemBuilder: (context, index) { return ListTile( visualDensity: VisualDensity.compact, contentPadding: const EdgeInsets.symmetric( horizontal: 2, vertical: 0, ), title: Text(_rfids[index]), trailing: IconButton( icon: const Icon( Icons.delete, size: 18, color: Colors.red, ), onPressed: () => _removeRfid(index), ), ); }, ), ), ), ], const SizedBox(height: 20), ], ), ), ); } Widget _buildBatchInput() { if (AppConfig.isOffline) { // 离线模式下使用文本输入框 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( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: TextField( decoration: const InputDecoration( hintText: '请输入批次号', border: InputBorder.none, ), onChanged: (value) { setState(() { _batchNum = value.isNotEmpty ? value : null; }); }, ), ), ], ); } else { // 在线模式下使用原来的搜索选择器 return _buildBatchSearchSelect(); } } Widget _buildFamilyInput() { if (AppConfig.isOffline) { // 离线模式下使用文本输入框 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( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: TextField( decoration: const InputDecoration( hintText: '请输入家系号', border: InputBorder.none, ), onChanged: (value) { setState(() { _familyId = value.isNotEmpty ? value : null; }); }, ), ), ], ); } else { // 在线模式下使用原来的搜索选择器 return _buildFamilySearchSelect(); } } Widget _buildBatchSearchSelect() { 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( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: VberSearchSelect( searchApi: ({required dynamic queryParams}) async { final result = await apis.breeding.queryApi.queryPageBatchs( queryParams, ); return {'rows': result.rows, 'total': result.total}; }, converter: (BatchModel data) { return SelectOption( label: '${data.batchNum}(${data.batchName})', value: data.batchNum, extra: data, ); }, value: _batchNum, hint: '批次号', onChanged: (String? value) { setState(() { _batchNum = value; // 当切换批次时,重置后续选项和数据 _familyId = null; }); // // 获取翅号数据 // if (value != null) { // // 使用Future.microtask确保在下一个微任务中加载数据,避免在构建过程中修改状态 // Future.microtask(() => _loadWingTags(value)); // } }, hideUnderline: true, ), ), ], ); } Widget _buildFamilySearchSelect() { 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( border: Border.all(color: Colors.grey), borderRadius: BorderRadius.circular(8), ), child: VberSearchSelect( searchApi: ({required dynamic queryParams}) async { final result = await apis.breeding.queryApi.queryPageFamilys( queryParams, ); return {'rows': result.rows, 'total': result.total}; }, converter: (FamilyModel data) { return SelectOption( label: data.familyNum, value: data.id.toString(), extra: data, ); }, value: _familyId, hint: '家系号', onChanged: (String? value) { setState(() { _familyId = value; }); }, hideUnderline: true, ), ), ], ); } Widget _buildRfidSection() { return VberRfidField( rfids: _rfids, onRfidsScanned: (List scannedRfids) { // 过滤出未存在的RFID final newRfids = scannedRfids .where((rfid) => !_rfids.contains(rfid.uid)) .toList(); if (newRfids.isNotEmpty) { setState(() { // 将新的RFID添加到列表中 for (var rfid in newRfids) { _rfids.insert(0, rfid.uid); } }); ToastUtil.success("新增 ${newRfids.length} 枚电子编号"); // if (newRfids.length == scannedRfids.length) { // // 全都是新添加的 // ToastUtil.success("成功添加 ${newRfids.length} 枚新的电子编号"); // } else { // // 部分是重复的 // ToastUtil.info("新增 ${newRfids.length} 枚电子编号"); // // ,${scannedRfids.length - newRfids.length} 枚已存在 // } } else { // 所有RFID都已存在 ToastUtil.info("电子编号已存在"); } }, multiple: true, label: '电子编号', multiplePlaceholder: '未识别', multipleFormat: '已识别 %d 枚电子编号', ); } // 移除指定索引的电子编号 void _removeRfid(int index) { setState(() { _rfids.removeAt(index); }); } // 清空所有已识别的电子编号 void _clearRfids() { setState(() { _rfids.clear(); }); ToastUtil.info('已清空所有电子编号'); } // 提交数据 void _handleSubmit() { final data = _rfids.map((rfid) { return { 'rfid': rfid, 'batchNum': _batchNum, 'familyId': _familyId, 'date': DateTimeUtil.format(DateTime.now()), }; }).toList(); apis.breeding.submitApi .bindChicken(data) .then((_) { if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('批量绑定个体成功'), backgroundColor: Colors.green, ), ); // 提交后重置表单 setState(() { _rfids.clear(); }); } }) .catchError((err) { ToastUtil.error('批量绑定个体失败'); if (mounted && err != null) { String errorMessage = err.toString(); if (err is Exception) { errorMessage = err.toString(); } logger.e(errorMessage); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(errorMessage), backgroundColor: Colors.red, ), ); } }); } }