Files
AI-Health/health_app/lib/providers/data_providers.dart
MingNian 714adc2d51 fix: diet capture flow - 去掉多余页面,点击直接拍照
- 点击"拍照识别/上传照片"直接打开相机/相册,不再跳转多余选择页
- DietCapturePage 去掉重复的拍照按钮,只保留分析结果展示
- 新增 dietActionProvider 处理拍饮食触发
- 修复 initState reset 导致结果页被清空的 bug
- 修复 IP 地址恢复问题
2026-06-08 14:39:45 +08:00

136 lines
4.5 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'auth_provider.dart';
import '../services/health_service.dart';
final exerciseServiceProvider = Provider<ExerciseService>((ref) {
return ExerciseService(ref.watch(apiClientProvider));
});
/// 健康数据服务
final healthServiceProvider = Provider<HealthService>((ref) {
return HealthService(ref.watch(apiClientProvider));
});
final userServiceProvider = Provider<UserService>((ref) {
return UserService(ref.watch(apiClientProvider));
});
final medicationServiceProvider = Provider<MedicationService>((ref) {
return MedicationService(ref.watch(apiClientProvider));
});
final dietServiceProvider = Provider<DietService>((ref) {
return DietService(ref.watch(apiClientProvider));
});
final followUpServiceProvider = Provider<FollowUpService>((ref) {
return FollowUpService(ref.watch(apiClientProvider));
});
final consultationServiceProvider = Provider<ConsultationService>((ref) {
return ConsultationService(ref.watch(apiClientProvider));
});
/// 最新健康数据 Provider
final latestHealthProvider = FutureProvider<Map<String, dynamic>>((ref) async {
final service = ref.watch(healthServiceProvider);
return service.getLatest();
});
/// AI 录入数据后调用,刷新侧边栏
void refreshHealthData(WidgetRef ref) {
ref.invalidate(latestHealthProvider);
ref.invalidate(medicationListProvider);
}
/// 用药列表 Provider
final medicationListProvider = FutureProvider<List<Map<String, dynamic>>>((ref) async {
final service = ref.watch(medicationServiceProvider);
return service.getList();
});
final medicationReminderProvider = FutureProvider<List<Map<String, dynamic>>>((ref) async {
final service = ref.watch(medicationServiceProvider);
return service.getReminders();
});
/// 医生列表 Provider
final doctorListProvider = FutureProvider<List<Map<String, dynamic>>>((ref) async {
final service = ref.watch(consultationServiceProvider);
try {
return await service.getDoctors().timeout(const Duration(seconds: 8));
} catch (_) {
return _fallbackDoctors;
}
});
const _fallbackDoctors = [
{
'id': '468b82e2-d95a-4436-bff6-a50eecf99a66',
'name': '张明',
'title': '主任医师',
'department': '心脏康复科',
'introduction': '擅长冠心病、高血压术后管理20年临床经验',
},
{
'id': 'd4148733-b538-4398-af17-0c7592fc0c2d',
'name': '李芳',
'title': '副主任医师',
'department': '营养科',
'introduction': '擅长糖尿病、甲状腺疾病管理15年临床经验',
},
{
'id': 'ef0953c9-eb63-4d03-b6d7-050a1897d4a3',
'name': '王建国',
'title': '主任医师',
'department': '心血管内科',
'introduction': '擅长术后营养指导、饮食方案制定10年临床经验',
},
];
/// 问诊配额 Provider
final consultationQuotaProvider = FutureProvider<Map<String, dynamic>>((ref) async {
final service = ref.watch(consultationServiceProvider);
return service.getQuota();
});
/// 当前运动计划 Provider
final currentExercisePlanProvider = FutureProvider<Map<String, dynamic>?>((ref) async {
final service = ref.watch(exerciseServiceProvider);
try {
return await service.getCurrentPlan().timeout(const Duration(seconds: 8));
} catch (_) {
final today = DateTime.now();
final monday = today.subtract(Duration(days: today.weekday - 1));
return {
'weekStartDate': '${monday.year}-${monday.month.toString().padLeft(2, '0')}-${monday.day.toString().padLeft(2, '0')}',
'items': List.generate(7, (i) => {
'id': 'local_$i',
'dayOfWeek': i, // matches C# DayOfWeek: 0=Sun, 1=Mon, ..., 6=Sat
'exerciseType': i == 1 || i == 6 ? '休息' : '散步',
'durationMinutes': i == 1 || i == 6 ? 0 : 30,
'isRestDay': i == 1 || i == 6,
'isCompleted': false,
}),
};
}
});
/// 拍照/相册直接触发(无需跳转页面)
final cameraActionProvider = NotifierProvider<CameraActionNotifier, String?>(CameraActionNotifier.new);
class CameraActionNotifier extends Notifier<String?> {
@override String? build() => null;
void trigger(String action) => state = action;
void clear() => state = null;
}
/// 拍饮食动作触发(不用跳多余页面)
final dietActionProvider = NotifierProvider<DietActionNotifier, String?>(DietActionNotifier.new);
class DietActionNotifier extends Notifier<String?> {
@override String? build() => null;
void trigger(String action) => state = action;
void clear() => state = null;
}