import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'widgets/manual_entry_tab.dart'; import 'widgets/ocr_tab.dart'; /// 记账页内部 Tab:0=手动记账 1=OCR识别 class AddTabNotifier extends Notifier { @override int build() => 0; void set(int index) => state = index; } final addTabProvider = NotifierProvider(AddTabNotifier.new); /// 记账页:手动记账 / OCR识别 双 Tab(复刻 uniApp pages/add/add.vue) class AddPage extends ConsumerWidget { const AddPage({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final tabIndex = ref.watch(addTabProvider); return Scaffold( appBar: AppBar(title: const Text('添加账单')), body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFFFE5CC), Color(0xFFFFD4A8), Color(0xFFFFC08A)], ), ), child: Column( children: [ const SizedBox(height: 12), _buildTabs(tabIndex, ref), Expanded( child: tabIndex == 0 ? const ManualEntryTab() : const OcrTab(), ), ], ), ), ); } Widget _buildTabs(int tabIndex, WidgetRef ref) { void setTab(int index) => ref.read(addTabProvider.notifier).set(index); return Container( margin: const EdgeInsets.symmetric(horizontal: 16), padding: const EdgeInsets.all(4), decoration: BoxDecoration( color: Colors.white.withValues(alpha: 0.9), borderRadius: BorderRadius.circular(14), border: Border.all(color: const Color(0xFFC8956E)), ), child: Row( children: [ _tab('手动记账', 0, tabIndex, setTab), _tab('OCR识别', 1, tabIndex, setTab), ], ), ); } Widget _tab(String text, int index, int tabIndex, void Function(int) setTab) { final active = tabIndex == index; return Expanded( child: GestureDetector( onTap: () => setTab(index), child: AnimatedContainer( duration: const Duration(milliseconds: 200), padding: const EdgeInsets.symmetric(vertical: 10), decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), gradient: active ? const LinearGradient(colors: [Color(0xFFC8956E), Color(0xFFF5D59E)]) : null, ), child: Center( child: Text( text, style: TextStyle( fontSize: 15, fontWeight: FontWeight.w600, color: active ? const Color(0xFF5D4037) : const Color(0xFF8D6E63), ), ), ), ), ), ); } }