feat: 三端抽屉重构 + 配色系统更新 + 后台管理页精调 + 键盘抬起组件
## 抽屉重构 - admin_drawer / doctor_drawer / health_drawer 三端抽屉全部重做 - drawer_shell 增强 ## 配色系统 - app_colors / app_module_visuals / app_theme 更新 - app.dart 启动流程调整 ## 后台管理页 - admin_doctors_page 大幅重构(+251) - admin_home / doctor_dashboard / doctor_reports / doctor_home / doctor_followups / doctor_settings 精调 ## 患者端 - home_page / chat_messages_view / medication_list / notification_center / remaining_pages / exercise_plan / device / diet / consultation 微调 ## 新增 - keyboard_lift.dart: 键盘抬起处理组件 - AGENTS.md: agent 指引文档 ## 其他 - api_client IP 适配 - app_future_view 增强 - data_providers 调整 - secondary_page_visuals_test 更新
This commit is contained in:
@@ -213,11 +213,7 @@ class _HealthDashboard extends StatelessWidget {
|
||||
onTap: () => pushRoute(ref, 'trend'),
|
||||
),
|
||||
titleColor: Colors.white,
|
||||
backgroundGradient: const LinearGradient(
|
||||
begin: Alignment.topCenter,
|
||||
end: Alignment.bottomCenter,
|
||||
colors: [Color(0xFF89F7FE), Color(0xFF66A6FF)],
|
||||
),
|
||||
backgroundPainter: const _HealthDashboardBackgroundPainter(),
|
||||
child: latestHealth.when(
|
||||
data: (data) => _DashboardMetrics(data: data, ref: ref),
|
||||
loading: () => const SizedBox(
|
||||
@@ -392,7 +388,7 @@ class _NavigationSection extends StatelessWidget {
|
||||
colors: AppColors.medicationGradient.colors,
|
||||
),
|
||||
_NavItem(
|
||||
icon: LucideIcons.utensils,
|
||||
icon: AppModuleVisuals.diet.icon,
|
||||
title: '饮食',
|
||||
route: 'dietRecords',
|
||||
colors: AppColors.dietGradient.colors,
|
||||
@@ -476,6 +472,7 @@ class _NavTile extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDevice = item.route == 'devices';
|
||||
return InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: AppRadius.mdBorder,
|
||||
@@ -488,12 +485,16 @@ class _NavTile extends StatelessWidget {
|
||||
width: 48,
|
||||
height: 48,
|
||||
decoration: BoxDecoration(
|
||||
gradient: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: _colors,
|
||||
),
|
||||
color: isDevice ? AppColors.device : null,
|
||||
gradient: isDevice
|
||||
? null
|
||||
: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: _colors,
|
||||
),
|
||||
borderRadius: AppRadius.mdBorder,
|
||||
border: null,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: _colors.last.withValues(alpha: 0.10),
|
||||
@@ -567,60 +568,96 @@ class _Panel extends StatelessWidget {
|
||||
final String title;
|
||||
final Widget child;
|
||||
final Widget? trailing;
|
||||
final LinearGradient? backgroundGradient;
|
||||
final CustomPainter? backgroundPainter;
|
||||
final Color titleColor;
|
||||
const _Panel({
|
||||
required this.title,
|
||||
required this.child,
|
||||
this.trailing,
|
||||
this.backgroundGradient,
|
||||
this.backgroundPainter,
|
||||
this.titleColor = AppColors.textPrimary,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(14),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
decoration: BoxDecoration(
|
||||
gradient:
|
||||
backgroundGradient ??
|
||||
LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Colors.white.withValues(alpha: 0.92),
|
||||
const Color(0xFFF8F4FF).withValues(alpha: 0.84),
|
||||
],
|
||||
),
|
||||
color: backgroundPainter == null ? null : const Color(0xFFBAE6FD),
|
||||
gradient: backgroundPainter != null
|
||||
? null
|
||||
: LinearGradient(
|
||||
begin: Alignment.topLeft,
|
||||
end: Alignment.bottomRight,
|
||||
colors: [
|
||||
Colors.white.withValues(alpha: 0.92),
|
||||
const Color(0xFFF8F4FF).withValues(alpha: 0.84),
|
||||
],
|
||||
),
|
||||
borderRadius: AppRadius.xlBorder,
|
||||
boxShadow: AppShadows.soft,
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
child: CustomPaint(
|
||||
painter: backgroundPainter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(14),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: titleColor,
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: titleColor,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
?trailing,
|
||||
],
|
||||
),
|
||||
?trailing,
|
||||
const SizedBox(height: 12),
|
||||
child,
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
child,
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _HealthDashboardBackgroundPainter extends CustomPainter {
|
||||
const _HealthDashboardBackgroundPainter();
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final rect = Offset.zero & size;
|
||||
canvas.drawRect(rect, Paint()..color = const Color(0xFFBAE6FD));
|
||||
|
||||
void drawGlow(Alignment center, Color color) {
|
||||
final paint = Paint()
|
||||
..shader = RadialGradient(
|
||||
center: center,
|
||||
radius: 1,
|
||||
colors: [color, color.withValues(alpha: 0)],
|
||||
stops: const [0, 0.8],
|
||||
).createShader(rect);
|
||||
canvas.drawRect(rect, paint);
|
||||
}
|
||||
|
||||
drawGlow(Alignment.bottomRight, const Color(0xFF818CF8));
|
||||
drawGlow(const Alignment(0, 0.6), const Color(0xFF60A5FA));
|
||||
drawGlow(const Alignment(0.6, -0.6), const Color(0xFF6366F1));
|
||||
drawGlow(const Alignment(-0.6, -0.6), const Color(0xFF38BDF8));
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(_HealthDashboardBackgroundPainter oldDelegate) => false;
|
||||
}
|
||||
|
||||
class _TextAction extends StatelessWidget {
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
Reference in New Issue
Block a user