Files
AI-Health/health_app/lib/providers/conversation_history_provider.dart
MingNian 7a93237069 feat: AI 对话附件上下文解析 + 历史会话归档 + 多页面 UI 重构
- 后端: 新增 AttachmentContextBuilder 解析图片/PDF 摘要并拼入 LLM 上下文; ai_chat_endpoints 扩展附件接口; 新增 ReportAnalysisService
- 前端: 新增历史会话页与 conversation_history_provider; chat 链路支持附件展示与回放
- UI: 重构 medication_checkin / notification_center / profile / health_drawer 等多页面
- 配置: api_client baseUrl 适配当前 WiFi IP
2026-07-06 12:44:59 +08:00

86 lines
2.7 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 '../providers/auth_provider.dart';
import '../providers/chat_provider.dart';
/// 对话历史列表项
class ConversationListItem {
final String id;
final String? title;
final String? summary;
final int messageCount;
final DateTime updatedAt;
const ConversationListItem({
required this.id,
this.title,
this.summary,
required this.messageCount,
required this.updatedAt,
});
factory ConversationListItem.fromJson(Map<String, dynamic> json) =>
ConversationListItem(
id: json['id']?.toString() ?? '',
title: json['title']?.toString(),
summary: json['summary']?.toString(),
messageCount: (json['messageCount'] as num?)?.toInt() ?? 0,
updatedAt: DateTime.tryParse(json['updatedAt']?.toString() ?? '') ??
DateTime.now(),
);
}
/// 对话历史 Notifier缓存列表提供刷新/删除/清空。
class ConversationHistoryNotifier
extends AsyncNotifier<List<ConversationListItem>> {
@override
Future<List<ConversationListItem>> build() => _fetch();
Future<List<ConversationListItem>> _fetch() async {
final api = ref.read(apiClientProvider);
final res = await api.get('/api/ai/conversations');
final raw = (res.data['data'] as List?) ?? const [];
return raw
.whereType<Map>()
.map((m) => ConversationListItem.fromJson(Map<String, dynamic>.from(m)))
.toList();
}
Future<void> refresh() async {
state = const AsyncValue.loading();
state = await AsyncValue.guard(_fetch);
}
/// 删除单条;先乐观更新 UI失败回滚。
Future<void> deleteOne(String id) async {
final previous = state.asData?.value ?? const <ConversationListItem>[];
state = AsyncValue.data(previous.where((e) => e.id != id).toList());
try {
final api = ref.read(apiClientProvider);
await api.delete('/api/ai/conversations/$id');
} catch (_) {
state = AsyncValue.data(previous);
rethrow;
}
// 同步清掉当前 chat state如果删的就是当前会话
final chat = ref.read(chatProvider);
if (chat.conversationId == id) {
ref.read(chatProvider.notifier).resetSession();
}
}
/// 一键清空当前用户的全部对话。
Future<int> clearAll() async {
final api = ref.read(apiClientProvider);
final res = await api.delete('/api/ai/conversations');
state = const AsyncValue.data([]);
ref.read(chatProvider.notifier).resetSession();
final deleted = res.data['data']?['deleted'];
return deleted is num ? deleted.toInt() : 0;
}
}
final conversationHistoryProvider = AsyncNotifierProvider<
ConversationHistoryNotifier, List<ConversationListItem>>(
ConversationHistoryNotifier.new,
);