feat: UI 清新风全面改造 — 朝露主题 + shadcn_ui + 全局字号放大

- 全新"朝露"主题:深青绿主色(#2D6A4F),暖白底,完整设计Token
- 引入 shadcn_ui 组件库,MaterialApp 注入 ShadTheme
- 新增 4 个公共组件:AppCard、AppMenuItem、AppEmptyState、AppTabChip
- 全面消除硬编码颜色,统一使用 AppTheme Token
- 全局字号 +3~4pt,图标等比放大 +3px
- home/medication/profile/settings/login 等核心页面重写
- 路由和功能逻辑零改动
This commit is contained in:
MingNian
2026-06-08 18:06:18 +08:00
parent 16d1d3d305
commit 58af5f6d5b
28 changed files with 1616 additions and 812 deletions

View File

@@ -1,6 +1,7 @@
import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../../core/app_theme.dart';
import '../../providers/auth_provider.dart';
import '../../providers/data_providers.dart';
@@ -109,7 +110,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
builder: (ctx) => Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(ctx).viewInsets.bottom, left: 20, right: 20, top: 20),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Text('录入$_name', style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w700)),
Text('录入$_name', style: const TextStyle(fontSize: 21, fontWeight: FontWeight.w700)),
const SizedBox(height: 16),
if (_isBP) ...[
Row(children: [
@@ -155,7 +156,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
},
style: ElevatedButton.styleFrom(backgroundColor: _color, foregroundColor: Colors.white,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), padding: const EdgeInsets.symmetric(vertical: 14)),
child: const Text('确认录入', style: TextStyle(fontSize: 16)),
child: const Text('确认录入', style: TextStyle(fontSize: 19)),
)),
const SizedBox(height: 20),
]),
@@ -165,7 +166,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
@override Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color(0xFFF8F9FC),
backgroundColor: AppTheme.bg,
appBar: AppBar(title: const Text('健康概览'), centerTitle: true),
floatingActionButton: FloatingActionButton(
onPressed: _showAddDialog,
@@ -173,7 +174,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
child: const Icon(Icons.add),
),
body: _loading
? const Center(child: CircularProgressIndicator(color: Color(0xFF6C5CE7)))
? const Center(child: CircularProgressIndicator(color: AppTheme.primary))
: RefreshIndicator(
onRefresh: _loadAll,
child: SingleChildScrollView(
@@ -211,7 +212,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
border: Border.all(color: sel ? color : const Color(0xFFE0E0E0)),
),
child: Text(m['label'] as String, style: TextStyle(
fontSize: 14, fontWeight: FontWeight.w600,
fontSize: 17, fontWeight: FontWeight.w600,
color: sel ? Colors.white : const Color(0xFF666666)),
),
),
@@ -230,7 +231,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
const SizedBox(height: 8),
Text('暂无$_name数据', style: const TextStyle(color: Color(0xFFBBBBBB))),
const SizedBox(height: 4),
const Text('点击右下角 + 手动录入', style: TextStyle(fontSize: 12, color: Color(0xFFCCCCCC))),
const Text('点击右下角 + 手动录入', style: TextStyle(fontSize: 15, color: Color(0xFFCCCCCC))),
])),
);
}
@@ -258,11 +259,11 @@ class _TrendPageState extends ConsumerState<TrendPage> {
child: Column(children: [
Row(children: [
const SizedBox(width: 8),
Text(_name, style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600, color: _color)),
Text(_name, style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600, color: _color)),
const SizedBox(width: 6),
Text('趋势 (${_filtered.length}条)', style: const TextStyle(fontSize: 12, color: Color(0xFF999999))),
Text('趋势 (${_filtered.length}条)', style: const TextStyle(fontSize: 15, color: Color(0xFF999999))),
const Spacer(),
Text('单位: $_unit', style: const TextStyle(fontSize: 11, color: Color(0xFFBBBBBB))),
Text('单位: $_unit', style: const TextStyle(fontSize: 14, color: Color(0xFFBBBBBB))),
]),
const SizedBox(height: 10),
SizedBox(
@@ -280,7 +281,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
leftTitles: AxisTitles(sideTitles: SideTitles(
showTitles: true, reservedSize: 40,
getTitlesWidget: (v, meta) => Text(v.toStringAsFixed(v.truncateToDouble() == v ? 0 : 1),
style: const TextStyle(fontSize: 10, color: Color(0xFF999999))),
style: const TextStyle(fontSize: 13, color: Color(0xFF999999))),
)),
bottomTitles: AxisTitles(sideTitles: SideTitles(
showTitles: true, reservedSize: 24,
@@ -289,7 +290,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
final idx = v.toInt();
if (idx < 0 || idx >= _filtered.length) return const SizedBox.shrink();
final d = _filtered[idx]['date'] as DateTime;
return Text('${d.month}/${d.day}', style: const TextStyle(fontSize: 9, color: Color(0xFFBBBBBB)));
return Text('${d.month}/${d.day}', style: const TextStyle(fontSize: 12, color: Color(0xFFBBBBBB)));
},
)),
topTitles: const AxisTitles(sideTitles: SideTitles(showTitles: false)),
@@ -321,7 +322,7 @@ class _TrendPageState extends ConsumerState<TrendPage> {
final v = _isBP ? '${r['systolic']}/${r['diastolic']}' : '${r['value']}';
return LineTooltipItem(
'${d.month}/${d.day} ${d.hour}:${d.minute.toString().padLeft(2, '0')}\n$v $_unit',
TextStyle(color: _color, fontSize: 12, fontWeight: FontWeight.w600),
TextStyle(color: _color, fontSize: 15, fontWeight: FontWeight.w600),
);
}).toList(),
),
@@ -338,9 +339,9 @@ class _TrendPageState extends ConsumerState<TrendPage> {
if (_filtered.isEmpty) return const SizedBox.shrink();
return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Row(children: [
const Text('历史记录', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w700)),
const Text('历史记录', style: TextStyle(fontSize: 19, fontWeight: FontWeight.w700)),
const Spacer(),
Text('${_filtered.length}', style: const TextStyle(fontSize: 13, color: Color(0xFF999999))),
Text('${_filtered.length}', style: const TextStyle(fontSize: 16, color: Color(0xFF999999))),
]),
const SizedBox(height: 10),
..._filtered.reversed.take(30).map((r) {
@@ -359,20 +360,20 @@ class _TrendPageState extends ConsumerState<TrendPage> {
child: Row(children: [
Container(width: 40, height: 40, decoration: BoxDecoration(
color: _color.withAlpha(20), borderRadius: BorderRadius.circular(10)),
child: Center(child: Text(_getMetricIcon(_selected), style: const TextStyle(fontSize: 18))),
child: Center(child: Text(_getMetricIcon(_selected), style: const TextStyle(fontSize: 21))),
),
const SizedBox(width: 12),
Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [
Text('${date.month}${date.day}${date.hour}:${date.minute.toString().padLeft(2, '0')}',
style: const TextStyle(fontSize: 12, color: Color(0xFF999999))),
style: const TextStyle(fontSize: 15, color: Color(0xFF999999))),
const SizedBox(height: 2),
Text('$display $_unit', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w700,
Text('$display $_unit', style: TextStyle(fontSize: 23, fontWeight: FontWeight.w700,
color: abnormal ? const Color(0xFFEF4444) : const Color(0xFF1A1A1A))),
])),
if (abnormal)
Container(padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3),
decoration: BoxDecoration(color: const Color(0xFFFEE2E2), borderRadius: BorderRadius.circular(6)),
child: const Text('异常', style: TextStyle(fontSize: 11, color: Color(0xFFEF4444), fontWeight: FontWeight.w500))),
child: const Text('异常', style: TextStyle(fontSize: 14, color: Color(0xFFEF4444), fontWeight: FontWeight.w500))),
]),
);
}),