import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../../providers/add_bill_provider.dart'; import '../../../providers/ocr_provider.dart'; import '../../../utils/date_util.dart'; import '../add_page.dart'; /// 单条 OCR 识别结果卡片:可折叠详情 + 「选择此条」填充手动表单 class OcrResultCard extends ConsumerWidget { final int index; final bool expanded; final VoidCallback onToggle; const OcrResultCard({ super.key, required this.index, required this.expanded, required this.onToggle, }); @override Widget build(BuildContext context, WidgetRef ref) { final state = ref.watch(ocrProvider); if (index >= state.results.length) return const SizedBox.shrink(); final result = state.results[index]; final isExpense = result.isExpense; return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(14), border: Border.all(color: const Color(0xFFE0C9A6)), ), child: Column( children: [ // 头部:序号 + 金额 + 置信度 + 展开 InkWell( onTap: onToggle, borderRadius: BorderRadius.circular(14), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), child: Row( children: [ Text( '#${index + 1}', style: const TextStyle(fontSize: 13, fontWeight: FontWeight.bold, color: Color(0xFF8D6E63)), ), const SizedBox(width: 12), Expanded( child: Text( '¥${result.absAmount.toStringAsFixed(2)}', style: TextStyle( fontSize: 17, fontWeight: FontWeight.bold, color: isExpense ? const Color(0xFFEF5350) : const Color(0xFF66BB6A), ), ), ), if (result.confidence != null) Padding( padding: const EdgeInsets.only(right: 8), child: Text( '置信度 ${(result.confidence! * 100).toStringAsFixed(1)}%', style: const TextStyle(fontSize: 12, color: Color(0xFFBCAAA4)), ), ), AnimatedRotation( turns: expanded ? 0.5 : 0, duration: const Duration(milliseconds: 200), child: const Icon(Icons.expand_more, color: Color(0xFF8D6E63)), ), ], ), ), ), // 详情 AnimatedCrossFade( duration: const Duration(milliseconds: 200), crossFadeState: expanded ? CrossFadeState.showSecond : CrossFadeState.showFirst, firstChild: const SizedBox(width: double.infinity), secondChild: Padding( padding: const EdgeInsets.fromLTRB(14, 0, 14, 12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Divider(height: 1, color: Color(0xFFF0E6D8)), const SizedBox(height: 8), _detailRow('类型', isExpense ? '支出' : '收入'), if (result.merchant != null && result.merchant!.isNotEmpty) _detailRow('商户', result.merchant!), if (result.date != null && result.date!.isNotEmpty) _detailRow('日期', parseBillDate(result.date)), const SizedBox(height: 10), SizedBox( width: double.infinity, height: 38, child: OutlinedButton( style: OutlinedButton.styleFrom( foregroundColor: const Color(0xFFC8956E), side: const BorderSide(color: Color(0xFFC8956E)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(19)), ), onPressed: () { ref.read(addBillFormProvider.notifier).fillFromOcr(result); // 切回手动记账 Tab 并清空 OCR 状态 ref.read(addTabProvider.notifier).set(0); ref.read(ocrProvider.notifier).clearImage(); }, child: const Text('选择此条', style: TextStyle(fontSize: 14, fontWeight: FontWeight.w600)), ), ), ], ), ), ), ], ), ); } Widget _detailRow(String label, String value) { return Padding( padding: const EdgeInsets.only(bottom: 4), child: Row( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox( width: 42, child: Text(label, style: const TextStyle(fontSize: 13, color: Color(0xFF8D6E63))), ), Expanded( child: Text(value, style: const TextStyle(fontSize: 13, color: Color(0xFF5D4037))), ), ], ), ); } }