import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/theme/app_theme.dart'; class InventoryCheckScreen extends ConsumerStatefulWidget { const InventoryCheckScreen({super.key}); @override ConsumerState createState() => _InventoryCheckScreenState(); } class _InventoryCheckScreenState extends ConsumerState { final _checkNoCtrl = TextEditingController(text: 'PD20260404001'); String _warehouse = '主仓库'; String _checkType = '全盘'; bool _submitting = false; // Mock inventory items for checking final List> _checkItems = [ { 'code': 'SP001', 'name': '茅台酒(飞天)53度500ml', 'unit': '瓶', 'systemQty': 286, 'actualQtyCtrl': TextEditingController(text: '286'), 'remark': TextEditingController(), }, { 'code': 'SP002', 'name': '五粮液(普五)52度500ml', 'unit': '瓶', 'systemQty': 152, 'actualQtyCtrl': TextEditingController(text: '150'), 'remark': TextEditingController(text: '破损2瓶'), }, { 'code': 'SP003', 'name': '洋河梦之蓝M6+ 45度500ml', 'unit': '瓶', 'systemQty': 88, 'actualQtyCtrl': TextEditingController(text: '88'), 'remark': TextEditingController(), }, { 'code': 'SP005', 'name': '泸州老窖(国窖1573)52度500ml', 'unit': '瓶', 'systemQty': 68, 'actualQtyCtrl': TextEditingController(text: '70'), 'remark': TextEditingController(text: '盘盈2瓶'), }, { 'code': 'SP006', 'name': '汾酒(青花30)53度500ml', 'unit': '瓶', 'systemQty': 45, 'actualQtyCtrl': TextEditingController(text: '45'), 'remark': TextEditingController(), }, { 'code': 'SP010', 'name': '青岛啤酒(经典)500ml', 'unit': '箱', 'systemQty': 35, 'actualQtyCtrl': TextEditingController(text: '35'), 'remark': TextEditingController(), }, ]; @override void dispose() { _checkNoCtrl.dispose(); for (final item in _checkItems) { (item['actualQtyCtrl'] as TextEditingController).dispose(); (item['remark'] as TextEditingController).dispose(); } super.dispose(); } int _getDiff(Map item) { final actual = int.tryParse( (item['actualQtyCtrl'] as TextEditingController).text) ?? 0; return actual - (item['systemQty'] as int); } Future _submit() async { setState(() => _submitting = true); await Future.delayed(const Duration(milliseconds: 800)); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('盘点单已提交,待审核'), backgroundColor: AppTheme.success, ), ); context.go('/inventory'); } if (mounted) setState(() => _submitting = false); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.background, body: Column( children: [ // Header Container( height: 52, color: AppTheme.surface, padding: const EdgeInsets.symmetric(horizontal: 16), child: Row( children: [ IconButton( icon: const Icon(Icons.arrow_back, size: 20), onPressed: () => context.go('/inventory'), ), const SizedBox(width: 8), const Text('库存盘点', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600)), const Spacer(), OutlinedButton( onPressed: () {}, child: const Text('保存草稿'), ), const SizedBox(width: 8), ElevatedButton.icon( onPressed: _submitting ? null : _submit, icon: _submitting ? const SizedBox( width: 14, height: 14, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white)) : const Icon(Icons.check_circle_outline, size: 16), label: const Text('提交盘点'), ), const SizedBox(width: 8), OutlinedButton( onPressed: () => context.go('/inventory'), child: const Text('取消'), ), ], ), ), const Divider(height: 1), Expanded( child: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( children: [ // Basic info Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Text('盘点基本信息', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.primaryDark)), const SizedBox(height: 16), Wrap( spacing: 16, runSpacing: 16, children: [ _InfoField( label: '盘点单号', child: TextFormField( controller: _checkNoCtrl, readOnly: true, style: const TextStyle( fontFamily: 'monospace'), decoration: const InputDecoration(), ), ), _InfoField( label: '盘点仓库', child: DropdownButtonFormField( value: _warehouse, items: ['主仓库', '副仓库', '全部仓库'] .map((s) => DropdownMenuItem( value: s, child: Text(s, style: const TextStyle( fontSize: 13)))) .toList(), onChanged: (v) => setState(() => _warehouse = v!), decoration: const InputDecoration(), ), ), _InfoField( label: '盘点类型', child: DropdownButtonFormField( value: _checkType, items: ['全盘', '抽盘', '循环盘点'] .map((s) => DropdownMenuItem( value: s, child: Text(s, style: const TextStyle( fontSize: 13)))) .toList(), onChanged: (v) => setState(() => _checkType = v!), decoration: const InputDecoration(), ), ), _InfoField( label: '盘点日期', child: InputDecorator( decoration: const InputDecoration(), child: Text( '2026-04-04', style: const TextStyle(fontSize: 13), ), ), ), ], ), ], ), ), ), const SizedBox(height: 12), // Check items table Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ const Text('盘点明细', style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: AppTheme.primaryDark)), const SizedBox(width: 12), Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2), decoration: BoxDecoration( color: AppTheme.accent.withOpacity(0.1), borderRadius: BorderRadius.circular(3), ), child: Text( '差异 ${_checkItems.where((i) => _getDiff(i) != 0).length} 项', style: const TextStyle( fontSize: 12, color: AppTheme.accent), ), ), ], ), const SizedBox(height: 12), // Table Table( columnWidths: const { 0: FixedColumnWidth(36), 1: FixedColumnWidth(80), 2: FlexColumnWidth(3), 3: FixedColumnWidth(50), 4: FixedColumnWidth(80), 5: FixedColumnWidth(120), 6: FixedColumnWidth(80), 7: FlexColumnWidth(2), }, children: [ TableRow( decoration: const BoxDecoration( color: Color(0xFFF0F4FF)), children: [ '序号', '商品编码', '商品名称', '单位', '账面数量', '实际数量', '差异', '备注', ] .map((h) => Padding( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 10), child: Text(h, style: const TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: AppTheme .primaryDark)), )) .toList(), ), ...List.generate( _checkItems.length, (i) => _buildCheckRow(i)), ], ), const Divider(height: 1), // Summary Padding( padding: const EdgeInsets.only(top: 12), child: Row( children: [ _SummaryItem( label: '盘点商品', value: '${_checkItems.length}种', color: AppTheme.primary, ), const SizedBox(width: 24), _SummaryItem( label: '盘盈', value: '${_checkItems.where((i) => _getDiff(i) > 0).length}种', color: AppTheme.success, ), const SizedBox(width: 24), _SummaryItem( label: '盘亏', value: '${_checkItems.where((i) => _getDiff(i) < 0).length}种', color: AppTheme.danger, ), const SizedBox(width: 24), _SummaryItem( label: '相符', value: '${_checkItems.where((i) => _getDiff(i) == 0).length}种', color: AppTheme.textSecondary, ), ], ), ), ], ), ), ), ], ), ), ), ], ), ); } TableRow _buildCheckRow(int index) { final item = _checkItems[index]; final diff = _getDiff(item); return TableRow( decoration: BoxDecoration( color: diff != 0 ? (diff > 0 ? AppTheme.success.withOpacity(0.04) : AppTheme.danger.withOpacity(0.04)) : (index.isEven ? Colors.white : const Color(0xFFFAFAFA)), ), children: [ Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text('${index + 1}', style: const TextStyle( fontSize: 13, color: AppTheme.textSecondary)), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text(item['code'] as String, style: const TextStyle( fontFamily: 'monospace', fontSize: 12, color: AppTheme.textSecondary)), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text(item['name'] as String, style: const TextStyle(fontSize: 13), overflow: TextOverflow.ellipsis), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text(item['unit'] as String, style: const TextStyle(fontSize: 13)), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text('${item['systemQty']}', style: const TextStyle(fontSize: 13)), ), Padding( padding: const EdgeInsets.all(4), child: TextFormField( controller: item['actualQtyCtrl'] as TextEditingController, decoration: const InputDecoration(), style: const TextStyle(fontSize: 13), keyboardType: TextInputType.number, inputFormatters: [FilteringTextInputFormatter.digitsOnly], onChanged: (_) => setState(() {}), ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 10), child: Text( diff == 0 ? '0' : (diff > 0 ? '+$diff' : '$diff'), style: TextStyle( fontSize: 13, fontWeight: FontWeight.w600, color: diff == 0 ? AppTheme.textSecondary : (diff > 0 ? AppTheme.success : AppTheme.danger), ), ), ), Padding( padding: const EdgeInsets.all(4), child: TextFormField( controller: item['remark'] as TextEditingController, decoration: const InputDecoration(hintText: '备注'), style: const TextStyle(fontSize: 13), ), ), ], ); } } class _InfoField extends StatelessWidget { final String label; final Widget child; const _InfoField({required this.label, required this.child}); @override Widget build(BuildContext context) { return SizedBox( width: 220, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(label, style: const TextStyle( fontSize: 13, color: AppTheme.textSecondary)), const SizedBox(height: 6), child, ], ), ); } } class _SummaryItem extends StatelessWidget { final String label; final String value; final Color color; const _SummaryItem( {required this.label, required this.value, required this.color}); @override Widget build(BuildContext context) { return Row( children: [ Text(label, style: const TextStyle( fontSize: 13, color: AppTheme.textSecondary)), const SizedBox(width: 4), Text(value, style: TextStyle( fontSize: 14, fontWeight: FontWeight.w600, color: color)), ], ); } }