feat: UI 系统中心化 + 趋势图重构 + 法律文档 H5 上线
- UI 系统: 新增 design_tokens / module_visuals / app_buttons / app_status_badge / app_toast / ai_content 六个共享模块; 28 个页面接入, SnackBar 全部替换为 AppToast - 趋势图: 直线折线 + 渐变填充 + 阴影; 去网格线; X 轴日+月份分隔; Y 轴整数刻度最多 4 个; 点击数据点/录入记录显示上方浮层, 选中点变实心 - 法律文档 H5: 后端 wwwroot 托管隐私政策/服务协议/关于/个人信息收集清单/第三方 SDK 清单 + 索引页; Program.cs 启用 UseDefaultFiles + UseStaticFiles - 其他: auth_provider 登录流程调整; api_client IP 适配; 主页智能体栏间距优化
This commit is contained in:
@@ -2,6 +2,8 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
|
||||
import '../../core/app_colors.dart';
|
||||
import '../../core/app_design_tokens.dart';
|
||||
import '../../core/app_module_visuals.dart';
|
||||
import '../../core/app_theme.dart';
|
||||
import '../../core/navigation_provider.dart';
|
||||
import '../../providers/auth_provider.dart';
|
||||
@@ -36,10 +38,10 @@ class ProfilePage extends ConsumerWidget {
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
_ActionTile(
|
||||
icon: Icons.folder_shared_outlined,
|
||||
icon: AppModuleVisuals.health.icon,
|
||||
title: '健康档案',
|
||||
subtitle: '维护个人资料、病史、手术和过敏信息',
|
||||
color: const Color(0xFF8B5CF6),
|
||||
visual: AppModuleVisuals.health,
|
||||
onTap: () => pushRoute(ref, 'healthArchive'),
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
@@ -54,9 +56,7 @@ class ProfilePage extends ConsumerWidget {
|
||||
final ok = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(AppTheme.rLg),
|
||||
),
|
||||
shape: RoundedRectangleBorder(borderRadius: AppRadius.lgBorder),
|
||||
title: const Text('退出登录'),
|
||||
content: const Text('确定退出当前账号?'),
|
||||
actions: [
|
||||
@@ -91,12 +91,12 @@ class _AccountCard extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
padding: AppSpacing.panel,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: AppRadius.lgBorder,
|
||||
border: Border.all(color: AppColors.border, width: 1.1),
|
||||
boxShadow: [AppTheme.shadowLight],
|
||||
boxShadow: AppShadows.soft,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -110,21 +110,14 @@ class _AccountCard extends StatelessWidget {
|
||||
name,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
style: AppTextStyles.summaryTitle.copyWith(fontSize: 20),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Text(
|
||||
phone,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: AppColors.textSecondary,
|
||||
),
|
||||
style: AppTextStyles.listSubtitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -144,18 +137,13 @@ class _Avatar extends StatelessWidget {
|
||||
width: 58,
|
||||
height: 58,
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.iconBg,
|
||||
borderRadius: BorderRadius.circular(18),
|
||||
border: Border.all(color: AppColors.borderLight),
|
||||
gradient: AppModuleVisuals.health.gradient,
|
||||
borderRadius: AppRadius.lgBorder,
|
||||
),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: avatarUrl != null && avatarUrl!.isNotEmpty
|
||||
? Image.network(avatarUrl!, fit: BoxFit.cover)
|
||||
: const Icon(
|
||||
Icons.person_rounded,
|
||||
color: AppColors.blueMeasure,
|
||||
size: 34,
|
||||
),
|
||||
: const Icon(Icons.person_rounded, color: Colors.white, size: 34),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -163,30 +151,30 @@ class _ActionTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
final Color color;
|
||||
final AppModuleVisual visual;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const _ActionTile({
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
required this.color,
|
||||
required this.visual,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => Material(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: AppRadius.lgBorder,
|
||||
child: InkWell(
|
||||
onTap: onTap,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: AppRadius.lgBorder,
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(15),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
borderRadius: AppRadius.lgBorder,
|
||||
border: Border.all(color: AppColors.border, width: 1.1),
|
||||
boxShadow: [AppTheme.shadowLight],
|
||||
boxShadow: AppShadows.soft,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
@@ -194,42 +182,28 @@ class _ActionTile extends StatelessWidget {
|
||||
width: 46,
|
||||
height: 46,
|
||||
decoration: BoxDecoration(
|
||||
color: color.withValues(alpha: 0.10),
|
||||
borderRadius: BorderRadius.circular(14),
|
||||
gradient: visual.gradient,
|
||||
borderRadius: AppRadius.mdBorder,
|
||||
),
|
||||
child: Icon(icon, color: color, size: 24),
|
||||
child: Icon(icon, color: Colors.white, size: 24),
|
||||
),
|
||||
const SizedBox(width: 13),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
fontSize: 17,
|
||||
fontWeight: FontWeight.w800,
|
||||
color: AppColors.textPrimary,
|
||||
),
|
||||
),
|
||||
Text(title, style: AppTextStyles.listTitle),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
subtitle,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: AppColors.textSecondary,
|
||||
),
|
||||
style: AppTextStyles.listSubtitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const Icon(
|
||||
Icons.chevron_right_rounded,
|
||||
size: 22,
|
||||
color: AppColors.textHint,
|
||||
),
|
||||
const Icon(Icons.chevron_right_rounded, color: AppColors.textHint),
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -243,16 +217,13 @@ class _LogoutButton extends StatelessWidget {
|
||||
const _LogoutButton({required this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) => OutlinedButton.icon(
|
||||
Widget build(BuildContext context) => TextButton(
|
||||
onPressed: onPressed,
|
||||
icon: const Icon(Icons.logout_rounded, size: 19),
|
||||
label: const Text('退出登录'),
|
||||
style: OutlinedButton.styleFrom(
|
||||
style: TextButton.styleFrom(
|
||||
foregroundColor: AppColors.error,
|
||||
side: BorderSide(color: AppColors.error.withValues(alpha: 0.34)),
|
||||
minimumSize: const Size.fromHeight(52),
|
||||
textStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w800),
|
||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
textStyle: AppTextStyles.button,
|
||||
),
|
||||
child: const Text('退出登录'),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user