import 'package:flutter/material.dart'; import 'package:chicken_farm/components/vb_app_bar.dart'; import 'package:chicken_farm/modes/experiment/sample/sample.dart'; import 'package:chicken_farm/modes/experiment/sample/sample_flow_log.dart'; import 'package:chicken_farm/apis/experiment/_sample.dart'; import 'package:chicken_farm/core/utils/logger.dart'; import 'package:chicken_farm/core/utils/datetime_util.dart'; class SampleDetailPage extends StatefulWidget { final String id; const SampleDetailPage({super.key, required this.id}); @override State createState() => _SampleDetailPageState(); } class _SampleDetailPageState extends State { SampleModel? _sample; List _flowLogs = []; bool _isLoading = true; @override void initState() { super.initState(); // 将 _loadSampleData 调用推迟到下一帧,避免在构建过程中修改状态 WidgetsBinding.instance.addPostFrameCallback((_) { _loadSampleData(); }); } Future _loadSampleData() async { try { final sampleFuture = SampleApi().querySample(widget.id); final flowLogsFuture = SampleApi().queryFlowLogs(widget.id); final results = await Future.wait([sampleFuture, flowLogsFuture]); setState(() { _sample = results[0] as SampleModel; _flowLogs = results[1] as List; _isLoading = false; }); } catch (e, stackTrace) { logger.e('加载样品详情失败: $e, error: e, stackTrace: $stackTrace'); setState(() { _isLoading = false; }); } } @override Widget build(BuildContext context) { return Scaffold( appBar: const VberAppBar(title: '样品详情', showLeftButton: true), body: _buildBody(), ); } Widget _buildBody() { if (_isLoading) { return const Center(child: CircularProgressIndicator()); } if (_sample == null) { return const Center( child: Text( '无法加载样品信息', style: TextStyle(fontSize: 16, color: Colors.grey), ), ); } return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ _buildSampleInfo(), const Divider(), _buildFlowLogsTitle(), _buildFlowLogsList(), ], ), ); } Widget _buildSampleInfo() { return Container( width: double.infinity, padding: const EdgeInsets.all(16.0), child: Card( child: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( _sample!.sampleName, style: Theme.of(context).textTheme.titleLarge, ), Chip( label: Text( _getSampleStatusText(_sample!.sampleStatus), style: TextStyle( color: _getSampleStatusColor(_sample!.sampleStatus), ), ), ), ], ), const SizedBox(height: 16), _buildInfoRow('样品编号', _sample!.id.toString()), _buildInfoRow('样品类型', _getSampleTypeText(_sample!.sampleType)), _buildInfoRow('取样批次', _sample!.batchNum), _buildInfoRow('取样翅号', _sample!.wingTagNum), _buildInfoRow( '取样时间', DateTimeUtil.toStandardString(_sample!.sampleTime), ), _buildInfoRow('取样人', _sample!.createByName), const SizedBox(height: 8), Text('样品描述: ${_sample!.description}'), ], ), ), ), ); } Widget _buildInfoRow(String label, String value) { return Padding( padding: const EdgeInsets.symmetric(vertical: 4.0), child: Row( children: [ SizedBox( width: 80, child: Text( '$label:', style: const TextStyle(fontWeight: FontWeight.bold), ), ), Expanded(child: Text(value)), ], ), ); } Widget _buildFlowLogsTitle() { return Padding( padding: const EdgeInsets.all(16.0), child: Text('流转记录', style: Theme.of(context).textTheme.titleLarge), ); } Widget _buildFlowLogsList() { if (_flowLogs.isEmpty) { return const Center( child: Padding( padding: EdgeInsets.all(32.0), child: Text( '暂无流转记录', style: TextStyle(fontSize: 16, color: Colors.grey), ), ), ); } return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), itemCount: _flowLogs.length, itemBuilder: (context, index) { final log = _flowLogs[index]; return _buildFlowLogItem(log); }, ); } Widget _buildFlowLogItem(SampleFlowLogModel log) { return Card( margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), child: ListTile( title: Text(log.handlerName), subtitle: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('查询时间: ${DateTimeUtil.toStandardString(log.handleTime)}'), ], ), ), ); } String _getSampleStatusText(int status) { switch (status) { case 0: return '待处理'; case 1: return '处理中'; case 2: return '已完成'; default: return '未知状态'; } } Color _getSampleStatusColor(int status) { switch (status) { case 0: return Colors.orange; case 1: return Colors.blue; case 2: return Colors.green; default: return Colors.grey; } } String _getSampleTypeText(int type) { switch (type) { case 1: return '血液样品'; case 2: return '组织样品'; case 3: return '粪便样品'; default: return '未知类型'; } } }