feat: UI全面改造 + 后端多项修复

【后端修复】
- 删除diet/consultation agent假工具声明
- 修复DayOfWeek实体注释
- 修复Vision API content序列化
- cleanup_service级联删除修复
- 用药提醒时区偏差修复
- 统一DateTime处理(UtcNow+8)
- 新增UTC DateTime JSON转换器

【前端UI重构】
- 配色体系全面更新(#8B5CF6淡紫+#F0ECFF背景)
- 登录页重设计
- 首页重设计(透明顶栏、渐变背景、胶囊输入区)
- 聊天卡片加白蓝边框、渐变标题
- 侧边栏重构(渐变背景、合并顶部、删除底部设置)
- 确认卡片可编辑字段恢复
- 所有子页面加返回按钮
- catch异常加日志
- 删除后refresh provider缓存
This commit is contained in:
MingNian
2026-06-10 18:27:38 +08:00
parent 3964cf2bcb
commit 63d2092c24
46 changed files with 2003 additions and 1431 deletions

View File

@@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:shadcn_ui/shadcn_ui.dart';
import 'app_colors.dart';
/// 健康管家 —— 蚂蚁阿福风格:紫蓝渐变 + 超大圆角 + 漂浮卡片
/// 健康管家 — 设计规范 v1.0:紫色系 + 干净白灰 + 12px圆角
class AppTheme {
AppTheme._();
@@ -11,8 +11,8 @@ class AppTheme {
static const Color primaryLight = AppColors.primaryLight;
static const Color primaryDark = AppColors.primaryDark;
static const Color primaryMid = AppColors.primaryMid;
static const Color accent = AppColors.accentCyan;
static const Color info = AppColors.accentCyan;
static const Color accent = AppColors.success;
static const Color info = AppColors.blueMeasure;
// ── 中性色 ──
static const Color bg = AppColors.background;
@@ -33,51 +33,51 @@ class AppTheme {
static const Color warning = AppColors.warning;
static const Color warningLight = AppColors.warningLight;
// ── 圆角(阿福风格:超大圆角)──
static const double rXs = 8;
static const double rSm = 12;
static const double rMd = 18;
static const double rLg = 24;
static const double rXl = 32;
// ── 圆角(规范12px 卡片)──
static const double rXs = 4;
static const double rSm = 8;
static const double rMd = 12;
static const double rLg = 16;
static const double rXl = 20;
static const double rPill = 999;
// ── 间距 ──
// ── 间距8px 网格)──
static const double sXs = 4;
static const double sSm = 8;
static const double sMd = 12;
static const double sLg = 16;
static const double sXl = 20;
static const double sXxl = 28;
static const double sXxl = 24;
// ── 阴影(淡紫柔和阴影)──
// ── 阴影(阴影)──
static BoxShadow get shadowCard => BoxShadow(
color: AppColors.primary.withOpacity(0.08),
blurRadius: 24,
offset: const Offset(0, 8),
color: Colors.black.withOpacity(0.06),
blurRadius: 8,
offset: const Offset(0, 2),
);
static BoxShadow get shadowLight => BoxShadow(
color: AppColors.primary.withOpacity(0.05),
blurRadius: 16,
offset: const Offset(0, 4),
color: Colors.black.withOpacity(0.04),
blurRadius: 6,
offset: const Offset(0, 1),
);
static BoxShadow get shadowElevated => BoxShadow(
color: AppColors.primary.withOpacity(0.15),
blurRadius: 32,
offset: const Offset(0, 10),
color: primary.withOpacity(0.08),
blurRadius: 12,
offset: const Offset(0, 4),
);
static BoxShadow get shadowButton => BoxShadow(
color: AppColors.primary.withOpacity(0.25),
blurRadius: 16,
offset: const Offset(0, 6),
color: primary.withOpacity(0.25),
blurRadius: 12,
offset: const Offset(0, 4),
);
// ── 智能体配色 ──
static const Map<String, Color> agentColors = {
'default': AppColors.primaryLight,
'default': Color(0xFFEDE9FE),
'consultation': Color(0xFFE0E7FF),
'health': Color(0xFFDCFCE7),
'health': Color(0xFFD1FAE5),
'diet': Color(0xFFFEF3C7),
'medication': Color(0xFFFCE7F3),
'medication': Color(0xFFFEE2E2),
'report': Color(0xFFDBEAFE),
'exercise': Color(0xFFEDE9FE),
};
@@ -94,70 +94,75 @@ class AppTheme {
onPrimary: Colors.white,
secondary: accent,
surface: surface,
background: bg,
brightness: Brightness.light,
),
scaffoldBackgroundColor: bg,
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
hoverColor: primaryLight.withOpacity(0.5),
hoverColor: primaryLight.withOpacity(0.3),
fontFamily: null,
appBarTheme: AppBarTheme(
backgroundColor: bg,
backgroundColor: surface,
foregroundColor: text,
elevation: 0,
centerTitle: false,
centerTitle: true,
scrolledUnderElevation: 0,
titleTextStyle: TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: text),
titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: text),
toolbarHeight: 44,
),
cardTheme: CardThemeData(
color: surface,
elevation: 0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rLg)),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rMd)),
margin: EdgeInsets.zero,
),
inputDecorationTheme: InputDecorationTheme(
filled: true,
fillColor: bgSoft,
contentPadding: const EdgeInsets.symmetric(horizontal: sLg, vertical: 16),
border: OutlineInputBorder(borderRadius: BorderRadius.circular(rMd), borderSide: BorderSide.none),
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(rMd), borderSide: BorderSide.none),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(rMd),
borderSide: const BorderSide(color: primary, width: 2),
contentPadding: const EdgeInsets.symmetric(horizontal: sLg, vertical: 12),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
),
hintStyle: TextStyle(color: textHint, fontSize: 16),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide.none,
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: const BorderSide(color: primary, width: 1),
),
hintStyle: TextStyle(color: textHint, fontSize: 15),
),
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
backgroundColor: primary,
foregroundColor: Colors.white,
minimumSize: const Size(double.infinity, 56),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rPill)),
textStyle: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600),
minimumSize: const Size(double.infinity, 52),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rMd)),
textStyle: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
elevation: 0,
shadowColor: primary.withOpacity(0.3),
),
),
dialogTheme: DialogThemeData(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rXl))),
dialogTheme: DialogThemeData(shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(rLg))),
textTheme: const TextTheme(
headlineLarge: TextStyle(fontSize: 28, fontWeight: FontWeight.w700, color: text, letterSpacing: -0.3),
titleLarge: TextStyle(fontSize: 22, fontWeight: FontWeight.w700, color: text),
titleMedium: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: text),
bodyLarge: TextStyle(fontSize: 16, color: text, height: 1.5),
bodyMedium: TextStyle(fontSize: 14, color: textSub, height: 1.4),
headlineLarge: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: text),
titleLarge: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: text),
titleMedium: TextStyle(fontSize: 16, fontWeight: FontWeight.w500, color: text),
bodyLarge: TextStyle(fontSize: 15, color: text, height: 1.5),
bodyMedium: TextStyle(fontSize: 13, color: textSub, height: 1.4),
labelMedium: TextStyle(fontSize: 13, color: textSub),
labelSmall: TextStyle(fontSize: 12, color: textHint),
),
);
// ── Shadcn UI 主题(紫蓝系) ──
// ── Shadcn UI 主题 ──
static ShadThemeData get shadTheme => ShadThemeData(
brightness: Brightness.light,
colorScheme: ShadVioletColorScheme.light(