- 点击"拍照识别/上传照片"直接打开相机/相册,不再跳转多余选择页 - DietCapturePage 去掉重复的拍照按钮,只保留分析结果展示 - 新增 dietActionProvider 处理拍饮食触发 - 修复 initState reset 导致结果页被清空的 bug - 修复 IP 地址恢复问题
136 lines
4.5 KiB
Dart
136 lines
4.5 KiB
Dart
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;
|
||
}
|