feat: UI清爽紫蓝风全面改造 + 对话卡片重构 + 配色体系升级

- 新增 AppColors 统一配色方案(清爽紫蓝,参考蚂蚁阿福风格)
- 新增 common_widgets(GradientBorderButton / CardActionButton / IconBox)
- AgentWelcomeCard 美化:渐变 header + AI标签 + 核心功能区 + 快捷操作区
- DataConfirmCard 统一:三合一(健康/药品/运动),可编辑字段列表
- 删除死代码:medicationConfirm/dietAnalysis/reportAnalysis/quickOptions 卡片
- 删除死路由:doctors/profileEdit/editProfile
- AI 对话去除 Markdown 符号(_stripMd),统一行间距 1.5
- 逐字淡入动画修复:key 改用 stableId 避免重复触发
- 健康概览时间修复:前端发送 UTC 避免时区歧义
- PG 数据目录迁入项目 backend/pgdata/,加入 .gitignore
- 新增欧姆龙血压计实施方案文档
This commit is contained in:
MingNian
2026-06-09 17:04:11 +08:00
parent 5f8964e03f
commit f01fc9268d
14 changed files with 1228 additions and 866 deletions

View File

@@ -7,108 +7,6 @@ import '../../core/navigation_provider.dart';
import '../../providers/data_providers.dart';
import '../../providers/consultation_provider.dart';
/// 医生列表页
class DoctorListPage extends ConsumerWidget {
const DoctorListPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
final doctors = ref.watch(doctorListProvider);
return Scaffold(
appBar: AppBar(title: const Text('选择医生')),
body: doctors.when(
data: (list) {
if (list.isEmpty) {
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Icon(Icons.person_search, size: 64, color: Colors.grey[300]),
const SizedBox(height: 12),
Text('暂无可用医生', style: Theme.of(context).textTheme.bodyMedium),
],
),
);
}
return SizedBox(
height: 330,
child: ListView.builder(
scrollDirection: Axis.horizontal,
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12),
itemCount: list.length,
itemBuilder: (ctx, i) {
final d = list[i];
return Container(
width: 155,
margin: const EdgeInsets.symmetric(horizontal: 5),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(20),
boxShadow: [
BoxShadow(color: AppTheme.primary.withAlpha(15), blurRadius: 12, offset: const Offset(0, 4))
],
),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
CircleAvatar(
radius: 28,
backgroundColor: AppTheme.primaryLight,
child: Text(
(d['name'] as String?)?.isNotEmpty == true ? d['name']![0] : '?',
style: const TextStyle(fontSize: 25, fontWeight: FontWeight.w600, color: AppTheme.primaryLight),
),
),
const SizedBox(height: 10),
Container(
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(
color: AppTheme.primaryLight,
borderRadius: BorderRadius.circular(6),
),
child: Text(d['title'] ?? '', style: const TextStyle(fontSize: 15, color: AppTheme.primaryLight, fontWeight: FontWeight.w500)),
),
const SizedBox(height: 6),
Text(d['department'] ?? '', style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Color(0xFF333333))),
const SizedBox(height: 8),
Text(d['introduction'] ?? '',
style: const TextStyle(fontSize: 15, color: Color(0xFF888888), height: 1.4),
maxLines: 4,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center),
const SizedBox(height: 14),
SizedBox(
width: double.infinity,
height: 34,
child: ElevatedButton(
onPressed: () => pushRoute(ref, 'consultation', params: {'id': d['id']?.toString() ?? ''}),
style: ElevatedButton.styleFrom(
backgroundColor: AppTheme.primary,
foregroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)),
padding: EdgeInsets.zero,
),
child: const Text('立即咨询', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
),
),
],
),
),
);
},
),
);
},
loading: () => const Center(child: CircularProgressIndicator()),
error: (_, _) => Center(
child: Text('加载失败', style: Theme.of(context).textTheme.bodyMedium),
),
),
);
}
}
/// 问诊对话页 — 完整的 AI 分身聊天界面
class DoctorChatPage extends ConsumerStatefulWidget {
final String id;