feat: AI Agent 处理器扩展 + 服药打卡确认链路 + AI 气泡配色微调 + 数据刷新 providers 抽离 + 多端页面细节调整

This commit is contained in:
MingNian
2026-07-20 17:12:00 +08:00
parent 9cea41705e
commit 0cb5b8e85a
45 changed files with 1435 additions and 276 deletions

View File

@@ -12,3 +12,9 @@ final adminDoctorsRefreshSignalProvider =
final doctorFollowupsRefreshSignalProvider =
NotifierProvider<BackofficeRefreshSignal, int>(BackofficeRefreshSignal.new);
final doctorReportsRefreshSignalProvider =
NotifierProvider<BackofficeRefreshSignal, int>(BackofficeRefreshSignal.new);
final doctorDashboardRefreshSignalProvider =
NotifierProvider<BackofficeRefreshSignal, int>(BackofficeRefreshSignal.new);

View File

@@ -5,10 +5,27 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'auth_provider.dart';
import 'conversation_history_provider.dart';
import 'data_providers.dart';
import 'data_refresh_providers.dart';
import '../utils/sse_handler.dart';
enum MessageType { text, dataConfirm, agentWelcome, taskCard }
List<ChatMessage> prependTodayHealthCard(
List<ChatMessage> messages, {
DateTime? now,
}) {
return [
ChatMessage(
id: 'task_card',
role: 'assistant',
content: '',
createdAt: now ?? DateTime.now(),
type: MessageType.taskCard,
),
...messages,
];
}
class ChatMessage {
final String id;
final String role;
@@ -133,10 +150,9 @@ class ChatNotifier extends Notifier<ChatState> {
msgs[i].confirmed = true;
state = state.copyWith(messages: msgs);
ref.invalidate(medicationListProvider);
ref.invalidate(medicationReminderProvider);
ref.read(medicationDataRefreshSignalProvider.notifier).trigger();
ref.invalidate(latestHealthProvider);
ref.invalidate(currentExercisePlanProvider);
ref.read(exerciseDataRefreshSignalProvider.notifier).trigger();
return null;
}
@@ -161,18 +177,7 @@ class ChatNotifier extends Notifier<ChatState> {
void insertTaskCard() {
if (state.messages.any((m) => m.type == MessageType.taskCard)) return;
state = state.copyWith(
messages: [
ChatMessage(
id: 'task_card',
role: 'assistant',
content: '',
createdAt: DateTime.now(),
type: MessageType.taskCard,
),
...state.messages,
],
);
state = state.copyWith(messages: prependTodayHealthCard(state.messages));
}
Future<String?> loadConversation(String convId) async {
@@ -212,7 +217,7 @@ class ChatNotifier extends Notifier<ChatState> {
}).toList();
state = ChatState(
messages: messages,
messages: prependTodayHealthCard(messages),
conversationId: convId,
activeAgent: ActiveAgent.default_,
isViewingHistory: true,

View File

@@ -1,5 +1,6 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'auth_provider.dart';
import 'data_refresh_providers.dart';
import '../services/health_service.dart';
import '../services/admin_service.dart';
import '../services/in_app_notification_service.dart';
@@ -63,6 +64,7 @@ final medicationListProvider = FutureProvider<List<Map<String, dynamic>>>((
ref,
) async {
ref.watch(userSessionIdentityProvider);
ref.watch(medicationDataRefreshSignalProvider);
final service = ref.watch(medicationServiceProvider);
return service.getList();
});
@@ -71,6 +73,7 @@ final exercisePlansProvider = FutureProvider<List<Map<String, dynamic>>>((
ref,
) async {
ref.watch(userSessionIdentityProvider);
ref.watch(exerciseDataRefreshSignalProvider);
return ref.watch(exerciseServiceProvider).getPlans();
});
@@ -85,6 +88,7 @@ final dietRecordsProvider = FutureProvider<List<Map<String, dynamic>>>((
ref,
) async {
ref.watch(userSessionIdentityProvider);
ref.watch(dietDataRefreshSignalProvider);
return ref.watch(dietServiceProvider).getRecords();
});
@@ -92,6 +96,7 @@ final medicationReminderProvider = FutureProvider<List<Map<String, dynamic>>>((
ref,
) async {
ref.watch(userSessionIdentityProvider);
ref.watch(medicationDataRefreshSignalProvider);
final service = ref.watch(medicationServiceProvider);
return service.getReminders();
});
@@ -109,6 +114,7 @@ final currentExercisePlanProvider = FutureProvider<Map<String, dynamic>?>((
ref,
) async {
ref.watch(userSessionIdentityProvider);
ref.watch(exerciseDataRefreshSignalProvider);
final service = ref.watch(exerciseServiceProvider);
return service.getCurrentPlan().timeout(const Duration(seconds: 8));
});

View File

@@ -0,0 +1,18 @@
import 'package:flutter_riverpod/flutter_riverpod.dart';
class DataRefreshSignal extends Notifier<int> {
@override
int build() => 0;
void trigger() => state++;
}
final exerciseDataRefreshSignalProvider =
NotifierProvider<DataRefreshSignal, int>(DataRefreshSignal.new);
final medicationDataRefreshSignalProvider =
NotifierProvider<DataRefreshSignal, int>(DataRefreshSignal.new);
final dietDataRefreshSignalProvider = NotifierProvider<DataRefreshSignal, int>(
DataRefreshSignal.new,
);