fix: 任务卡片移入对话流 + 综合信息卡片分组修复
- 新增 taskCard 消息类型,作为对话第一条消息 - 今日任务卡片从独立区域移至聊天流内 - AgentWelcomeCard 从 metadata 读 agent 不再全局共享 - 切换胶囊不会影响已发过的卡片
This commit is contained in:
@@ -92,10 +92,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
// ── 顶部栏 ──
|
||||
_buildHeader(user),
|
||||
|
||||
// ── 今日任务(可折叠) ──
|
||||
_buildTaskCardsArea(),
|
||||
|
||||
// ── 聊天区域(弹性填充剩余空间) ──
|
||||
// ── 聊天区域(今日任务已移入对话流第一条消息) ──
|
||||
Expanded(child: ChatMessagesView(scrollCtrl: _scrollCtrl, messages: chatState.messages)),
|
||||
|
||||
// ── 底部合并区:智能体栏 + 操作面板 + 输入框(固定高度) ──
|
||||
|
||||
@@ -63,7 +63,10 @@ class ChatMessagesView extends ConsumerWidget {
|
||||
|
||||
switch (msg.type) {
|
||||
case MessageType.agentWelcome:
|
||||
return _buildAgentWelcomeCard(context, ref, msg, chatState.activeAgent);
|
||||
final storedAgent = _parseAgentFromName(msg.metadata?['agent'] as String?);
|
||||
return _buildAgentWelcomeCard(context, ref, msg, storedAgent);
|
||||
case MessageType.taskCard:
|
||||
return _buildTaskCardInChat(context, ref);
|
||||
case MessageType.dataConfirm:
|
||||
return _buildDataConfirmCard(context, msg);
|
||||
case MessageType.medicationConfirm:
|
||||
@@ -1254,4 +1257,69 @@ class _ExpandableAdviceState extends State<_ExpandableAdvice> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
static ActiveAgent _parseAgentFromName(String? name) {
|
||||
switch (name) {
|
||||
case 'consultation': return ActiveAgent.consultation;
|
||||
case 'health': return ActiveAgent.health;
|
||||
case 'diet': return ActiveAgent.diet;
|
||||
case 'medication': return ActiveAgent.medication;
|
||||
case 'report': return ActiveAgent.report;
|
||||
case 'exercise': return ActiveAgent.exercise;
|
||||
default: return ActiveAgent.default_;
|
||||
}
|
||||
}
|
||||
|
||||
Widget _buildTaskCardInChat(BuildContext context, WidgetRef ref) {
|
||||
final health = ref.watch(latestHealthProvider);
|
||||
return health.when(
|
||||
data: (data) => _taskCardBubble(context, ref, data),
|
||||
loading: () => _taskCardBubble(context, ref, {}),
|
||||
error: (_, __) => _taskCardBubble(context, ref, {}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _taskCardBubble(BuildContext context, WidgetRef ref, Map<String, dynamic> data) {
|
||||
final bp = data['BloodPressure'];
|
||||
final bpText = bp is Map ? '${bp['systolic'] ?? '--'}/${bp['diastolic'] ?? '--'}' : '--';
|
||||
final hr = data['HeartRate'];
|
||||
final hrText = hr is Map && hr['value'] != null ? '${hr['value']}' : '--';
|
||||
final gl = data['Glucose'];
|
||||
final glText = gl is Map && gl['value'] != null ? '${gl['value']}' : '--';
|
||||
final sp = data['SpO2'];
|
||||
final spText = sp is Map && sp['value'] != null ? '${sp['value']}' : '--';
|
||||
|
||||
return Container(
|
||||
margin: const EdgeInsets.only(bottom: 12),
|
||||
padding: const EdgeInsets.all(14),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))],
|
||||
),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||
Row(children: [
|
||||
Icon(Icons.today, size: 18, color: const Color(0xFF635BFF)),
|
||||
const SizedBox(width: 8),
|
||||
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||
_miniMetric('血压', bpText, Icons.favorite, ref),
|
||||
_miniMetric('心率', hrText, Icons.monitor_heart, ref),
|
||||
_miniMetric('血糖', glText, Icons.bloodtype, ref),
|
||||
_miniMetric('血氧', spText, Icons.air, ref),
|
||||
]),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _miniMetric(String label, String value, IconData icon, WidgetRef ref) {
|
||||
return Column(children: [
|
||||
Icon(icon, size: 20, color: const Color(0xFF635BFF)),
|
||||
const SizedBox(height: 4),
|
||||
Text(value, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))),
|
||||
Text(label, style: const TextStyle(fontSize: 10, color: Color(0xFF999999))),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user