fix: 7处修复 - 溢出/黑屏/趋势图/欢迎卡片/抽屉
This commit is contained in:
@@ -20,17 +20,23 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
bool _taskCardsExpanded = true;
|
||||
double _lastScrollOffset = 0;
|
||||
DateTime? _lastCollapseTime;
|
||||
bool _medicationTaken = false;
|
||||
bool _exerciseDone = false;
|
||||
final Set<ActiveAgent> _welcomedAgents = {};
|
||||
|
||||
static final _mockFollowUps = [
|
||||
{'hospital': '协和医院', 'department': '心内科', 'date': DateTime.now().add(const Duration(days: 2)), 'type': '复查'},
|
||||
{'hospital': '人民医院', 'department': '心内科', 'date': DateTime.now().add(const Duration(days: 3)), 'type': '复诊'},
|
||||
];
|
||||
|
||||
@override void initState() { super.initState(); _scrollCtrl.addListener(_onScroll); }
|
||||
@override void initState() { super.initState(); _scrollCtrl.addListener(_onScroll); _textCtrl.addListener(_onTextChange); }
|
||||
@override void dispose() { _textCtrl.dispose(); _scrollCtrl.dispose(); super.dispose(); }
|
||||
|
||||
void _onTextChange() {
|
||||
if (_textCtrl.text.isNotEmpty && _taskCardsExpanded) {
|
||||
setState(() => _taskCardsExpanded = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _onScroll() {
|
||||
if (!_scrollCtrl.hasClients) return;
|
||||
final offset = _scrollCtrl.offset;
|
||||
@@ -51,6 +57,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
final text = _textCtrl.text.trim();
|
||||
if (text.isEmpty) return;
|
||||
_textCtrl.clear();
|
||||
setState(() => _taskCardsExpanded = false);
|
||||
ref.read(chatProvider.notifier).sendMessage(text);
|
||||
}
|
||||
|
||||
@@ -64,7 +71,6 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
drawer: const HealthDrawer(),
|
||||
backgroundColor: const Color(0xFFF8F7FF),
|
||||
body: SafeArea(
|
||||
bottom: false,
|
||||
child: Column(children: [
|
||||
// ── 顶部栏 ──
|
||||
_buildHeader(user),
|
||||
@@ -75,14 +81,8 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
// ── 聊天区域(弹性填充剩余空间) ──
|
||||
Expanded(child: ChatMessagesView(scrollCtrl: _scrollCtrl, messages: chatState.messages)),
|
||||
|
||||
// ── 智能体选择器(常驻显示) ──
|
||||
_buildAgentBar(selectedAgent),
|
||||
|
||||
// ── 选中智能体的操作面板 ──
|
||||
if (selectedAgent != null) _buildAgentPanel(context, selectedAgent),
|
||||
|
||||
// ── 输入框 ──
|
||||
_buildInputBar(context),
|
||||
// ── 底部合并区:智能体栏 + 操作面板 + 输入框(固定高度) ──
|
||||
_buildBottomBar(context, selectedAgent),
|
||||
]),
|
||||
),
|
||||
);
|
||||
@@ -134,18 +134,15 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
return GestureDetector(
|
||||
onTap: () => setState(() => _taskCardsExpanded = true),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(8), blurRadius: 6, offset: const Offset(0, 1))]),
|
||||
child: Row(children: [
|
||||
Icon(Icons.assignment_turned_in_outlined, size: 18, color: const Color(0xFF635BFF)),
|
||||
const SizedBox(width: 8),
|
||||
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
const Spacer(),
|
||||
Text('点击展开', style: TextStyle(fontSize: 12, color: const Color(0xFF635BFF))),
|
||||
Icon(Icons.keyboard_arrow_right, size: 18, color: const Color(0xFF635BFF)),
|
||||
]),
|
||||
child: Center(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
const Text('今日任务', style: TextStyle(fontSize: 13, color: Color(0xFF635BFF))),
|
||||
const SizedBox(width: 4),
|
||||
const Text('▾', style: TextStyle(fontSize: 12, color: Color(0xFF635BFF))),
|
||||
]),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -160,8 +157,8 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
const Spacer(),
|
||||
GestureDetector(onTap: () => setState(() => _taskCardsExpanded = false), child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
Text('收起', style: TextStyle(fontSize: 12, color: const Color(0xFF999999))),
|
||||
Icon(Icons.keyboard_arrow_up, size: 18, color: const Color(0xFF999999)),
|
||||
const Text('收起', style: TextStyle(fontSize: 12, color: Color(0xFF999999))),
|
||||
const Text('∧', style: TextStyle(fontSize: 12, color: Color(0xFF999999))),
|
||||
])),
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
@@ -355,7 +352,6 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
|
||||
void _handleMedicationCheck() async {
|
||||
await ref.read(medicationServiceProvider).confirm('');
|
||||
setState(() => _medicationTaken = true);
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已记录服药 ✅'), backgroundColor: Color(0xFF635BFF)));
|
||||
}
|
||||
@@ -373,7 +369,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
|
||||
Widget _buildAgentBar(ActiveAgent? selected) {
|
||||
return Container(
|
||||
height: 44,
|
||||
height: 36,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12),
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
@@ -385,21 +381,27 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final notifier = ref.read(selectedAgentProvider.notifier);
|
||||
notifier.select(isActive ? null : agent);
|
||||
// 切换智能体时清空聊天
|
||||
if (!isActive) ref.read(chatProvider.notifier).setAgent(agent);
|
||||
final newAgent = isActive ? null : agent;
|
||||
notifier.select(newAgent);
|
||||
if (newAgent != null) {
|
||||
ref.read(chatProvider.notifier).setAgent(newAgent);
|
||||
if (!_welcomedAgents.contains(newAgent)) {
|
||||
_welcomedAgents.add(newAgent);
|
||||
ref.read(chatProvider.notifier).insertAgentWelcome(newAgent);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||
decoration: BoxDecoration(
|
||||
color: isActive ? const Color(0xFF635BFF) : Colors.white,
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
border: Border.all(color: isActive ? const Color(0xFF635BFF) : const Color(0xFFE0E0E0)),
|
||||
),
|
||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||
Icon(icon, size: 14, color: isActive ? Colors.white : const Color(0xFF666666)),
|
||||
const SizedBox(width: 4),
|
||||
Text(label, style: TextStyle(fontSize: 12, fontWeight: isActive ? FontWeight.w600 : FontWeight.w500, color: isActive ? Colors.white : const Color(0xFF666666))),
|
||||
Icon(icon, size: 13, color: isActive ? Colors.white : const Color(0xFF666666)),
|
||||
const SizedBox(width: 3),
|
||||
Text(label, style: TextStyle(fontSize: 11, fontWeight: isActive ? FontWeight.w600 : FontWeight.w500, color: isActive ? Colors.white : const Color(0xFF666666))),
|
||||
]),
|
||||
),
|
||||
);
|
||||
@@ -408,27 +410,52 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
);
|
||||
}
|
||||
|
||||
// ═════════════════════ 智能体操作面板(选中后显示) ═════════════════════
|
||||
// ═════════════════════ 底部合并区:智能体栏 + 操作面板 + 输入框 ═════════════════════
|
||||
|
||||
Widget _buildAgentPanel(BuildContext context, ActiveAgent agent) {
|
||||
Widget _buildBottomBar(BuildContext context, ActiveAgent? selectedAgent) {
|
||||
return Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
// 智能体胶囊栏(常驻,高度36)
|
||||
_buildAgentBar(selectedAgent),
|
||||
|
||||
// 选中智能体的操作面板(紧凑版)
|
||||
if (selectedAgent != null) _buildCompactAgentPanel(selectedAgent),
|
||||
|
||||
// 输入框(紧凑)
|
||||
_buildCompactInputBar(context),
|
||||
]);
|
||||
}
|
||||
|
||||
Widget _buildCompactAgentPanel(ActiveAgent agent) {
|
||||
final titles = {ActiveAgent.consultation: 'AI 问诊', ActiveAgent.health: '记数据', ActiveAgent.diet: '拍饮食', ActiveAgent.medication: '药管家', ActiveAgent.report: '看报告', ActiveAgent.exercise: '运动计划'};
|
||||
final tips = {ActiveAgent.consultation: '或直接对我说你的症状', ActiveAgent.health: '或直接对我说:"血压 135/85"', ActiveAgent.diet: '或直接对我说:"中午吃了牛肉面"', ActiveAgent.medication: '或直接对我说:"医生让我吃阿托伐他汀 20mg"', ActiveAgent.report: '或直接上传报告图片', ActiveAgent.exercise: '或直接对我说:"每周一三五散步 30 分钟"'};
|
||||
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||
decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: const Color(0xFFEEEEEE)))),
|
||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||
Row(children: [
|
||||
Text(titles[agent] ?? '', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
Text(titles[agent] ?? '', style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||
const SizedBox(width: 6),
|
||||
Expanded(child: Text(tips[agent] ?? '', style: TextStyle(fontSize: 11, color: Colors.grey[500]))),
|
||||
GestureDetector(onTap: () => ref.read(selectedAgentProvider.notifier).select(null), child: Icon(Icons.close, size: 18, color: Colors.grey[400])),
|
||||
Expanded(child: Text(tips[agent] ?? '', style: TextStyle(fontSize: 10, color: Colors.grey[500]))),
|
||||
GestureDetector(onTap: () => ref.read(selectedAgentProvider.notifier).select(null), child: Icon(Icons.close, size: 16, color: Colors.grey[400])),
|
||||
]),
|
||||
const SizedBox(height: 8),
|
||||
const SizedBox(height: 4),
|
||||
SingleChildScrollView(scrollDirection: Axis.horizontal, child: Row(children: _getAgentButtons(agent))),
|
||||
]));
|
||||
}
|
||||
|
||||
Widget _buildCompactInputBar(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||
decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: const Color(0xFFEEEEEE)))),
|
||||
child: Row(children: [
|
||||
IconButton(icon: const Icon(Icons.attach_file, size: 20, color: Color(0xFF666666)), onPressed: () => _showAttachmentPicker(context), padding: const EdgeInsets.all(4)),
|
||||
Expanded(child: TextField(controller: _textCtrl, decoration: InputDecoration(hintText: '输入你想说的...', contentPadding: const EdgeInsets.symmetric(horizontal: 8), border: InputBorder.none, isDense: true, hintStyle: const TextStyle(fontSize: 13)), onSubmitted: (_) => _sendMessage())),
|
||||
IconButton(icon: const Icon(Icons.send, size: 20, color: Color(0xFF635BFF)), onPressed: _sendMessage, padding: const EdgeInsets.all(4)),
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
List<Widget> _getAgentButtons(ActiveAgent agent) {
|
||||
switch (agent) {
|
||||
case ActiveAgent.health: return [_agentBtn('录入血压', Icons.favorite), _agentBtn('录入血糖', Icons.bloodtype), _agentBtn('录入心率', Icons.monitor_heart), _agentBtn('录入血氧', Icons.air), _agentBtn('录入体重', Icons.monitor_weight)];
|
||||
@@ -480,15 +507,4 @@ class _HomePageState extends ConsumerState<HomePage> {
|
||||
])));
|
||||
}
|
||||
|
||||
Widget _buildInputBar(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6),
|
||||
decoration: BoxDecoration(color: Colors.white, border: Border(top: BorderSide(color: const Color(0xFFEEEEEE)))),
|
||||
child: Row(children: [
|
||||
IconButton(icon: const Icon(Icons.attach_file, size: 22, color: Color(0xFF666666)), onPressed: () => _showAttachmentPicker(context)),
|
||||
Expanded(child: TextField(controller: _textCtrl, decoration: InputDecoration(hintText: '输入你想说的...', contentPadding: const EdgeInsets.symmetric(horizontal: 10), border: InputBorder.none, isDense: true), onSubmitted: (_) => _sendMessage())),
|
||||
IconButton(icon: const Icon(Icons.send, size: 22, color: Color(0xFF635BFF)), onPressed: _sendMessage),
|
||||
]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user