style: 全项目紫色→薄荷绿 Fresh Air 清新风
- 主色 #635BFF→#14B8A6 (薄荷绿) - 浅紫 #EDEBFF→#E6FAF6 (极浅薄荷) - 深紫 #4B44D6→#0F9D8E (深薄荷) - 渐变紫→薄荷渐变 - 全局13种紫色映射替换
This commit is contained in:
@@ -1,33 +1,28 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
/// 健康管家主题 —— 暖茶绿 · Soft Clinical
|
/// 健康管家 — Fresh Air 清新风
|
||||||
/// 深青碧色主调 + 暖白基底 + 琥珀点缀 避开传统医疗蓝/紫
|
/// 薄荷绿主调 · 轻透白底 · 珊瑚点缀
|
||||||
class AppTheme {
|
class AppTheme {
|
||||||
AppTheme._();
|
AppTheme._();
|
||||||
|
|
||||||
// ── 品牌色 ──
|
static const Color primary = Color(0xFF14B8A6); // 薄荷绿
|
||||||
static const Color primary = Color(0xFF0E8C7D); // 深青碧 · 专业信赖
|
static const Color primaryLight = Color(0xFFE6FAF6); // 极浅薄荷
|
||||||
static const Color primaryLight = Color(0xFFE3F4F0); // 浅青底
|
static const Color primaryDark = Color(0xFF0F9D8E); // 深薄荷
|
||||||
static const Color primaryDark = Color(0xFF0A6B5F); // 深青
|
|
||||||
|
|
||||||
// ── 背景 ──
|
static const Color bg = Color(0xFFF6F9FB); // 清透底
|
||||||
static const Color bg = Color(0xFFFAF6F1); // 暖白 · 不冰冷
|
static const Color surface = Color(0xFFFFFFFF); // 卡片白
|
||||||
static const Color surface = Color(0xFFFFFCF9); // 卡片白
|
|
||||||
|
|
||||||
// ── 文字 ──
|
static const Color text = Color(0xFF1C2B33);
|
||||||
static const Color text = Color(0xFF2D2B32);
|
static const Color textSub = Color(0xFF6B7C85);
|
||||||
static const Color textSub = Color(0xFF7B797F);
|
static const Color textHint = Color(0xFFA5B4BD);
|
||||||
static const Color textHint = Color(0xFFB0ADB5);
|
|
||||||
|
|
||||||
// ── 功能色 ──
|
static const Color success = Color(0xFF10B981);
|
||||||
static const Color success = Color(0xFF43A047);
|
static const Color error = Color(0xFFF56C6C);
|
||||||
static const Color error = Color(0xFFE05D5D);
|
static const Color warning = Color(0xFFF59E0B);
|
||||||
static const Color warning = Color(0xFFF0984A);
|
static const Color accent = Color(0xFFFF7B6B); // 珊瑚
|
||||||
static const Color accent = Color(0xFFF0984A); // 琥珀 · 高亮/操作
|
|
||||||
|
|
||||||
// ── 边框 & 分割 ──
|
static const Color border = Color(0xFFE5EBF0);
|
||||||
static const Color border = Color(0xFFE8E4DF);
|
static const Color divider = Color(0xFFEEF2F6);
|
||||||
static const Color divider = Color(0xFFF0ECE7);
|
|
||||||
|
|
||||||
static ThemeData get lightTheme => ThemeData(
|
static ThemeData get lightTheme => ThemeData(
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
@@ -39,77 +34,54 @@ class AppTheme {
|
|||||||
),
|
),
|
||||||
scaffoldBackgroundColor: bg,
|
scaffoldBackgroundColor: bg,
|
||||||
|
|
||||||
// AppBar
|
|
||||||
appBarTheme: const AppBarTheme(
|
appBarTheme: const AppBarTheme(
|
||||||
backgroundColor: surface,
|
backgroundColor: surface,
|
||||||
foregroundColor: text,
|
foregroundColor: text,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
titleTextStyle: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: text),
|
scrolledUnderElevation: 0,
|
||||||
),
|
),
|
||||||
|
|
||||||
// 卡片
|
|
||||||
cardTheme: CardThemeData(
|
cardTheme: CardThemeData(
|
||||||
color: surface,
|
color: surface,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(18)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
margin: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
|
|
||||||
// 输入框
|
|
||||||
inputDecorationTheme: InputDecorationTheme(
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
filled: true,
|
filled: true,
|
||||||
fillColor: surface,
|
fillColor: const Color(0xFFF2F6F9),
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12),
|
||||||
border: OutlineInputBorder(
|
border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none),
|
||||||
borderRadius: BorderRadius.circular(14),
|
enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none),
|
||||||
borderSide: const BorderSide(color: border),
|
focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: primary, width: 1.5)),
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(14),
|
|
||||||
borderSide: const BorderSide(color: border),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(14),
|
|
||||||
borderSide: const BorderSide(color: primary, width: 1.5),
|
|
||||||
),
|
|
||||||
hintStyle: const TextStyle(color: textHint, fontSize: 15),
|
hintStyle: const TextStyle(color: textHint, fontSize: 15),
|
||||||
),
|
),
|
||||||
|
|
||||||
// 按钮
|
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: primary,
|
backgroundColor: primary,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
minimumSize: const Size(double.infinity, 50),
|
minimumSize: const Size(double.infinity, 48),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(26)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(14)),
|
||||||
textStyle: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600),
|
textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// 圆角 Dialog
|
|
||||||
dialogTheme: DialogThemeData(
|
dialogTheme: DialogThemeData(
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(22)),
|
||||||
backgroundColor: surface,
|
|
||||||
),
|
),
|
||||||
|
|
||||||
// 总体圆角
|
|
||||||
chipTheme: ChipThemeData(
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
|
||||||
backgroundColor: primaryLight,
|
|
||||||
),
|
|
||||||
|
|
||||||
// 字体层级
|
|
||||||
textTheme: const TextTheme(
|
textTheme: const TextTheme(
|
||||||
headlineLarge: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: text, letterSpacing: -0.5),
|
headlineLarge: TextStyle(fontSize: 24, fontWeight: FontWeight.w700, color: text),
|
||||||
titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: text),
|
titleLarge: TextStyle(fontSize: 20, fontWeight: FontWeight.w600, color: text),
|
||||||
titleMedium: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: text),
|
titleMedium: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: text),
|
||||||
bodyLarge: TextStyle(fontSize: 16, fontWeight: FontWeight.w400, color: text, height: 1.5),
|
bodyLarge: TextStyle(fontSize: 16, color: text, height: 1.5),
|
||||||
bodyMedium: TextStyle(fontSize: 15, fontWeight: FontWeight.w400, color: textSub, height: 1.4),
|
bodyMedium: TextStyle(fontSize: 15, color: textSub, height: 1.4),
|
||||||
labelLarge: TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: textSub),
|
labelMedium: TextStyle(fontSize: 13, color: textSub),
|
||||||
labelMedium: TextStyle(fontSize: 13, fontWeight: FontWeight.w400, color: textSub),
|
labelSmall: TextStyle(fontSize: 11, color: textHint),
|
||||||
labelSmall: TextStyle(fontSize: 11, fontWeight: FontWeight.w400, color: textHint),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,11 +50,11 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: Container(
|
body: Container(
|
||||||
decoration: const BoxDecoration(gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFF5F3FF), Color(0xFFEDEBFF), Color(0xFFE8E4FF)])),
|
decoration: const BoxDecoration(gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [Color(0xFFF2FAF9), Color(0xFFE6FAF6), Color(0xFFE8E4FF)])),
|
||||||
child: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.symmetric(horizontal: 32), child: Column(children: [
|
child: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.symmetric(horizontal: 32), child: Column(children: [
|
||||||
const SizedBox(height: 60),
|
const SizedBox(height: 60),
|
||||||
Container(width: 140, height: 140, decoration: BoxDecoration(color: const Color(0xFF635BFF).withAlpha(20), borderRadius: BorderRadius.circular(70)), child: Stack(alignment: Alignment.center, children: [
|
Container(width: 140, height: 140, decoration: BoxDecoration(color: const Color(0xFF14B8A6).withAlpha(20), borderRadius: BorderRadius.circular(70)), child: Stack(alignment: Alignment.center, children: [
|
||||||
Container(width: 100, height: 100, decoration: BoxDecoration(color: Colors.white.withAlpha(200), borderRadius: BorderRadius.circular(50)), child: Icon(Icons.favorite, size: 50, color: const Color(0xFF635BFF))),
|
Container(width: 100, height: 100, decoration: BoxDecoration(color: Colors.white.withAlpha(200), borderRadius: BorderRadius.circular(50)), child: Icon(Icons.favorite, size: 50, color: const Color(0xFF14B8A6))),
|
||||||
Positioned(right: 10, top: 10, child: Container(width: 30, height: 30, decoration: BoxDecoration(color: const Color(0xFFFFB800), borderRadius: BorderRadius.circular(15), border: Border.all(color: Colors.white, width: 2)), child: const Icon(Icons.add, size: 16, color: Colors.white))),
|
Positioned(right: 10, top: 10, child: Container(width: 30, height: 30, decoration: BoxDecoration(color: const Color(0xFFFFB800), borderRadius: BorderRadius.circular(15), border: Border.all(color: Colors.white, width: 2)), child: const Icon(Icons.add, size: 16, color: Colors.white))),
|
||||||
])),
|
])),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
@@ -63,22 +63,22 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
|||||||
Text('你的 AI 心脏健康管家', style: TextStyle(fontSize: 15, color: Colors.grey[500])),
|
Text('你的 AI 心脏健康管家', style: TextStyle(fontSize: 15, color: Colors.grey[500])),
|
||||||
const SizedBox(height: 48),
|
const SizedBox(height: 48),
|
||||||
TextField(controller: _phoneCtrl, keyboardType: TextInputType.phone, maxLength: 11,
|
TextField(controller: _phoneCtrl, keyboardType: TextInputType.phone, maxLength: 11,
|
||||||
decoration: InputDecoration(hintText: '请输入手机号', prefixIcon: const Padding(padding: EdgeInsets.only(left: 12), child: Text('+86', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500))), counterText: '', filled: true, fillColor: Colors.white, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF635BFF), width: 1.5)))),
|
decoration: InputDecoration(hintText: '请输入手机号', prefixIcon: const Padding(padding: EdgeInsets.only(left: 12), child: Text('+86', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w500))), counterText: '', filled: true, fillColor: Colors.white, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF14B8A6), width: 1.5)))),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Row(children: [
|
Row(children: [
|
||||||
Expanded(child: TextField(controller: _codeCtrl, keyboardType: TextInputType.number, maxLength: 6,
|
Expanded(child: TextField(controller: _codeCtrl, keyboardType: TextInputType.number, maxLength: 6,
|
||||||
decoration: InputDecoration(hintText: '验证码', filled: true, fillColor: Colors.white, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF635BFF), width: 1.5)), counterText: ''))),
|
decoration: InputDecoration(hintText: '验证码', filled: true, fillColor: Colors.white, border: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: BorderSide.none), focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(12), borderSide: const BorderSide(color: Color(0xFF14B8A6), width: 1.5)), counterText: ''))),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
GestureDetector(onTap: (_countdown > 0 || _sending) ? null : _sendSms, child: Container(width: 100, height: 48, alignment: Alignment.center, decoration: BoxDecoration(color: _countdown > 0 ? Colors.grey[300] : const Color(0xFF635BFF), borderRadius: BorderRadius.circular(12)), child: Text(_sending ? '发送中' : _countdown > 0 ? '${_countdown}s' : '获取验证码', style: TextStyle(fontSize: 14, color: _countdown > 0 ? Colors.grey[600] : Colors.white, fontWeight: FontWeight.w500)))),
|
GestureDetector(onTap: (_countdown > 0 || _sending) ? null : _sendSms, child: Container(width: 100, height: 48, alignment: Alignment.center, decoration: BoxDecoration(color: _countdown > 0 ? Colors.grey[300] : const Color(0xFF14B8A6), borderRadius: BorderRadius.circular(12)), child: Text(_sending ? '发送中' : _countdown > 0 ? '${_countdown}s' : '获取验证码', style: TextStyle(fontSize: 14, color: _countdown > 0 ? Colors.grey[600] : Colors.white, fontWeight: FontWeight.w500)))),
|
||||||
]),
|
]),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Align(alignment: Alignment.centerLeft, child: GestureDetector(onTap: () => setState(() => _agreed = !_agreed), child: Row(mainAxisSize: MainAxisSize.min, children: [
|
Align(alignment: Alignment.centerLeft, child: GestureDetector(onTap: () => setState(() => _agreed = !_agreed), child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
Container(width: 20, height: 20, margin: const EdgeInsets.only(right: 6), decoration: BoxDecoration(shape: BoxShape.rectangle, color: _agreed ? const Color(0xFF635BFF) : Colors.transparent, border: Border.all(color: _agreed ? const Color(0xFF635BFF) : const Color(0xFFBDBDBD), width: 1.5), borderRadius: BorderRadius.circular(4)), child: _agreed ? const Icon(Icons.check, size: 14, color: Colors.white) : null),
|
Container(width: 20, height: 20, margin: const EdgeInsets.only(right: 6), decoration: BoxDecoration(shape: BoxShape.rectangle, color: _agreed ? const Color(0xFF14B8A6) : Colors.transparent, border: Border.all(color: _agreed ? const Color(0xFF14B8A6) : const Color(0xFFBDBDBD), width: 1.5), borderRadius: BorderRadius.circular(4)), child: _agreed ? const Icon(Icons.check, size: 14, color: Colors.white) : null),
|
||||||
RichText(text: TextSpan(children: [TextSpan(text: '已阅读并同意', style: TextStyle(fontSize: 13, color: Colors.grey[600])), TextSpan(text: '《服务协议》', style: const TextStyle(fontSize: 13, color: Color(0xFF635BFF))), TextSpan(text: '和', style: TextStyle(fontSize: 13, color: Colors.grey[600])), TextSpan(text: '《隐私政策》', style: const TextStyle(fontSize: 13, color: Color(0xFF635BFF)))])),
|
RichText(text: TextSpan(children: [TextSpan(text: '已阅读并同意', style: TextStyle(fontSize: 13, color: Colors.grey[600])), TextSpan(text: '《服务协议》', style: const TextStyle(fontSize: 13, color: Color(0xFF14B8A6))), TextSpan(text: '和', style: TextStyle(fontSize: 13, color: Colors.grey[600])), TextSpan(text: '《隐私政策》', style: const TextStyle(fontSize: 13, color: Color(0xFF14B8A6)))])),
|
||||||
]))),
|
]))),
|
||||||
if (_error != null) Padding(padding: const EdgeInsets.only(top: 12), child: Text(_error!, style: const TextStyle(color: Color(0xFFE53935), fontSize: 13))),
|
if (_error != null) Padding(padding: const EdgeInsets.only(top: 12), child: Text(_error!, style: const TextStyle(color: Color(0xFFE53935), fontSize: 13))),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
GestureDetector(onTap: _loading ? null : _login, child: Container(width: double.infinity, height: 50, alignment: Alignment.center, decoration: BoxDecoration(gradient: const LinearGradient(colors: [Color(0xFF7C73FF), Color(0xFF635BFF)]), borderRadius: BorderRadius.circular(25), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(80), blurRadius: 16, offset: const Offset(0, 8))]), child: _loading ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2.5, color: Colors.white)) : const Text('登 录', style: TextStyle(fontSize: 17, color: Colors.white, fontWeight: FontWeight.w600, letterSpacing: 2)))),
|
GestureDetector(onTap: _loading ? null : _login, child: Container(width: double.infinity, height: 50, alignment: Alignment.center, decoration: BoxDecoration(gradient: const LinearGradient(colors: [Color(0xFF2DC4B4), Color(0xFF14B8A6)]), borderRadius: BorderRadius.circular(25), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(80), blurRadius: 16, offset: const Offset(0, 8))]), child: _loading ? const SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2.5, color: Colors.white)) : const Text('登 录', style: TextStyle(fontSize: 17, color: Colors.white, fontWeight: FontWeight.w600, letterSpacing: 2)))),
|
||||||
const SizedBox(height: 40),
|
const SizedBox(height: 40),
|
||||||
]))),
|
]))),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -265,7 +265,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
final title = _labels[widget.metricType] ?? '趋势图表';
|
final title = _labels[widget.metricType] ?? '趋势图表';
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -351,7 +351,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
gradient: const LinearGradient(
|
gradient: const LinearGradient(
|
||||||
colors: [Color(0xFFEDEBFF), Color(0xFFF3F1FF)],
|
colors: [Color(0xFFE6FAF6), Color(0xFFF3F1FF)],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
@@ -423,7 +423,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(
|
BoxShadow(
|
||||||
color: const Color(0xFF635BFF).withValues(alpha: 0.06),
|
color: const Color(0xFF14B8A6).withValues(alpha: 0.06),
|
||||||
blurRadius: 20,
|
blurRadius: 20,
|
||||||
offset: const Offset(0, 4),
|
offset: const Offset(0, 4),
|
||||||
),
|
),
|
||||||
@@ -435,7 +435,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
_buildLegendDot(const Color(0xFF635BFF), _isDualLine ? '收缩压' : _labels[widget.metricType]?.replaceAll('趋势', '') ?? ''),
|
_buildLegendDot(const Color(0xFF14B8A6), _isDualLine ? '收缩压' : _labels[widget.metricType]?.replaceAll('趋势', '') ?? ''),
|
||||||
if (_isDualLine) ...[
|
if (_isDualLine) ...[
|
||||||
const SizedBox(width: 24),
|
const SizedBox(width: 24),
|
||||||
_buildLegendDot(const Color(0xFF43A047), '舒张压'),
|
_buildLegendDot(const Color(0xFF43A047), '舒张压'),
|
||||||
@@ -500,7 +500,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
_buildVerticalDivider(),
|
_buildVerticalDivider(),
|
||||||
Expanded(child: _StatItem(label: '最低值', value: stats['min'].toString(), color: const Color(0xFFFF9800))),
|
Expanded(child: _StatItem(label: '最低值', value: stats['min'].toString(), color: const Color(0xFFFF9800))),
|
||||||
_buildVerticalDivider(),
|
_buildVerticalDivider(),
|
||||||
Expanded(child: _StatItem(label: '平均值', value: stats['avg'].toString(), color: const Color(0xFF635BFF))),
|
Expanded(child: _StatItem(label: '平均值', value: stats['avg'].toString(), color: const Color(0xFF14B8A6))),
|
||||||
_buildVerticalDivider(),
|
_buildVerticalDivider(),
|
||||||
Expanded(child: _StatItem(label: '测量次数', value: stats['count'].toString(), color: const Color(0xFF78909C))),
|
Expanded(child: _StatItem(label: '测量次数', value: stats['count'].toString(), color: const Color(0xFF78909C))),
|
||||||
]),
|
]),
|
||||||
@@ -554,7 +554,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
_showAllRecords ? '收起' : '查看全部 (${validRecords.length} 条)',
|
_showAllRecords ? '收起' : '查看全部 (${validRecords.length} 条)',
|
||||||
style: const TextStyle(fontSize: 13, color: Color(0xFF635BFF)),
|
style: const TextStyle(fontSize: 13, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -688,7 +688,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
child: const Text('关闭', style: TextStyle(color: Color(0xFF635BFF))),
|
child: const Text('关闭', style: TextStyle(color: Color(0xFF14B8A6))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -713,10 +713,10 @@ class _TimeChip extends StatelessWidget {
|
|||||||
duration: const Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 200),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 22, vertical: 8),
|
padding: const EdgeInsets.symmetric(horizontal: 22, vertical: 8),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: selected ? const Color(0xFF635BFF) : Colors.white,
|
color: selected ? const Color(0xFF14B8A6) : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: selected ? const Color(0xFF635BFF) : const Color(0xFFE0E0E0)),
|
border: Border.all(color: selected ? const Color(0xFF14B8A6) : const Color(0xFFE0E0E0)),
|
||||||
boxShadow: selected ? [BoxShadow(color: const Color(0xFF635BFF).withValues(alpha: 0.25), blurRadius: 8, offset: const Offset(0, 3))] : null,
|
boxShadow: selected ? [BoxShadow(color: const Color(0xFF14B8A6).withValues(alpha: 0.25), blurRadius: 8, offset: const Offset(0, 3))] : null,
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
label,
|
label,
|
||||||
@@ -770,7 +770,7 @@ class _TrendChartPainter extends CustomPainter {
|
|||||||
final String Function(DateTime) formatDateLabel;
|
final String Function(DateTime) formatDateLabel;
|
||||||
final String Function(num) formatValue;
|
final String Function(num) formatValue;
|
||||||
|
|
||||||
static const _primaryColor = Color(0xFF635BFF);
|
static const _primaryColor = Color(0xFF14B8A6);
|
||||||
static const _secondaryColor = Color(0xFF43A047);
|
static const _secondaryColor = Color(0xFF43A047);
|
||||||
static const _gridColor = Color(0xFFEEEEEE);
|
static const _gridColor = Color(0xFFEEEEEE);
|
||||||
static const _labelColor = Color(0xFF999999);
|
static const _labelColor = Color(0xFF999999);
|
||||||
|
|||||||
@@ -36,10 +36,10 @@ class DoctorListPage extends ConsumerWidget {
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 28,
|
radius: 28,
|
||||||
backgroundColor: const Color(0xFFEDEBFF),
|
backgroundColor: const Color(0xFFE6FAF6),
|
||||||
child: Text(
|
child: Text(
|
||||||
(d['name'] as String?)?.isNotEmpty == true ? d['name']![0] : '?',
|
(d['name'] as String?)?.isNotEmpty == true ? d['name']![0] : '?',
|
||||||
style: const TextStyle(fontSize: 22, color: Color(0xFF635BFF)),
|
style: const TextStyle(fontSize: 22, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
@@ -53,7 +53,7 @@ class DoctorListPage extends ConsumerWidget {
|
|||||||
Text(d['title'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF666666))),
|
Text(d['title'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF666666))),
|
||||||
]),
|
]),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(d['department'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF635BFF))),
|
Text(d['department'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF14B8A6))),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text(d['introduction'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF999999))),
|
Text(d['introduction'] ?? '', style: const TextStyle(fontSize: 14, color: Color(0xFF999999))),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -132,11 +132,11 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
width: 180,
|
width: 180,
|
||||||
height: 180,
|
height: 180,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(90),
|
borderRadius: BorderRadius.circular(90),
|
||||||
border: Border.all(color: const Color(0xFF635BFF), width: 2),
|
border: Border.all(color: const Color(0xFF14B8A6), width: 2),
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.camera_alt, size: 48, color: Color(0xFF635BFF)),
|
child: const Icon(Icons.camera_alt, size: 48, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
const Text('拍摄或上传您的餐食照片', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
|
const Text('拍摄或上传您的餐食照片', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
|
||||||
@@ -165,10 +165,10 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFEFEFF),
|
color: const Color(0xFFFEFEFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(20), blurRadius: 8, offset: const Offset(0, 2))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(20), blurRadius: 8, offset: const Offset(0, 2))],
|
||||||
),
|
),
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(icon, size: 32, color: const Color(0xFF635BFF)),
|
icon: Icon(icon, size: 32, color: const Color(0xFF14B8A6)),
|
||||||
onPressed: () => _pickImage(context, ref, source),
|
onPressed: () => _pickImage(context, ref, source),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -244,11 +244,11 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Text(meal['icon']!, style: const TextStyle(fontSize: 20)),
|
Text(meal['icon']!, style: const TextStyle(fontSize: 20)),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(meal['label']!, style: TextStyle(fontSize: 12, color: isSelected ? Colors.white : const Color(0xFF635BFF))),
|
Text(meal['label']!, style: TextStyle(fontSize: 12, color: isSelected ? Colors.white : const Color(0xFF14B8A6))),
|
||||||
]),
|
]),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: isSelected ? const Color(0xFF635BFF) : const Color(0xFFF5F3FF),
|
backgroundColor: isSelected ? const Color(0xFF14B8A6) : const Color(0xFFF2FAF9),
|
||||||
foregroundColor: isSelected ? Colors.white : const Color(0xFF635BFF),
|
foregroundColor: isSelected ? Colors.white : const Color(0xFF14B8A6),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
@@ -268,10 +268,10 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
height: 60,
|
height: 60,
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFEDEBFF),
|
color: const Color(0xFFE6FAF6),
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
),
|
),
|
||||||
child: const CircularProgressIndicator(strokeWidth: 3, color: Color(0xFF635BFF)),
|
child: const CircularProgressIndicator(strokeWidth: 3, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
const Text('AI 正在识别食物...', style: TextStyle(fontSize: 16, color: Color(0xFF666666))),
|
const Text('AI 正在识别食物...', style: TextStyle(fontSize: 16, color: Color(0xFF666666))),
|
||||||
@@ -286,7 +286,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFEFEFF),
|
color: const Color(0xFFFEFEFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: const Color(0xFFE8E6FF), width: 1.5),
|
border: Border.all(color: const Color(0xFFD4EDE8), width: 1.5),
|
||||||
),
|
),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
Padding(
|
Padding(
|
||||||
@@ -297,7 +297,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
const Text('识别结果', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
const Text('识别结果', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.add, size: 20, color: Color(0xFF635BFF)),
|
icon: const Icon(Icons.add, size: 20, color: Color(0xFF14B8A6)),
|
||||||
onPressed: () => ref.read(dietProvider.notifier).addFood(),
|
onPressed: () => ref.read(dietProvider.notifier).addFood(),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
@@ -312,14 +312,14 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: food.selected ? const Color(0xFFF5F3FF) : const Color(0xFFF5F5F5),
|
color: food.selected ? const Color(0xFFF2FAF9) : const Color(0xFFF5F5F5),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Checkbox(
|
Checkbox(
|
||||||
value: food.selected,
|
value: food.selected,
|
||||||
onChanged: (v) => ref.read(dietProvider.notifier).toggleFood(food.id),
|
onChanged: (v) => ref.read(dietProvider.notifier).toggleFood(food.id),
|
||||||
activeColor: const Color(0xFF635BFF),
|
activeColor: const Color(0xFF14B8A6),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -339,7 +339,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
controller: TextEditingController(text: food.calories.toString()),
|
controller: TextEditingController(text: food.calories.toString()),
|
||||||
keyboardType: TextInputType.number,
|
keyboardType: TextInputType.number,
|
||||||
onChanged: (v) => ref.read(dietProvider.notifier).updateFoodCalories(food.id, int.tryParse(v) ?? 0),
|
onChanged: (v) => ref.read(dietProvider.notifier).updateFoodCalories(food.id, int.tryParse(v) ?? 0),
|
||||||
style: TextStyle(fontSize: 12, color: const Color(0xFF635BFF)),
|
style: TextStyle(fontSize: 12, color: const Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Text('kcal', style: TextStyle(fontSize: 12, color: Color(0xFF999999))),
|
const Text('kcal', style: TextStyle(fontSize: 12, color: Color(0xFF999999))),
|
||||||
@@ -358,7 +358,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
@@ -383,7 +383,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFEFEFF),
|
color: const Color(0xFFFEFEFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: const Color(0xFFE8E6FF), width: 1.5),
|
border: Border.all(color: const Color(0xFFD4EDE8), width: 1.5),
|
||||||
),
|
),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
const Text('🥗 健康评分', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
const Text('🥗 健康评分', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||||
@@ -417,7 +417,7 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
switch (score) {
|
switch (score) {
|
||||||
case 1: return const Color(0xFFE53935);
|
case 1: return const Color(0xFFE53935);
|
||||||
case 2: return const Color(0xFFF9A825);
|
case 2: return const Color(0xFFF9A825);
|
||||||
case 3: return const Color(0xFF635BFF);
|
case 3: return const Color(0xFF14B8A6);
|
||||||
case 4: return const Color(0xFF43A047);
|
case 4: return const Color(0xFF43A047);
|
||||||
case 5: return const Color(0xFF00C853);
|
case 5: return const Color(0xFF00C853);
|
||||||
default: return Colors.grey[400]!;
|
default: return Colors.grey[400]!;
|
||||||
@@ -431,13 +431,13 @@ class DietCapturePage extends ConsumerWidget {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||||
content: Text('饮食记录已保存 ✅'),
|
content: Text('饮食记录已保存 ✅'),
|
||||||
backgroundColor: Color(0xFF635BFF),
|
backgroundColor: Color(0xFF14B8A6),
|
||||||
));
|
));
|
||||||
popRoute(ref);
|
popRoute(ref);
|
||||||
},
|
},
|
||||||
child: const Text('保存记录'),
|
child: const Text('保存记录'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
drawer: const HealthDrawer(),
|
drawer: const HealthDrawer(),
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
// ── 顶部栏 ──
|
// ── 顶部栏 ──
|
||||||
@@ -110,11 +110,11 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Builder(builder: (ctx) => GestureDetector(
|
Builder(builder: (ctx) => GestureDetector(
|
||||||
onTap: () => Scaffold.of(ctx).openDrawer(),
|
onTap: () => Scaffold.of(ctx).openDrawer(),
|
||||||
child: CircleAvatar(radius: 20, backgroundColor: const Color(0xFFEDEBFF), backgroundImage: user?.avatarUrl != null ? NetworkImage(user!.avatarUrl!) : null, child: user?.avatarUrl == null ? const Icon(Icons.person, size: 24, color: Color(0xFF635BFF)) : null),
|
child: CircleAvatar(radius: 20, backgroundColor: const Color(0xFFE6FAF6), backgroundImage: user?.avatarUrl != null ? NetworkImage(user!.avatarUrl!) : null, child: user?.avatarUrl == null ? const Icon(Icons.person, size: 24, color: Color(0xFF14B8A6)) : null),
|
||||||
)),
|
)),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Row(mainAxisSize: MainAxisSize.min, children: [Icon(Icons.smart_toy_outlined, size: 16, color: const Color(0xFF635BFF)), const SizedBox(width: 4), Text('AI 健康管家', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500, color: Colors.grey[600]))]),
|
Row(mainAxisSize: MainAxisSize.min, children: [Icon(Icons.smart_toy_outlined, size: 16, color: const Color(0xFF14B8A6)), const SizedBox(width: 4), Text('AI 健康管家', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w500, color: Colors.grey[600]))]),
|
||||||
const SizedBox(height: 2),
|
const SizedBox(height: 2),
|
||||||
Text('${_getGreeting()},${user?.name ?? '张三'}!', style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))),
|
Text('${_getGreeting()},${user?.name ?? '张三'}!', style: const TextStyle(fontSize: 17, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))),
|
||||||
])),
|
])),
|
||||||
@@ -151,11 +151,11 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(8), blurRadius: 6, offset: const Offset(0, 1))]),
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(8), blurRadius: 6, offset: const Offset(0, 1))]),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
const Text('展开 ▾', style: TextStyle(fontSize: 12, color: Color(0xFF635BFF))),
|
const Text('展开 ▾', style: TextStyle(fontSize: 12, color: Color(0xFF14B8A6))),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -165,7 +165,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
margin: const EdgeInsets.symmetric(horizontal: 16, vertical: 6),
|
||||||
padding: const EdgeInsets.all(14),
|
padding: const EdgeInsets.all(14),
|
||||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(8), blurRadius: 6, offset: const Offset(0, 1))]),
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(8), blurRadius: 6, offset: const Offset(0, 1))]),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Row(children: [
|
Row(children: [
|
||||||
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||||
@@ -339,7 +339,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [
|
||||||
Container(width: 30, height: 30, decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(8)), child: Icon(icon, size: 15, color: const Color(0xFF635BFF))),
|
Container(width: 30, height: 30, decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(8)), child: Icon(icon, size: 15, color: const Color(0xFF14B8A6))),
|
||||||
const SizedBox(width: 10), Expanded(child: Text(label, style: const TextStyle(fontSize: 13, color: Color(0xFF333333)))),
|
const SizedBox(width: 10), Expanded(child: Text(label, style: const TextStyle(fontSize: 13, color: Color(0xFF333333)))),
|
||||||
Icon(icons[effectiveStatus], size: 18, color: colors[effectiveStatus] ?? Colors.grey),
|
Icon(icons[effectiveStatus], size: 18, color: colors[effectiveStatus] ?? Colors.grey),
|
||||||
]),
|
]),
|
||||||
@@ -351,7 +351,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
void _handleMedicationCheck() async {
|
void _handleMedicationCheck() async {
|
||||||
await ref.read(medicationServiceProvider).confirm('');
|
await ref.read(medicationServiceProvider).confirm('');
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已记录服药 ✅'), backgroundColor: Color(0xFF635BFF)));
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已记录服药 ✅'), backgroundColor: Color(0xFF14B8A6)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═════════════════════ 智能体选择条(常驻) ═════════════════════
|
// ═════════════════════ 智能体选择条(常驻) ═════════════════════
|
||||||
@@ -392,9 +392,9 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isActive ? const Color(0xFF635BFF) : Colors.white,
|
color: isActive ? const Color(0xFF14B8A6) : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: isActive ? const Color(0xFF635BFF) : const Color(0xFFE0E0E0)),
|
border: Border.all(color: isActive ? const Color(0xFF14B8A6) : const Color(0xFFE0E0E0)),
|
||||||
),
|
),
|
||||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
Icon(icon, size: 13, color: isActive ? Colors.white : const Color(0xFF666666)),
|
Icon(icon, size: 13, color: isActive ? Colors.white : const Color(0xFF666666)),
|
||||||
@@ -456,7 +456,7 @@ class _HomePageState extends ConsumerState<HomePage> {
|
|||||||
decoration: const InputDecoration(hintText: '输入你想说的...', hintStyle: TextStyle(fontSize: 15, color: Color(0xFFBBBBBB)), contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 10), border: InputBorder.none),
|
decoration: const InputDecoration(hintText: '输入你想说的...', hintStyle: TextStyle(fontSize: 15, color: Color(0xFFBBBBBB)), contentPadding: EdgeInsets.symmetric(horizontal: 10, vertical: 10), border: InputBorder.none),
|
||||||
onSubmitted: (_) => _sendMessage(),
|
onSubmitted: (_) => _sendMessage(),
|
||||||
)),
|
)),
|
||||||
IconButton(icon: const Icon(Icons.send, size: 24, color: Color(0xFF635BFF)), onPressed: _sendMessage),
|
IconButton(icon: const Icon(Icons.send, size: 24, color: Color(0xFF14B8A6)), onPressed: _sendMessage),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,10 +26,10 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
width: 80,
|
width: 80,
|
||||||
height: 80,
|
height: 80,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFEDEBFF),
|
color: const Color(0xFFE6FAF6),
|
||||||
borderRadius: BorderRadius.circular(40),
|
borderRadius: BorderRadius.circular(40),
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.health_and_safety, size: 40, color: Color(0xFF635BFF)),
|
child: const Icon(Icons.health_and_safety, size: 40, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text('开始和 AI 健康管家对话吧', style: Theme.of(context).textTheme.bodyMedium),
|
Text('开始和 AI 健康管家对话吧', style: Theme.of(context).textTheme.bodyMedium),
|
||||||
@@ -100,7 +100,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [
|
boxShadow: [
|
||||||
BoxShadow(color: const Color(0xFF635BFF).withAlpha(20), blurRadius: 16, offset: const Offset(0, 4)),
|
BoxShadow(color: const Color(0xFF14B8A6).withAlpha(20), blurRadius: 16, offset: const Offset(0, 4)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
@@ -113,7 +113,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
padding: const EdgeInsets.fromLTRB(20, 24, 16, 20),
|
padding: const EdgeInsets.fromLTRB(20, 24, 16, 20),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
gradient: LinearGradient(
|
gradient: LinearGradient(
|
||||||
colors: [Color(0xFF7C73FF), Color(0xFF635BFF), Color(0xFF5241D9)],
|
colors: [Color(0xFF2DC4B4), Color(0xFF14B8A6), Color(0xFF0E8071)],
|
||||||
begin: Alignment.topLeft,
|
begin: Alignment.topLeft,
|
||||||
end: Alignment.bottomRight,
|
end: Alignment.bottomRight,
|
||||||
),
|
),
|
||||||
@@ -143,7 +143,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
color: Colors.white.withAlpha(25),
|
color: Colors.white.withAlpha(25),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
child: Text(info.$3, style: const TextStyle(fontSize: 12, color: Color(0xFFE0DDFF))),
|
child: Text(info.$3, style: const TextStyle(fontSize: 12, color: Color(0xFFC6EBE6))),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -157,7 +157,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
color: Colors.white.withAlpha(20),
|
color: Colors.white.withAlpha(20),
|
||||||
shape: BoxShape.circle,
|
shape: BoxShape.circle,
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.close, size: 16, color: Color(0xFFE0DDFF)),
|
child: const Icon(Icons.close, size: 16, color: Color(0xFFC6EBE6)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -182,12 +182,12 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Container(width: 24, height: 1, color: const Color(0xFFD0CCED)),
|
Container(width: 24, height: 1, color: const Color(0xFFC6EBE6)),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.symmetric(horizontal: 10),
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
child: Text('或直接对我说...', style: TextStyle(fontSize: 13, color: Color(0xFF9E94CF))),
|
child: Text('或直接对我说...', style: TextStyle(fontSize: 13, color: Color(0xFF9EDBD3))),
|
||||||
),
|
),
|
||||||
Container(width: 24, height: 1, color: const Color(0xFFD0CCED)),
|
Container(width: 24, height: 1, color: const Color(0xFFC6EBE6)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -216,7 +216,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF7F5FF),
|
color: const Color(0xFFF7F5FF),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(color: const Color(0xFFEBE8FF), width: 1),
|
border: Border.all(color: const Color(0xFFD4EDE8), width: 1),
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -228,7 +228,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
color: const Color(0xFFEDEAFF),
|
color: const Color(0xFFEDEAFF),
|
||||||
borderRadius: BorderRadius.circular(11),
|
borderRadius: BorderRadius.circular(11),
|
||||||
),
|
),
|
||||||
child: Icon(a.icon, size: 20, color: const Color(0xFF635BFF)),
|
child: Icon(a.icon, size: 20, color: const Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 7),
|
const SizedBox(height: 7),
|
||||||
Text(a.label, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xFF333333))),
|
Text(a.label, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500, color: Color(0xFF333333))),
|
||||||
@@ -257,13 +257,13 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
border: Border.all(color: const Color(0xFFEDEBFF)),
|
border: Border.all(color: const Color(0xFFE6FAF6)),
|
||||||
),
|
),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
CircleAvatar(
|
CircleAvatar(
|
||||||
radius: 24,
|
radius: 24,
|
||||||
backgroundColor: const Color(0xFFEDEBFF),
|
backgroundColor: const Color(0xFFE6FAF6),
|
||||||
child: Text(doc['name']![0], style: const TextStyle(fontSize: 20, color: Color(0xFF635BFF))),
|
child: Text(doc['name']![0], style: const TextStyle(fontSize: 20, color: Color(0xFF14B8A6))),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Text(doc['name']!, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
|
Text(doc['name']!, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w600)),
|
||||||
@@ -272,10 +272,10 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(4),
|
borderRadius: BorderRadius.circular(4),
|
||||||
),
|
),
|
||||||
child: Text(doc['dept']!, style: const TextStyle(fontSize: 10, color: Color(0xFF635BFF))),
|
child: Text(doc['dept']!, style: const TextStyle(fontSize: 10, color: Color(0xFF14B8A6))),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Text(
|
Text(
|
||||||
@@ -310,7 +310,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
||||||
),
|
),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -431,7 +431,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
width: 22,
|
width: 22,
|
||||||
height: h,
|
height: h,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: e.key == trend.length - 1 ? const Color(0xFF635BFF) : const Color(0xFFD5D0FF),
|
color: e.key == trend.length - 1 ? const Color(0xFF14B8A6) : const Color(0xFFD5D0FF),
|
||||||
borderRadius: BorderRadius.circular(5),
|
borderRadius: BorderRadius.circular(5),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -482,7 +482,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
||||||
),
|
),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -493,7 +493,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.fromLTRB(18, 20, 18, 16),
|
padding: const EdgeInsets.fromLTRB(18, 20, 18, 16),
|
||||||
decoration: const BoxDecoration(
|
decoration: const BoxDecoration(
|
||||||
gradient: LinearGradient(colors: [Color(0xFFE8F0FE), Color(0xFFF5F3FF)]),
|
gradient: LinearGradient(colors: [Color(0xFFE8F0FE), Color(0xFFF2FAF9)]),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
@@ -537,7 +537,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
const Text('剩余药量', style: TextStyle(fontSize: 13, color: Color(0xFF666666))),
|
const Text('剩余药量', style: TextStyle(fontSize: 13, color: Color(0xFF666666))),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Text('${(remaining * 100).toInt()}%', style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF635BFF))),
|
Text('${(remaining * 100).toInt()}%', style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF14B8A6))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -547,7 +547,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
value: remaining,
|
value: remaining,
|
||||||
minHeight: 8,
|
minHeight: 8,
|
||||||
backgroundColor: const Color(0xFFEFEDFF),
|
backgroundColor: const Color(0xFFEFEDFF),
|
||||||
valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFF635BFF)),
|
valueColor: const AlwaysStoppedAnimation<Color>(Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
@@ -601,7 +601,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
||||||
),
|
),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -657,7 +657,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
] else ...[
|
] else ...[
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(12)),
|
decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(12)),
|
||||||
child: const Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
child: const Row(mainAxisAlignment: MainAxisAlignment.center, children: [
|
||||||
Icon(Icons.hourglass_empty, size: 18, color: Color(0xFF999999)),
|
Icon(Icons.hourglass_empty, size: 18, color: Color(0xFF999999)),
|
||||||
SizedBox(width: 8),
|
SizedBox(width: 8),
|
||||||
@@ -672,7 +672,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
const SizedBox(height: 6),
|
const SizedBox(height: 6),
|
||||||
Container(
|
Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(10)),
|
decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(10)),
|
||||||
child: Text(advice, style: const TextStyle(fontSize: 13, height: 1.6, color: Color(0xFF555555))),
|
child: Text(advice, style: const TextStyle(fontSize: 13, height: 1.6, color: Color(0xFF555555))),
|
||||||
),
|
),
|
||||||
]),
|
]),
|
||||||
@@ -702,7 +702,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
||||||
),
|
),
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -839,9 +839,9 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
const Row(
|
const Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.auto_awesome, size: 16, color: Color(0xFF635BFF)),
|
Icon(Icons.auto_awesome, size: 16, color: Color(0xFF14B8A6)),
|
||||||
SizedBox(width: 6),
|
SizedBox(width: 6),
|
||||||
Text('AI 解读摘要', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF635BFF))),
|
Text('AI 解读摘要', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF14B8A6))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
@@ -883,7 +883,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFFFFFF),
|
color: const Color(0xFFFFFFFF),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(15), blurRadius: 14, offset: const Offset(0, 4))],
|
||||||
),
|
),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(18, 16, 18, 14),
|
padding: const EdgeInsets.fromLTRB(18, 16, 18, 14),
|
||||||
@@ -897,8 +897,8 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
return ElevatedButton(
|
return ElevatedButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFFF5F3FF),
|
backgroundColor: const Color(0xFFF2FAF9),
|
||||||
foregroundColor: const Color(0xFF635BFF),
|
foregroundColor: const Color(0xFF14B8A6),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 11),
|
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 11),
|
||||||
@@ -926,8 +926,8 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFFEFEFF),
|
color: const Color(0xFFFEFEFF),
|
||||||
borderRadius: const BorderRadius.only(topLeft: Radius.circular(4), topRight: Radius.circular(20), bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
borderRadius: const BorderRadius.only(topLeft: Radius.circular(4), topRight: Radius.circular(20), bottomLeft: Radius.circular(20), bottomRight: Radius.circular(20)),
|
||||||
border: Border.all(color: const Color(0xFFE8E6FF), width: 1.5),
|
border: Border.all(color: const Color(0xFFD4EDE8), width: 1.5),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(12), blurRadius: 10, offset: const Offset(0, 3))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(12), blurRadius: 10, offset: const Offset(0, 3))],
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
@@ -937,10 +937,10 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
height: 26,
|
height: 26,
|
||||||
padding: const EdgeInsets.all(5),
|
padding: const EdgeInsets.all(5),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFEDEBFF),
|
color: const Color(0xFFE6FAF6),
|
||||||
borderRadius: BorderRadius.circular(13),
|
borderRadius: BorderRadius.circular(13),
|
||||||
),
|
),
|
||||||
child: const CircularProgressIndicator(strokeWidth: 2.2, color: Color(0xFF635BFF)),
|
child: const CircularProgressIndicator(strokeWidth: 2.2, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text(thinkingText?.isNotEmpty == true ? thinkingText! : '正在分析...', style: const TextStyle(fontSize: 14, color: Color(0xFF999999))),
|
Text(thinkingText?.isNotEmpty == true ? thinkingText! : '正在分析...', style: const TextStyle(fontSize: 14, color: Color(0xFF999999))),
|
||||||
@@ -963,15 +963,15 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.82),
|
constraints: BoxConstraints(maxWidth: MediaQuery.of(context).size.width * 0.82),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isUser ? const Color(0xFF635BFF) : const Color(0xFFFEFEFF),
|
color: isUser ? const Color(0xFF14B8A6) : const Color(0xFFFEFEFF),
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(isUser ? 20 : 4),
|
topLeft: Radius.circular(isUser ? 20 : 4),
|
||||||
topRight: Radius.circular(isUser ? 4 : 20),
|
topRight: Radius.circular(isUser ? 4 : 20),
|
||||||
bottomLeft: const Radius.circular(20),
|
bottomLeft: const Radius.circular(20),
|
||||||
bottomRight: const Radius.circular(20),
|
bottomRight: const Radius.circular(20),
|
||||||
),
|
),
|
||||||
border: isUser ? null : Border.all(color: const Color(0xFFE8E6FF), width: 1.5),
|
border: isUser ? null : Border.all(color: const Color(0xFFD4EDE8), width: 1.5),
|
||||||
boxShadow: isUser ? [] : [BoxShadow(color: const Color(0xFF635BFF).withAlpha(12), blurRadius: 10, offset: const Offset(0, 3))],
|
boxShadow: isUser ? [] : [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(12), blurRadius: 10, offset: const Offset(0, 3))],
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
@@ -998,14 +998,14 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
p: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A), height: 1.5),
|
p: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A), height: 1.5),
|
||||||
h1: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)),
|
h1: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)),
|
||||||
h2: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)),
|
h2: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)),
|
||||||
code: const TextStyle(fontSize: 14, backgroundColor: Color(0xFFF5F3FF)),
|
code: const TextStyle(fontSize: 14, backgroundColor: Color(0xFFF2FAF9)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!isUser && msg.content.isNotEmpty)
|
if (!isUser && msg.content.isNotEmpty)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 10),
|
padding: const EdgeInsets.only(top: 10),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
const CircleAvatar(radius: 10, backgroundColor: Color(0xFFEDEBFF), child: Icon(Icons.chat_bubble_outline, size: 14, color: Color(0xFF635BFF))),
|
const CircleAvatar(radius: 10, backgroundColor: Color(0xFFE6FAF6), child: Icon(Icons.chat_bubble_outline, size: 14, color: Color(0xFF14B8A6))),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
const Text('健康管家', style: TextStyle(fontSize: 12, color: Color(0xFF9E9E9E))),
|
const Text('健康管家', style: TextStyle(fontSize: 12, color: Color(0xFF9E9E9E))),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
@@ -1038,7 +1038,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
return ElevatedButton(
|
return ElevatedButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
@@ -1056,8 +1056,8 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
return OutlinedButton(
|
return OutlinedButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: const Color(0xFF635BFF),
|
foregroundColor: const Color(0xFF14B8A6),
|
||||||
side: const BorderSide(color: Color(0xFF635BFF), width: 1.2),
|
side: const BorderSide(color: Color(0xFF14B8A6), width: 1.2),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 11),
|
padding: const EdgeInsets.symmetric(vertical: 11),
|
||||||
),
|
),
|
||||||
@@ -1195,9 +1195,9 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
padding: const EdgeInsets.all(14),
|
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))]),
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(16), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
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)))]),
|
Row(children: [Icon(Icons.today, size: 18, color: const Color(0xFF14B8A6)), const SizedBox(width: 8), const Text('今日任务', style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)))]),
|
||||||
const SizedBox(height: 10),
|
const SizedBox(height: 10),
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
Row(mainAxisAlignment: MainAxisAlignment.spaceAround, children: [
|
||||||
_miniMetric('血压', bpText, Icons.favorite),
|
_miniMetric('血压', bpText, Icons.favorite),
|
||||||
@@ -1211,7 +1211,7 @@ class ChatMessagesView extends ConsumerWidget {
|
|||||||
|
|
||||||
Widget _miniMetric(String label, String value, IconData icon) {
|
Widget _miniMetric(String label, String value, IconData icon) {
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
Icon(icon, size: 20, color: const Color(0xFF635BFF)),
|
Icon(icon, size: 20, color: const Color(0xFF14B8A6)),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(value, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))),
|
Text(value, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))),
|
||||||
Text(label, style: const TextStyle(fontSize: 10, color: Color(0xFF999999))),
|
Text(label, style: const TextStyle(fontSize: 10, color: Color(0xFF999999))),
|
||||||
@@ -1298,9 +1298,9 @@ class _ExpandableAdviceState extends State<_ExpandableAdvice> {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.lightbulb_outline, size: 16, color: Color(0xFF635BFF)),
|
const Icon(Icons.lightbulb_outline, size: 16, color: Color(0xFF14B8A6)),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
const Text('AI 建议', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF635BFF))),
|
const Text('AI 建议', style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600, color: Color(0xFF14B8A6))),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Icon(_expanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, size: 18, color: const Color(0xFFAAAAAA)),
|
Icon(_expanded ? Icons.keyboard_arrow_up : Icons.keyboard_arrow_down, size: 18, color: const Color(0xFFAAAAAA)),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('已添加 ${_items.length} 种药品'),
|
content: Text('已添加 ${_items.length} 种药品'),
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
ref.invalidate(medicationListProvider);
|
ref.invalidate(medicationListProvider);
|
||||||
@@ -136,7 +136,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -158,7 +158,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
child: const Text(
|
child: const Text(
|
||||||
'保存',
|
'保存',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Color(0xFF635BFF),
|
color: Color(0xFF14B8A6),
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -204,7 +204,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF635BFF),
|
color: Color(0xFF14B8A6),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_items.length > 1)
|
if (_items.length > 1)
|
||||||
@@ -390,7 +390,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.access_time, size: 16, color: Color(0xFF635BFF)),
|
const Icon(Icons.access_time, size: 16, color: Color(0xFF14B8A6)),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Text(
|
Text(
|
||||||
time.format(context),
|
time.format(context),
|
||||||
@@ -410,11 +410,11 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
icon: const Icon(Icons.add, size: 18),
|
icon: const Icon(Icons.add, size: 18),
|
||||||
label: const Text('添加', style: TextStyle(fontSize: 14)),
|
label: const Text('添加', style: TextStyle(fontSize: 14)),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: const Color(0xFF635BFF),
|
foregroundColor: const Color(0xFF14B8A6),
|
||||||
side: const BorderSide(color: Color(0xFFD5D1FF)),
|
side: const BorderSide(color: Color(0xFFC0E8E2)),
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
padding: const EdgeInsets.symmetric(vertical: 12),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
|
||||||
backgroundColor: const Color(0xFFF5F3FF),
|
backgroundColor: const Color(0xFFF2FAF9),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -438,7 +438,7 @@ class _MedicationEditPageState extends ConsumerState<MedicationEditPage> {
|
|||||||
),
|
),
|
||||||
focusedBorder: OutlineInputBorder(
|
focusedBorder: OutlineInputBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
borderSide: const BorderSide(color: Color(0xFF635BFF)),
|
borderSide: const BorderSide(color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ class MedicationListPage extends ConsumerWidget {
|
|||||||
@override Widget build(BuildContext context, WidgetRef ref) {
|
@override Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final meds = ref.watch(medicationListProvider);
|
final meds = ref.watch(medicationListProvider);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -19,9 +19,9 @@ class MedicationListPage extends ConsumerWidget {
|
|||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => pushRoute(ref, 'medicationEdit'),
|
onPressed: () => pushRoute(ref, 'medicationEdit'),
|
||||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
const Icon(Icons.add_circle_outline, size: 18, color: Color(0xFF635BFF)),
|
const Icon(Icons.add_circle_outline, size: 18, color: Color(0xFF14B8A6)),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
const Text('添加新药', style: TextStyle(color: Color(0xFF635BFF), fontSize: 14)),
|
const Text('添加新药', style: TextStyle(color: Color(0xFF14B8A6), fontSize: 14)),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -47,7 +47,7 @@ class MedicationListPage extends ConsumerWidget {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator(color: Color(0xFF635BFF))),
|
loading: () => const Center(child: CircularProgressIndicator(color: Color(0xFF14B8A6))),
|
||||||
error: (_, __) => _empty(context),
|
error: (_, __) => _empty(context),
|
||||||
)),
|
)),
|
||||||
_buildReminderBar(),
|
_buildReminderBar(),
|
||||||
@@ -65,11 +65,11 @@ class MedicationListPage extends ConsumerWidget {
|
|||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFEDEBFF),
|
color: const Color(0xFFE6FAF6),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
border: Border.all(color: const Color(0xFF635BFF).withAlpha(50)),
|
border: Border.all(color: const Color(0xFF14B8A6).withAlpha(50)),
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.notifications_active_outlined, size: 20, color: Color(0xFF635BFF)),
|
child: const Icon(Icons.notifications_active_outlined, size: 20, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
const Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
const Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
@@ -102,9 +102,9 @@ class _TabChip extends StatelessWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 7),
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 7),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: active ? const Color(0xFF635BFF) : Colors.white,
|
color: active ? const Color(0xFF14B8A6) : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: active ? const Color(0xFF635BFF) : const Color(0xFFE0E0E0)),
|
border: Border.all(color: active ? const Color(0xFF14B8A6) : const Color(0xFFE0E0E0)),
|
||||||
),
|
),
|
||||||
child: Text(
|
child: Text(
|
||||||
label,
|
label,
|
||||||
@@ -130,14 +130,14 @@ class _MedicationCard extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
||||||
),
|
),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Container(
|
Container(
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(14),
|
borderRadius: BorderRadius.circular(14),
|
||||||
),
|
),
|
||||||
child: const Center(child: Text('💊', style: TextStyle(fontSize: 24))),
|
child: const Center(child: Text('💊', style: TextStyle(fontSize: 24))),
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ class ProfileDetailPage extends ConsumerWidget {
|
|||||||
final latestHealth = ref.watch(latestHealthProvider);
|
final latestHealth = ref.watch(latestHealthProvider);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -22,23 +22,23 @@ class ProfileDetailPage extends ConsumerWidget {
|
|||||||
]),
|
]),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.all(16), child: Column(children: [_buildUserCard(), const SizedBox(height: 16), _buildHealthOverview(latestHealth), const SizedBox(height: 16), _buildHistoryList(), const SizedBox(height: 16), SizedBox(width: double.infinity, height: 48, child: OutlinedButton(onPressed: () => pushRoute(ref, 'settings'), style: OutlinedButton.styleFrom(foregroundColor: const Color(0xFF635BFF), side: const BorderSide(color: Color(0xFF635BFF)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))), child: const Text('退出档案')))]))),
|
body: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.all(16), child: Column(children: [_buildUserCard(), const SizedBox(height: 16), _buildHealthOverview(latestHealth), const SizedBox(height: 16), _buildHistoryList(), const SizedBox(height: 16), SizedBox(width: double.infinity, height: 48, child: OutlinedButton(onPressed: () => pushRoute(ref, 'settings'), style: OutlinedButton.styleFrom(foregroundColor: const Color(0xFF14B8A6), side: const BorderSide(color: Color(0xFF14B8A6)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))), child: const Text('退出档案')))]))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildUserCard() => Container(width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]), child: Row(children: [CircleAvatar(radius: 32, backgroundColor: const Color(0xFFEDEBFF), child: const Icon(Icons.person, size: 40, color: Color(0xFF635BFF))), const SizedBox(width: 16), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [const Text('张三', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))), const SizedBox(height: 4), Text('42岁 · 男 · 175cm · 72kg', style: TextStyle(fontSize: 14, color: Colors.grey[500]))])), Icon(Icons.chevron_right, size: 24, color: Colors.grey[400])]));
|
Widget _buildUserCard() => Container(width: double.infinity, padding: const EdgeInsets.all(20), decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]), child: Row(children: [CircleAvatar(radius: 32, backgroundColor: const Color(0xFFE6FAF6), child: const Icon(Icons.person, size: 40, color: Color(0xFF14B8A6))), const SizedBox(width: 16), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [const Text('张三', style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))), const SizedBox(height: 4), Text('42岁 · 男 · 175cm · 72kg', style: TextStyle(fontSize: 14, color: Colors.grey[500]))])), Icon(Icons.chevron_right, size: 24, color: Colors.grey[400])]));
|
||||||
|
|
||||||
Widget _buildHealthOverview(AsyncValue<Map<String, dynamic>> healthData) {
|
Widget _buildHealthOverview(AsyncValue<Map<String, dynamic>> healthData) {
|
||||||
return Container(
|
return Container(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
padding: const EdgeInsets.all(20),
|
padding: const EdgeInsets.all(20),
|
||||||
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]),
|
decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
const Text('健康概览', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
const Text('健康概览', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text('(最近测量)', style: TextStyle(fontSize: 13, color: Colors.grey[500])),
|
Text('(最近测量)', style: TextStyle(fontSize: 13, color: Colors.grey[500])),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
healthData.when(data: (data) => _buildMetricsList(data), loading: () => const Center(child: Padding(padding: EdgeInsets.all(24), child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF635BFF)))), error: (_, __) => _buildMetricsEmpty()),
|
healthData.when(data: (data) => _buildMetricsList(data), loading: () => const Center(child: Padding(padding: EdgeInsets.all(24), child: CircularProgressIndicator(strokeWidth: 2, color: Color(0xFF14B8A6)))), error: (_, __) => _buildMetricsEmpty()),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -54,11 +54,11 @@ class ProfileDetailPage extends ConsumerWidget {
|
|||||||
String _formatBP(dynamic bp) { if (bp is Map) { final s = bp['systolic']; final d = bp['diastolic']; if (s != null && d != null) return '$s/$d'; } return '--/--'; }
|
String _formatBP(dynamic bp) { if (bp is Map) { final s = bp['systolic']; final d = bp['diastolic']; if (s != null && d != null) return '$s/$d'; } return '--/--'; }
|
||||||
String _formatMetric(dynamic val, String unit) { if (val is Map) { final v = val['value']; if (v != null) return '$v$unit'; } return '-- $unit'; }
|
String _formatMetric(dynamic val, String unit) { if (val is Map) { final v = val['value']; if (v != null) return '$v$unit'; } return '-- $unit'; }
|
||||||
|
|
||||||
Widget _metricRow(IconData icon, String label, String value) => InkWell(onTap: () {}, borderRadius: BorderRadius.circular(12), child: Padding(padding: const EdgeInsets.symmetric(vertical: 14), child: Row(children: [Container(width: 40, height: 40, decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF635BFF))), const SizedBox(width: 12), Expanded(child: Text(label, style: const TextStyle(fontSize: 15, color: Color(0xFF333333)))), Text(value, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const SizedBox(width: 8), Icon(Icons.chevron_right, size: 18, color: Colors.grey[400])])));
|
Widget _metricRow(IconData icon, String label, String value) => InkWell(onTap: () {}, borderRadius: BorderRadius.circular(12), child: Padding(padding: const EdgeInsets.symmetric(vertical: 14), child: Row(children: [Container(width: 40, height: 40, decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF14B8A6))), const SizedBox(width: 12), Expanded(child: Text(label, style: const TextStyle(fontSize: 15, color: Color(0xFF333333)))), Text(value, style: const TextStyle(fontSize: 17, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const SizedBox(width: 8), Icon(Icons.chevron_right, size: 18, color: Colors.grey[400])])));
|
||||||
|
|
||||||
Widget _buildHistoryList() {
|
Widget _buildHistoryList() {
|
||||||
final items = [{'date': '05-31', 'label': '血压 · 餐前', 'value': '128/82', 'status': 'normal'}, {'date': '05-30', 'label': '血压 · 餐后', 'value': '135/85', 'status': 'warning'}, {'date': '05-29', 'label': '血压 · 餐前', 'value': '122/78', 'status': 'normal'}, {'date': '05-28', 'label': '血压 · 餐前', 'value': '118/76', 'status': 'normal'}, {'date': '05-27', 'label': '血糖 · 空腹', 'value': '5.6', 'status': 'normal'}, {'date': '05-26', 'label': '血压 · 餐前', 'value': '120/80', 'status': 'normal'}];
|
final items = [{'date': '05-31', 'label': '血压 · 餐前', 'value': '128/82', 'status': 'normal'}, {'date': '05-30', 'label': '血压 · 餐后', 'value': '135/85', 'status': 'warning'}, {'date': '05-29', 'label': '血压 · 餐前', 'value': '122/78', 'status': 'normal'}, {'date': '05-28', 'label': '血压 · 餐前', 'value': '118/76', 'status': 'normal'}, {'date': '05-27', 'label': '血糖 · 空腹', 'value': '5.6', 'status': 'normal'}, {'date': '05-26', 'label': '血压 · 餐前', 'value': '120/80', 'status': 'normal'}];
|
||||||
return Container(decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]), child: Column(children: [Container(padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row(children: [const Text('历史记录', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const Spacer(), Text('查看更多', style: TextStyle(fontSize: 13, color: const Color(0xFF635BFF)))])), ...items.map(_historyItem)]));
|
return Container(decoration: BoxDecoration(color: Colors.white, borderRadius: BorderRadius.circular(20), boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 8, offset: const Offset(0, 2))]), child: Column(children: [Container(padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 16), child: Row(children: [const Text('历史记录', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const Spacer(), Text('查看更多', style: TextStyle(fontSize: 13, color: const Color(0xFF14B8A6)))])), ...items.map(_historyItem)]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _historyItem(Map<String, dynamic> item) {
|
Widget _historyItem(Map<String, dynamic> item) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ class ProfilePage extends ConsumerWidget {
|
|||||||
final user = auth.user;
|
final user = auth.user;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
body: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.only(bottom: 20), child: Column(children: [
|
body: SafeArea(child: SingleChildScrollView(padding: const EdgeInsets.only(bottom: 20), child: Column(children: [
|
||||||
Container(width: double.infinity, padding: const EdgeInsets.all(24), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24))), child: Column(children: [
|
Container(width: double.infinity, padding: const EdgeInsets.all(24), decoration: const BoxDecoration(color: Colors.white, borderRadius: BorderRadius.only(bottomLeft: Radius.circular(24), bottomRight: Radius.circular(24))), child: Column(children: [
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text('9:41', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800])), Row(children: [Icon(Icons.wifi, size: 18, color: Colors.grey[700]), const SizedBox(width: 4), Icon(Icons.battery_full, size: 18, color: Colors.grey[700])]),]),
|
Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [Text('9:41', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.grey[800])), Row(children: [Icon(Icons.wifi, size: 18, color: Colors.grey[700]), const SizedBox(width: 4), Icon(Icons.battery_full, size: 18, color: Colors.grey[700])]),]),
|
||||||
@@ -20,8 +20,8 @@ class ProfilePage extends ConsumerWidget {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () => pushRoute(ref, 'editProfile'),
|
onTap: () => pushRoute(ref, 'editProfile'),
|
||||||
child: Stack(children: [
|
child: Stack(children: [
|
||||||
CircleAvatar(radius: 32, backgroundColor: const Color(0xFFEDEBFF), backgroundImage: user?.avatarUrl != null ? NetworkImage(user!.avatarUrl!) : null, child: user?.avatarUrl == null ? const Icon(Icons.person, size: 40, color: Color(0xFF635BFF)) : null),
|
CircleAvatar(radius: 32, backgroundColor: const Color(0xFFE6FAF6), backgroundImage: user?.avatarUrl != null ? NetworkImage(user!.avatarUrl!) : null, child: user?.avatarUrl == null ? const Icon(Icons.person, size: 40, color: Color(0xFF14B8A6)) : null),
|
||||||
Positioned(right: 0, bottom: 0, child: Container(width: 22, height: 22, decoration: BoxDecoration(color: const Color(0xFF635BFF), borderRadius: BorderRadius.circular(11), border: Border.all(color: Colors.white, width: 2)), child: const Icon(Icons.edit, size: 12, color: Colors.white))),
|
Positioned(right: 0, bottom: 0, child: Container(width: 22, height: 22, decoration: BoxDecoration(color: const Color(0xFF14B8A6), borderRadius: BorderRadius.circular(11), border: Border.all(color: Colors.white, width: 2)), child: const Icon(Icons.edit, size: 12, color: Colors.white))),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
@@ -87,7 +87,7 @@ class _MenuItem extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 14),
|
||||||
decoration: BoxDecoration(color: Colors.white),
|
decoration: BoxDecoration(color: Colors.white),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Container(width: 36, height: 36, decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF635BFF))),
|
Container(width: 36, height: 36, decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF14B8A6))),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Text(title, style: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A))),
|
Text(title, style: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A))),
|
||||||
if (trailing != null && trailing!.isNotEmpty) ...[const Spacer(), Text(trailing!, style: TextStyle(fontSize: 14, color: Colors.grey[400]))],
|
if (trailing != null && trailing!.isNotEmpty) ...[const Spacer(), Text(trailing!, style: TextStyle(fontSize: 14, color: Colors.grey[400]))],
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
onPressed: () => _createDefaultPlan(ref, context),
|
onPressed: () => _createDefaultPlan(ref, context),
|
||||||
icon: const Icon(Icons.add),
|
icon: const Icon(Icons.add),
|
||||||
label: const Text('创建本周计划'),
|
label: const Text('创建本周计划'),
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
),
|
),
|
||||||
body: plan.when(
|
body: plan.when(
|
||||||
data: (data) {
|
data: (data) {
|
||||||
@@ -82,7 +82,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator(color: Color(0xFF635BFF))),
|
loading: () => const Center(child: CircularProgressIndicator(color: Color(0xFF14B8A6))),
|
||||||
error: (_, __) => _empty(context, '运动计划', '暂无运动计划,点击右下角创建'),
|
error: (_, __) => _empty(context, '运动计划', '暂无运动计划,点击右下角创建'),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -94,7 +94,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
margin: const EdgeInsets.all(16),
|
margin: const EdgeInsets.all(16),
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
),
|
),
|
||||||
child: Column(children: [
|
child: Column(children: [
|
||||||
@@ -105,7 +105,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
width: 60,
|
width: 60,
|
||||||
height: 60,
|
height: 60,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFF635BFF),
|
color: const Color(0xFF14B8A6),
|
||||||
borderRadius: BorderRadius.circular(30),
|
borderRadius: BorderRadius.circular(30),
|
||||||
),
|
),
|
||||||
child: Center(
|
child: Center(
|
||||||
@@ -123,7 +123,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
child: FractionallySizedBox(
|
child: FractionallySizedBox(
|
||||||
widthFactor: progress / 100,
|
widthFactor: progress / 100,
|
||||||
child: Container(
|
child: Container(
|
||||||
decoration: BoxDecoration(color: const Color(0xFF635BFF), borderRadius: BorderRadius.circular(4)),
|
decoration: BoxDecoration(color: const Color(0xFF14B8A6), borderRadius: BorderRadius.circular(4)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -152,7 +152,7 @@ class ExercisePlanPage extends ConsumerWidget {
|
|||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||||
content: Text('运动计划已创建 ✅'),
|
content: Text('运动计划已创建 ✅'),
|
||||||
backgroundColor: Color(0xFF635BFF),
|
backgroundColor: Color(0xFF14B8A6),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,21 +199,21 @@ class _ExercisePlanItem extends StatelessWidget {
|
|||||||
color: isToday ? const Color(0xFFFEFCE8) : Colors.white,
|
color: isToday ? const Color(0xFFFEFCE8) : Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: isToday ? Border.all(color: const Color(0xFFFCD34D), width: 2) : null,
|
border: isToday ? Border.all(color: const Color(0xFFFCD34D), width: 2) : null,
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(8), blurRadius: 4, offset: const Offset(0, 2))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(8), blurRadius: 4, offset: const Offset(0, 2))],
|
||||||
),
|
),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Container(
|
Container(
|
||||||
width: 40,
|
width: 40,
|
||||||
height: 40,
|
height: 40,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isDone ? const Color(0xFFDCFCE7) : isRest ? const Color(0xFFF3F4F6) : const Color(0xFFF5F3FF),
|
color: isDone ? const Color(0xFFDCFCE7) : isRest ? const Color(0xFFF3F4F6) : const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: isDone
|
child: isDone
|
||||||
? const Icon(Icons.check, size: 20, color: Color(0xFF43A047))
|
? const Icon(Icons.check, size: 20, color: Color(0xFF43A047))
|
||||||
: isRest
|
: isRest
|
||||||
? const Icon(Icons.coffee, size: 20, color: Color(0xFF999999))
|
? const Icon(Icons.coffee, size: 20, color: Color(0xFF999999))
|
||||||
: const Icon(Icons.directions_run, size: 20, color: Color(0xFF635BFF)),
|
: const Icon(Icons.directions_run, size: 20, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -235,7 +235,7 @@ class _ExercisePlanItem extends StatelessWidget {
|
|||||||
onPressed: onCheckIn,
|
onPressed: onCheckIn,
|
||||||
child: const Text('打卡'),
|
child: const Text('打卡'),
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
|
||||||
@@ -257,7 +257,7 @@ class FollowUpListPage extends ConsumerWidget {
|
|||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () => _showAddDialog(context),
|
onPressed: () => _showAddDialog(context),
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
),
|
),
|
||||||
body: ListView(children: _mockFollowUps.map((item) => _FollowUpItem(item: item)).toList()),
|
body: ListView(children: _mockFollowUps.map((item) => _FollowUpItem(item: item)).toList()),
|
||||||
);
|
);
|
||||||
@@ -284,7 +284,7 @@ class FollowUpListPage extends ConsumerWidget {
|
|||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||||
content: Text('复查提醒已添加 ✅'),
|
content: Text('复查提醒已添加 ✅'),
|
||||||
backgroundColor: Color(0xFF635BFF),
|
backgroundColor: Color(0xFF14B8A6),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
child: const Text('保存'),
|
child: const Text('保存'),
|
||||||
@@ -314,7 +314,7 @@ class _FollowUpItem extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
||||||
),
|
),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Row(children: [
|
Row(children: [
|
||||||
@@ -513,7 +513,7 @@ class _HealthCalendarPageState extends ConsumerState<HealthCalendarPage> {
|
|||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
decoration: isToday ? BoxDecoration(
|
decoration: isToday ? BoxDecoration(
|
||||||
color: const Color(0xFF635BFF),
|
color: const Color(0xFF14B8A6),
|
||||||
borderRadius: BorderRadius.circular(20),
|
borderRadius: BorderRadius.circular(20),
|
||||||
) : null,
|
) : null,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
@@ -555,7 +555,7 @@ class _HealthCalendarPageState extends ConsumerState<HealthCalendarPage> {
|
|||||||
|
|
||||||
Color _getEventColor(String type) {
|
Color _getEventColor(String type) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'medication': return const Color(0xFF635BFF);
|
case 'medication': return const Color(0xFF14B8A6);
|
||||||
case 'exercise': return const Color(0xFF43A047);
|
case 'exercise': return const Color(0xFF43A047);
|
||||||
case 'followup': return const Color(0xFFF59E0B);
|
case 'followup': return const Color(0xFFF59E0B);
|
||||||
default: return Colors.grey;
|
default: return Colors.grey;
|
||||||
@@ -564,7 +564,7 @@ class _HealthCalendarPageState extends ConsumerState<HealthCalendarPage> {
|
|||||||
|
|
||||||
Widget _buildLegend() {
|
Widget _buildLegend() {
|
||||||
final items = [
|
final items = [
|
||||||
{'color': const Color(0xFF635BFF), 'label': '用药提醒'},
|
{'color': const Color(0xFF14B8A6), 'label': '用药提醒'},
|
||||||
{'color': const Color(0xFF43A047), 'label': '运动计划'},
|
{'color': const Color(0xFF43A047), 'label': '运动计划'},
|
||||||
{'color': const Color(0xFFF59E0B), 'label': '复查随访'},
|
{'color': const Color(0xFFF59E0B), 'label': '复查随访'},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ class AiAnalysisPage extends ConsumerWidget {
|
|||||||
|
|
||||||
Widget _buildTitle() {
|
Widget _buildTitle() {
|
||||||
return Row(mainAxisSize: MainAxisSize.min, children: [
|
return Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
Container(padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration(color: const Color(0xFF635BFF).withAlpha(15), borderRadius: BorderRadius.circular(12)), child: Row(mainAxisSize: MainAxisSize.min, children: [const Icon(Icons.auto_awesome, size: 16, color: Color(0xFF635BFF)), const SizedBox(width: 4), const Text('AI预解读', style: TextStyle(fontSize: 13, color: Color(0xFF635BFF), fontWeight: FontWeight.w500))])),
|
Container(padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), decoration: BoxDecoration(color: const Color(0xFF14B8A6).withAlpha(15), borderRadius: BorderRadius.circular(12)), child: Row(mainAxisSize: MainAxisSize.min, children: [const Icon(Icons.auto_awesome, size: 16, color: Color(0xFF14B8A6)), const SizedBox(width: 4), const Text('AI预解读', style: TextStyle(fontSize: 13, color: Color(0xFF14B8A6), fontWeight: FontWeight.w500))])),
|
||||||
const SizedBox(width: 4), Text('血常规检查', style: TextStyle(color: Colors.grey[800], fontWeight: FontWeight.w600)),
|
const SizedBox(width: 4), Text('血常规检查', style: TextStyle(color: Colors.grey[800], fontWeight: FontWeight.w600)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildReportPreview() => Container(width: double.infinity, height: 180, decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(16), border: Border.all(color: const Color(0xFFE8E6FF), width: 1.5)), child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [Icon(Icons.description_outlined, size: 48, color: Colors.grey[400]), const SizedBox(height: 8), Text('检查报告图片', style: TextStyle(fontSize: 14, color: Colors.grey[600]))]));
|
Widget _buildReportPreview() => Container(width: double.infinity, height: 180, decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(16), border: Border.all(color: const Color(0xFFD4EDE8), width: 1.5)), child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [Icon(Icons.description_outlined, size: 48, color: Colors.grey[400]), const SizedBox(height: 8), Text('检查报告图片', style: TextStyle(fontSize: 14, color: Colors.grey[600]))]));
|
||||||
|
|
||||||
Widget _buildIndicators() {
|
Widget _buildIndicators() {
|
||||||
final indicators = [{'name': '红细胞 (RBC)', 'value': '4.68', 'unit': '(×10¹²/L)', 'ref': '4.0-5.50', 'status': 'normal'}, {'name': '白细胞 (WBC)', 'value': '6.55', 'unit': '(×10⁹/L)', 'ref': '3.5-9.50', 'status': 'normal'}, {'name': '血红蛋白 (HGB)', 'value': '135', 'unit': '(g/L)', 'ref': '120-175', 'status': 'normal'}, {'name': '血小板 (PLT)', 'value': '235', 'unit': '(×10⁹/L)', 'ref': '125-350', 'status': 'normal'}];
|
final indicators = [{'name': '红细胞 (RBC)', 'value': '4.68', 'unit': '(×10¹²/L)', 'ref': '4.0-5.50', 'status': 'normal'}, {'name': '白细胞 (WBC)', 'value': '6.55', 'unit': '(×10⁹/L)', 'ref': '3.5-9.50', 'status': 'normal'}, {'name': '血红蛋白 (HGB)', 'value': '135', 'unit': '(g/L)', 'ref': '120-175', 'status': 'normal'}, {'name': '血小板 (PLT)', 'value': '235', 'unit': '(×10⁹/L)', 'ref': '125-350', 'status': 'normal'}];
|
||||||
@@ -31,11 +31,11 @@ class AiAnalysisPage extends ConsumerWidget {
|
|||||||
return Container(margin: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.all(14), decoration: BoxDecoration(color: isNormal ? const Color(0xFFF8FDFB) : const Color(0xFFFFF8F5), borderRadius: BorderRadius.circular(14), border: Border.all(color: isNormal ? const Color(0xFFD4EDDA) : const Color(0xFFFFD7C5))), child: Row(children: [Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Text(item['name']?.toString() ?? '', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xFF333333))), const SizedBox(height: 4), Text('参考范围:${item['ref']?.toString() ?? ''}', style: TextStyle(fontSize: 12, color: Colors.grey[500]))])), Column(crossAxisAlignment: CrossAxisAlignment.end, children: [Text('${item['value']?.toString() ?? ''} ${item['unit']?.toString() ?? ''}', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))), const SizedBox(height: 2), Container(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration(color: isNormal ? const Color(0xFF43A047).withAlpha(20) : const Color(0xFFFF9800).withAlpha(20), borderRadius: BorderRadius.circular(8)), child: Text(isNormal ? '正常' : '偏高', style: TextStyle(fontSize: 11, color: isNormal ? const Color(0xFF43A047) : const Color(0xFFFF9800))))])]));
|
return Container(margin: const EdgeInsets.only(bottom: 10), padding: const EdgeInsets.all(14), decoration: BoxDecoration(color: isNormal ? const Color(0xFFF8FDFB) : const Color(0xFFFFF8F5), borderRadius: BorderRadius.circular(14), border: Border.all(color: isNormal ? const Color(0xFFD4EDDA) : const Color(0xFFFFD7C5))), child: Row(children: [Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Text(item['name']?.toString() ?? '', style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xFF333333))), const SizedBox(height: 4), Text('参考范围:${item['ref']?.toString() ?? ''}', style: TextStyle(fontSize: 12, color: Colors.grey[500]))])), Column(crossAxisAlignment: CrossAxisAlignment.end, children: [Text('${item['value']?.toString() ?? ''} ${item['unit']?.toString() ?? ''}', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold, color: Color(0xFF1A1A1A))), const SizedBox(height: 2), Container(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), decoration: BoxDecoration(color: isNormal ? const Color(0xFF43A047).withAlpha(20) : const Color(0xFFFF9800).withAlpha(20), borderRadius: BorderRadius.circular(8)), child: Text(isNormal ? '正常' : '偏高', style: TextStyle(fontSize: 11, color: isNormal ? const Color(0xFF43A047) : const Color(0xFFFF9800))))])]));
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildAiInterpretation() => Container(width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(16)), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Icon(Icons.auto_awesome, size: 18, color: const Color(0xFF635BFF)), const SizedBox(width: 6), Text('AI 智能解读', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const Spacer(), Container(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration(color: const Color(0xFF635BFF).withAlpha(15), borderRadius: BorderRadius.circular(10)), child: const Text('已分析', style: TextStyle(fontSize: 11, color: Color(0xFF635BFF))))]), const SizedBox(height: 12), const Text('您的血常规检查结果基本正常,各项指标均在参考范围内。红细胞、白细胞、血小板计数均处于健康水平,血红蛋白含量充足,说明您的造血功能和免疫功能良好。建议继续保持良好的生活习惯,定期复查。', style: TextStyle(fontSize: 14, height: 1.6, color: Color(0xFF444444)))]));
|
Widget _buildAiInterpretation() => Container(width: double.infinity, padding: const EdgeInsets.all(16), decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(16)), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Icon(Icons.auto_awesome, size: 18, color: const Color(0xFF14B8A6)), const SizedBox(width: 6), Text('AI 智能解读', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A))), const Spacer(), Container(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), decoration: BoxDecoration(color: const Color(0xFF14B8A6).withAlpha(15), borderRadius: BorderRadius.circular(10)), child: const Text('已分析', style: TextStyle(fontSize: 11, color: Color(0xFF14B8A6))))]), const SizedBox(height: 12), const Text('您的血常规检查结果基本正常,各项指标均在参考范围内。红细胞、白细胞、血小板计数均处于健康水平,血红蛋白含量充足,说明您的造血功能和免疫功能良好。建议继续保持良好的生活习惯,定期复查。', style: TextStyle(fontSize: 14, height: 1.6, color: Color(0xFF444444)))]));
|
||||||
|
|
||||||
Widget _buildDoctorAdvice() => Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [CircleAvatar(radius: 16, backgroundColor: const Color(0xFFEDEBFF), child: const Icon(Icons.local_hospital, size: 16, color: Color(0xFF635BFF))), const SizedBox(width: 8), const Text('医生建议', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)))]), const SizedBox(height: 12), Container(width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), border: Border.all(color: const Color(0xFFEEEEEE))), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [_adviceItem('李医生', '心内科', '各项指标正常,继续保持。注意低盐饮食,适当运动。'), const Divider(), _adviceItem('王医生', '全科', '血常规结果理想,无需特殊处理。下次体检可关注血脂指标.')]))]);
|
Widget _buildDoctorAdvice() => Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [CircleAvatar(radius: 16, backgroundColor: const Color(0xFFE6FAF6), child: const Icon(Icons.local_hospital, size: 16, color: Color(0xFF14B8A6))), const SizedBox(width: 8), const Text('医生建议', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)))]), const SizedBox(height: 12), Container(width: double.infinity, padding: const EdgeInsets.all(14), decoration: BoxDecoration(borderRadius: BorderRadius.circular(14), border: Border.all(color: const Color(0xFFEEEEEE))), child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [_adviceItem('李医生', '心内科', '各项指标正常,继续保持。注意低盐饮食,适当运动。'), const Divider(), _adviceItem('王医生', '全科', '血常规结果理想,无需特殊处理。下次体检可关注血脂指标.')]))]);
|
||||||
|
|
||||||
Widget _adviceItem(String name, String dept, String advice) => Padding(padding: const EdgeInsets.symmetric(vertical: 8), child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [CircleAvatar(radius: 14, backgroundColor: const Color(0xFFF5F3FF), child: Text(name[0], style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF635BFF)))), const SizedBox(width: 10), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Text(name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xFF333333))), const SizedBox(width: 6), Text(dept, style: TextStyle(fontSize: 12, color: Colors.grey[500]))]), const SizedBox(height: 4), Text(advice, style: TextStyle(fontSize: 13, color: Colors.grey[700], height: 1.4))]))]));
|
Widget _adviceItem(String name, String dept, String advice) => Padding(padding: const EdgeInsets.symmetric(vertical: 8), child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [CircleAvatar(radius: 14, backgroundColor: const Color(0xFFF2FAF9), child: Text(name[0], style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w600, color: Color(0xFF14B8A6)))), const SizedBox(width: 10), Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Text(name, style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500, color: Color(0xFF333333))), const SizedBox(width: 6), Text(dept, style: TextStyle(fontSize: 12, color: Colors.grey[500]))]), const SizedBox(height: 4), Text(advice, style: TextStyle(fontSize: 13, color: Colors.grey[700], height: 1.4))]))]));
|
||||||
|
|
||||||
Widget _buildHealthTips() => Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Icon(Icons.lightbulb_outline, size: 18, color: const Color(0xFFFFB800)), const SizedBox(width: 8), const Text('健康提示', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)))]), const SizedBox(height: 12), ...['定期进行血常规检查,建议每半年一次', '保持均衡饮食,多吃富含铁和维生素的食物', '适度运动,每周至少150分钟中等强度有氧运动', '保证充足睡眠,每晚7-8小时'].map((tip) => Padding(padding: const EdgeInsets.only(bottom: 8), child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [Container(margin: const EdgeInsets.only(top: 6), width: 6, height: 6, decoration: const BoxDecoration(color: Color(0xFFFFB800), shape: BoxShape.circle)), const SizedBox(width: 10), Expanded(child: Text(tip, style: TextStyle(fontSize: 14, color: Colors.grey[700], height: 1.4)))])))]);
|
Widget _buildHealthTips() => Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Row(children: [Icon(Icons.lightbulb_outline, size: 18, color: const Color(0xFFFFB800)), const SizedBox(width: 8), const Text('健康提示', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF1A1A1A)))]), const SizedBox(height: 12), ...['定期进行血常规检查,建议每半年一次', '保持均衡饮食,多吃富含铁和维生素的食物', '适度运动,每周至少150分钟中等强度有氧运动', '保证充足睡眠,每晚7-8小时'].map((tip) => Padding(padding: const EdgeInsets.only(bottom: 8), child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [Container(margin: const EdgeInsets.only(top: 6), width: 6, height: 6, decoration: const BoxDecoration(color: Color(0xFFFFB800), shape: BoxShape.circle)), const SizedBox(width: 10), Expanded(child: Text(tip, style: TextStyle(fontSize: 14, color: Colors.grey[700], height: 1.4)))])))]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -182,7 +182,7 @@ class ReportListPage extends ConsumerWidget {
|
|||||||
appBar: AppBar(title: const Text('看报告')),
|
appBar: AppBar(title: const Text('看报告')),
|
||||||
body: const Center(
|
body: const Center(
|
||||||
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
child: Column(mainAxisSize: MainAxisSize.min, children: [
|
||||||
CircularProgressIndicator(color: Color(0xFF635BFF)),
|
CircularProgressIndicator(color: Color(0xFF14B8A6)),
|
||||||
SizedBox(height: 16),
|
SizedBox(height: 16),
|
||||||
Text('AI 正在分析报告...'),
|
Text('AI 正在分析报告...'),
|
||||||
]),
|
]),
|
||||||
@@ -209,7 +209,7 @@ class ReportListPage extends ConsumerWidget {
|
|||||||
Widget _buildUploadButton(BuildContext context, WidgetRef ref) {
|
Widget _buildUploadButton(BuildContext context, WidgetRef ref) {
|
||||||
return FloatingActionButton(
|
return FloatingActionButton(
|
||||||
onPressed: () => _showUploadOptions(context, ref),
|
onPressed: () => _showUploadOptions(context, ref),
|
||||||
backgroundColor: const Color(0xFF635BFF),
|
backgroundColor: const Color(0xFF14B8A6),
|
||||||
child: const Icon(Icons.add),
|
child: const Icon(Icons.add),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -266,10 +266,10 @@ class ReportListPage extends ConsumerWidget {
|
|||||||
width: 120,
|
width: 120,
|
||||||
height: 120,
|
height: 120,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(60),
|
borderRadius: BorderRadius.circular(60),
|
||||||
),
|
),
|
||||||
child: const Icon(Icons.file_open, size: 48, color: Color(0xFF635BFF)),
|
child: const Icon(Icons.file_open, size: 48, color: Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
const Text('暂无检查报告', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
|
const Text('暂无检查报告', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500)),
|
||||||
@@ -285,14 +285,14 @@ class ReportListPage extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
boxShadow: [BoxShadow(color: const Color(0xFF635BFF).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
boxShadow: [BoxShadow(color: const Color(0xFF14B8A6).withAlpha(10), blurRadius: 4, offset: const Offset(0, 2))],
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: Container(
|
leading: Container(
|
||||||
width: 48,
|
width: 48,
|
||||||
height: 48,
|
height: 48,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
child: _getReportIcon(report.type),
|
child: _getReportIcon(report.type),
|
||||||
@@ -315,13 +315,13 @@ class ReportListPage extends ConsumerWidget {
|
|||||||
|
|
||||||
Widget _getReportIcon(String type) {
|
Widget _getReportIcon(String type) {
|
||||||
final icons = {
|
final icons = {
|
||||||
'血液检查': const Icon(Icons.bloodtype, size: 24, color: Color(0xFF635BFF)),
|
'血液检查': const Icon(Icons.bloodtype, size: 24, color: Color(0xFF14B8A6)),
|
||||||
'心电图': const Icon(Icons.monitor_heart, size: 24, color: Color(0xFF635BFF)),
|
'心电图': const Icon(Icons.monitor_heart, size: 24, color: Color(0xFF14B8A6)),
|
||||||
'超声检查': const Icon(Icons.image, size: 24, color: Color(0xFF635BFF)),
|
'超声检查': const Icon(Icons.image, size: 24, color: Color(0xFF14B8A6)),
|
||||||
'影像报告': const Icon(Icons.image, size: 24, color: Color(0xFF635BFF)),
|
'影像报告': const Icon(Icons.image, size: 24, color: Color(0xFF14B8A6)),
|
||||||
'PDF文档': const Icon(Icons.picture_as_pdf, size: 24, color: Color(0xFF635BFF)),
|
'PDF文档': const Icon(Icons.picture_as_pdf, size: 24, color: Color(0xFF14B8A6)),
|
||||||
};
|
};
|
||||||
return icons[type] ?? const Icon(Icons.description, size: 24, color: Color(0xFF635BFF));
|
return icons[type] ?? const Icon(Icons.description, size: 24, color: Color(0xFF14B8A6));
|
||||||
}
|
}
|
||||||
|
|
||||||
String _formatDate(DateTime date) {
|
String _formatDate(DateTime date) {
|
||||||
@@ -382,8 +382,8 @@ class ReportDetailPage extends ConsumerWidget {
|
|||||||
icon: const Icon(Icons.image),
|
icon: const Icon(Icons.image),
|
||||||
label: const Text('查看原始图片'),
|
label: const Text('查看原始图片'),
|
||||||
style: OutlinedButton.styleFrom(
|
style: OutlinedButton.styleFrom(
|
||||||
foregroundColor: const Color(0xFF635BFF),
|
foregroundColor: const Color(0xFF14B8A6),
|
||||||
side: const BorderSide(color: Color(0xFF635BFF)),
|
side: const BorderSide(color: Color(0xFF14B8A6)),
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -394,7 +394,7 @@ class ReportDetailPage extends ConsumerWidget {
|
|||||||
height: 48,
|
height: 48,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () => pushRoute(ref, 'aiAnalysis'),
|
onPressed: () => pushRoute(ref, 'aiAnalysis'),
|
||||||
style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFF635BFF), foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))),
|
style: ElevatedButton.styleFrom(backgroundColor: const Color(0xFF14B8A6), foregroundColor: Colors.white, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(24))),
|
||||||
child: const Text('查看 AI 智能解读'),
|
child: const Text('查看 AI 智能解读'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -408,7 +408,7 @@ class ReportDetailPage extends ConsumerWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF5F3FF),
|
color: const Color(0xFFF2FAF9),
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
),
|
),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
@@ -430,7 +430,7 @@ class ReportDetailPage extends ConsumerWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(16),
|
borderRadius: BorderRadius.circular(16),
|
||||||
border: Border.all(color: const Color(0xFFE8E6FF), width: 1.5),
|
border: Border.all(color: const Color(0xFFD4EDE8), width: 1.5),
|
||||||
),
|
),
|
||||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
|
||||||
Padding(
|
Padding(
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class NotificationPrefsPage extends ConsumerWidget {
|
|||||||
final dndOn = prefs['dndEnabled'] ?? false;
|
final dndOn = prefs['dndEnabled'] ?? false;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -107,7 +107,7 @@ class NotificationPrefsPage extends ConsumerWidget {
|
|||||||
_SwitchTile(
|
_SwitchTile(
|
||||||
icon: Icons.smart_toy_outlined,
|
icon: Icons.smart_toy_outlined,
|
||||||
iconBg: const Color(0xFFF3E5F5),
|
iconBg: const Color(0xFFF3E5F5),
|
||||||
iconColor: const Color(0xFF635BFF),
|
iconColor: const Color(0xFF14B8A6),
|
||||||
title: 'AI 回复通知',
|
title: 'AI 回复通知',
|
||||||
subtitle: 'AI 助手回复时发送通知',
|
subtitle: 'AI 助手回复时发送通知',
|
||||||
value: prefs['aiReply'] ?? false,
|
value: prefs['aiReply'] ?? false,
|
||||||
@@ -193,7 +193,7 @@ class _SwitchTile extends StatelessWidget {
|
|||||||
Text(title, style: const TextStyle(fontSize: 15, color: Color(0xFF1A1A1A), fontWeight: FontWeight.w500)),
|
Text(title, style: const TextStyle(fontSize: 15, color: Color(0xFF1A1A1A), fontWeight: FontWeight.w500)),
|
||||||
if (subtitle != null && subtitle!.isNotEmpty) Text(subtitle!, style: TextStyle(fontSize: 12, color: Colors.grey[500])),
|
if (subtitle != null && subtitle!.isNotEmpty) Text(subtitle!, style: TextStyle(fontSize: 12, color: Colors.grey[500])),
|
||||||
])),
|
])),
|
||||||
Switch(value: value, onChanged: onChanged, activeThumbColor: const Color(0xFF635BFF), activeTrackColor: const Color(0xFFC5BFFF)),
|
Switch(value: value, onChanged: onChanged, activeThumbColor: const Color(0xFF14B8A6), activeTrackColor: const Color(0xFFC5BFFF)),
|
||||||
]),
|
]),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -210,7 +210,7 @@ class _TimeButton extends StatelessWidget {
|
|||||||
return GestureDetector(onTap: onTap, child: Container(
|
return GestureDetector(onTap: onTap, child: Container(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10),
|
||||||
decoration: BoxDecoration(border: Border.all(color: const Color(0xFFE0E0E0)), borderRadius: BorderRadius.circular(10)),
|
decoration: BoxDecoration(border: Border.all(color: const Color(0xFFE0E0E0)), borderRadius: BorderRadius.circular(10)),
|
||||||
child: Column(children: [Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[500])), Text(time, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF635BFF)))]),
|
child: Column(children: [Text(label, style: TextStyle(fontSize: 11, color: Colors.grey[500])), Text(time, style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Color(0xFF14B8A6)))]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class SettingsPage extends ConsumerWidget {
|
|||||||
|
|
||||||
@override Widget build(BuildContext context, WidgetRef ref) {
|
@override Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF8F7FF),
|
backgroundColor: const Color(0xFFF6F9FB),
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
@@ -72,7 +72,7 @@ class _SetItem extends StatelessWidget {
|
|||||||
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 14),
|
||||||
decoration: BoxDecoration(color: Colors.white),
|
decoration: BoxDecoration(color: Colors.white),
|
||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Container(width: 36, height: 36, decoration: BoxDecoration(color: const Color(0xFFF5F3FF), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF635BFF))),
|
Container(width: 36, height: 36, decoration: BoxDecoration(color: const Color(0xFFF2FAF9), borderRadius: BorderRadius.circular(10)), child: Icon(icon, size: 18, color: const Color(0xFF14B8A6))),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Text(title, style: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A))), if (subtitle != null && subtitle!.isNotEmpty) Text(subtitle!, style: TextStyle(fontSize: 13, color: Colors.grey[500]))])),
|
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [Text(title, style: const TextStyle(fontSize: 16, color: Color(0xFF1A1A1A))), if (subtitle != null && subtitle!.isNotEmpty) Text(subtitle!, style: TextStyle(fontSize: 13, color: Colors.grey[500]))])),
|
||||||
if (trailingText != null && trailingText!.isNotEmpty) Text(trailingText!, style: TextStyle(fontSize: 14, color: Colors.grey[400])),
|
if (trailingText != null && trailingText!.isNotEmpty) Text(trailingText!, style: TextStyle(fontSize: 14, color: Colors.grey[400])),
|
||||||
|
|||||||
@@ -43,16 +43,16 @@ class AgentBar extends ConsumerWidget {
|
|||||||
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 6),
|
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 6),
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 14),
|
padding: const EdgeInsets.symmetric(horizontal: 14),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected ? const Color(0xFF635BFF) : Colors.white,
|
color: isSelected ? const Color(0xFF14B8A6) : Colors.white,
|
||||||
border: Border.all(color: const Color(0xFF635BFF)),
|
border: Border.all(color: const Color(0xFF14B8A6)),
|
||||||
borderRadius: BorderRadius.circular(24),
|
borderRadius: BorderRadius.circular(24),
|
||||||
),
|
),
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(icon, size: 16, color: isSelected ? Colors.white : const Color(0xFF635BFF)),
|
Icon(icon, size: 16, color: isSelected ? Colors.white : const Color(0xFF14B8A6)),
|
||||||
const SizedBox(width: 6),
|
const SizedBox(width: 6),
|
||||||
Text(label, style: TextStyle(fontSize: 13, color: isSelected ? Colors.white : const Color(0xFF635BFF))),
|
Text(label, style: TextStyle(fontSize: 13, color: isSelected ? Colors.white : const Color(0xFF14B8A6))),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ class HealthDrawer extends ConsumerWidget {
|
|||||||
onTap: () => pushRoute(ref, 'profile'),
|
onTap: () => pushRoute(ref, 'profile'),
|
||||||
child: CircleAvatar(
|
child: CircleAvatar(
|
||||||
radius: 28,
|
radius: 28,
|
||||||
backgroundColor: const Color(0xFFEDEBFF),
|
backgroundColor: const Color(0xFFE6FAF6),
|
||||||
child: Icon(Icons.person, size: 32, color: Theme.of(context).colorScheme.primary),
|
child: Icon(Icons.person, size: 32, color: Theme.of(context).colorScheme.primary),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -95,7 +95,7 @@ class HealthDrawer extends ConsumerWidget {
|
|||||||
child: Row(children: [
|
child: Row(children: [
|
||||||
Text('历史对话', style: Theme.of(context).textTheme.labelMedium!.copyWith(fontWeight: FontWeight.w600)),
|
Text('历史对话', style: Theme.of(context).textTheme.labelMedium!.copyWith(fontWeight: FontWeight.w600)),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
TextButton(onPressed: () => ref.invalidate(conversationListProvider), child: const Text('刷新', style: TextStyle(fontSize: 12, color: Color(0xFF635BFF)))),
|
TextButton(onPressed: () => ref.invalidate(conversationListProvider), child: const Text('刷新', style: TextStyle(fontSize: 12, color: Color(0xFF14B8A6)))),
|
||||||
]),
|
]),
|
||||||
),
|
),
|
||||||
conversations.when(
|
conversations.when(
|
||||||
@@ -162,10 +162,10 @@ class _HealthMetricChip extends StatelessWidget {
|
|||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
border: Border.all(color: const Color(0xFFEDEBFF)),
|
border: Border.all(color: const Color(0xFFE6FAF6)),
|
||||||
),
|
),
|
||||||
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
child: Row(mainAxisSize: MainAxisSize.min, children: [
|
||||||
Icon(icon, size: 14, color: const Color(0xFF635BFF)),
|
Icon(icon, size: 14, color: const Color(0xFF14B8A6)),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [
|
Column(crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, children: [
|
||||||
Text(label, style: TextStyle(fontSize: 10, color: Colors.grey[600])),
|
Text(label, style: TextStyle(fontSize: 10, color: Colors.grey[600])),
|
||||||
@@ -186,7 +186,7 @@ class _ConversationItem extends ConsumerWidget {
|
|||||||
return Container(
|
return Container(
|
||||||
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
margin: const EdgeInsets.symmetric(horizontal: 4, vertical: 2),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFF8F7FF),
|
color: const Color(0xFFF6F9FB),
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
),
|
),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
@@ -194,10 +194,10 @@ class _ConversationItem extends ConsumerWidget {
|
|||||||
width: 28,
|
width: 28,
|
||||||
height: 28,
|
height: 28,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: const Color(0xFFEDEBFF),
|
color: const Color(0xFFE6FAF6),
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(8),
|
||||||
),
|
),
|
||||||
child: Icon(_getAgentIcon(item.agent), size: 14, color: const Color(0xFF635BFF)),
|
child: Icon(_getAgentIcon(item.agent), size: 14, color: const Color(0xFF14B8A6)),
|
||||||
),
|
),
|
||||||
title: Text(item.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500)),
|
title: Text(item.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: const TextStyle(fontSize: 12, fontWeight: FontWeight.w500)),
|
||||||
subtitle: Text(item.lastMessage, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 10, color: Colors.grey[500])),
|
subtitle: Text(item.lastMessage, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle(fontSize: 10, color: Colors.grey[500])),
|
||||||
|
|||||||
Reference in New Issue
Block a user