diff --git a/health_app/lib/core/api_client.dart b/health_app/lib/core/api_client.dart index dd85bcd..d991994 100644 --- a/health_app/lib/core/api_client.dart +++ b/health_app/lib/core/api_client.dart @@ -3,7 +3,7 @@ import 'package:dio/dio.dart'; import 'local_database.dart'; /// API 基础地址 -const String baseUrl = 'http://10.4.231.53:5000'; +const String baseUrl = 'http://192.168.1.45:5000'; /// Dio HTTP 客户端封装——带 token 注入、401 自动刷新 class ApiClient { diff --git a/health_app/lib/pages/diet/diet_capture_page.dart b/health_app/lib/pages/diet/diet_capture_page.dart index 7be9db1..e5b3285 100644 --- a/health_app/lib/pages/diet/diet_capture_page.dart +++ b/health_app/lib/pages/diet/diet_capture_page.dart @@ -230,7 +230,7 @@ class DietCapturePage extends ConsumerStatefulWidget { class _DietCapturePageState extends ConsumerState { @override void initState() { super.initState(); - Future.microtask(() => ref.read(dietProvider.notifier).reset()); + // 不 reset — 图片由 home_page 传入,这里只做展示 } @override @@ -242,74 +242,12 @@ class _DietCapturePageState extends ConsumerState { title: const Text('拍饮食'), centerTitle: true, ), - body: state.imagePath == null ? _buildCaptureView(context, ref) : _buildResultView(context, ref), + body: state.imagePath == null + ? const Center(child: Text('请从首页拍摄或选择食物照片', style: TextStyle(color: Color(0xFF999999)))) + : _buildResultView(context, ref), ); } - Widget _buildCaptureView(BuildContext context, WidgetRef ref) { - return Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: 180, - height: 180, - decoration: BoxDecoration( - color: const Color(0xFFF0F2FF), - borderRadius: BorderRadius.circular(90), - border: Border.all(color: const Color(0xFF8B9CF7), width: 2), - ), - child: const Icon(Icons.camera_alt, size: 48, color: Color(0xFF8B9CF7)), - ), - const SizedBox(height: 24), - const Text('拍摄或上传您的餐食照片', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)), - const SizedBox(height: 8), - const Text('AI将识别食物并分析营养成分', style: TextStyle(fontSize: 14, color: Color(0xFF999999))), - const SizedBox(height: 40), - Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - _captureBtn(context, ref, Icons.camera_alt, '拍照', ImageSource.camera), - const SizedBox(width: 24), - _captureBtn(context, ref, Icons.photo_library, '相册', ImageSource.gallery), - ], - ), - ], - ), - ); - } - - Widget _captureBtn(BuildContext context, WidgetRef ref, IconData icon, String label, ImageSource source) { - return Column( - children: [ - Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: const Color(0xFFFEFEFF), - borderRadius: BorderRadius.circular(20), - boxShadow: [BoxShadow(color: const Color(0xFF8B9CF7).withAlpha(20), blurRadius: 8, offset: const Offset(0, 2))], - ), - child: IconButton( - icon: Icon(icon, size: 32, color: const Color(0xFF8B9CF7)), - onPressed: () => _pickImage(context, ref, source), - ), - ), - const SizedBox(height: 8), - Text(label, style: const TextStyle(fontSize: 14, color: Color(0xFF666666))), - ], - ); - } - - Future _pickImage(BuildContext context, WidgetRef ref, ImageSource source) async { - final picker = ImagePicker(); - final picked = await picker.pickImage(source: source, imageQuality: 80, maxWidth: 1024, maxHeight: 1024); - if (picked != null) { - ref.read(dietProvider.notifier).setImage(picked.path); - ref.read(dietProvider.notifier).analyzeImage(); - } - } - // ─────────── 设计常量(与项目整体色调一致)─────────── static const _kPrimary = AppTheme.primary; // #6C5CE7 static const _kPrimaryLight = AppTheme.primaryLight; // #EDEAFF diff --git a/health_app/lib/pages/home/home_page.dart b/health_app/lib/pages/home/home_page.dart index 65b1f26..3279085 100644 --- a/health_app/lib/pages/home/home_page.dart +++ b/health_app/lib/pages/home/home_page.dart @@ -6,6 +6,7 @@ import 'dart:io'; import '../../providers/auth_provider.dart'; import '../../providers/chat_provider.dart'; import '../../providers/data_providers.dart'; +import '../diet/diet_capture_page.dart'; import '../../core/navigation_provider.dart'; import '../../widgets/health_drawer.dart'; import 'widgets/chat_messages_view.dart'; @@ -53,6 +54,16 @@ class _HomePageState extends ConsumerState { } }); + ref.listen(dietActionProvider, (prev, next) { + if (next == 'pickFoodCamera') { + _pickFoodImage(ImageSource.camera); + ref.read(dietActionProvider.notifier).clear(); + } else if (next == 'pickFoodGallery') { + _pickFoodImage(ImageSource.gallery); + ref.read(dietActionProvider.notifier).clear(); + } + }); + return Scaffold( drawer: const HealthDrawer(), backgroundColor: const Color(0xFFF8F9FC), @@ -217,6 +228,17 @@ class _HomePageState extends ConsumerState { } } + Future _pickFoodImage(ImageSource source) async { + final picker = ImagePicker(); + final picked = await picker.pickImage(source: source, imageQuality: 80, maxWidth: 1024, maxHeight: 1024); + if (picked != null && mounted) { + ref.read(dietProvider.notifier).reset(); + ref.read(dietProvider.notifier).setImage(picked.path); + ref.read(dietProvider.notifier).analyzeImage(); + pushRoute(ref, 'dietCapture'); + } + } + void _showAttachmentPicker(BuildContext context) { showModalBottomSheet(context: context, builder: (ctx) => SafeArea(child: Wrap(children: [ ListTile(leading: const Icon(Icons.camera_alt), title: const Text('拍照'), onTap: () { Navigator.pop(ctx); _pickImage(ImageSource.camera); }), diff --git a/health_app/lib/pages/home/widgets/chat_messages_view.dart b/health_app/lib/pages/home/widgets/chat_messages_view.dart index a91d98b..73de979 100644 --- a/health_app/lib/pages/home/widgets/chat_messages_view.dart +++ b/health_app/lib/pages/home/widgets/chat_messages_view.dart @@ -182,6 +182,8 @@ class ChatMessagesView extends ConsumerWidget { onTap: () { if (a.label == '服药打卡') { _medicationCheckIn(ref, context); + } else if (a.action == 'pickFoodCamera' || a.action == 'pickFoodGallery') { + ref.read(dietActionProvider.notifier).trigger(a.action!); } else if (a.route != null) { if (a.route == 'camera' || a.route == 'gallery') { ref.read(cameraActionProvider.notifier).trigger(a.route!); @@ -1372,8 +1374,8 @@ final _agentActions = >{ _AgentAction(label: '查看趋势', icon: Icons.trending_up, isWide: true, route: 'trend'), ], ActiveAgent.diet: [ - _AgentAction(label: '拍照识别', icon: Icons.camera_alt_outlined, isWide: true, route: 'dietCapture'), - _AgentAction(label: '上传照片', icon: Icons.photo_library_outlined, isWide: true, route: 'dietCapture'), + _AgentAction(label: '拍照识别', icon: Icons.camera_alt_outlined, isWide: true, action: 'pickFoodCamera'), + _AgentAction(label: '上传照片', icon: Icons.photo_library_outlined, isWide: true, action: 'pickFoodGallery'), ], ActiveAgent.medication: [ _AgentAction(label: '用药管理', icon: Icons.medication_liquid_outlined, isWide: true, route: 'medications'), diff --git a/health_app/lib/providers/data_providers.dart b/health_app/lib/providers/data_providers.dart index deb680f..012fc62 100644 --- a/health_app/lib/providers/data_providers.dart +++ b/health_app/lib/providers/data_providers.dart @@ -124,3 +124,12 @@ class CameraActionNotifier extends Notifier { void trigger(String action) => state = action; void clear() => state = null; } + +/// 拍饮食动作触发(不用跳多余页面) +final dietActionProvider = NotifierProvider(DietActionNotifier.new); + +class DietActionNotifier extends Notifier { + @override String? build() => null; + void trigger(String action) => state = action; + void clear() => state = null; +}