import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; import '../../../core/theme/app_color_scheme.dart'; import '../../../core/theme/app_spacing.dart'; import '../../../providers/auth_provider.dart'; import '../../../providers/theme_provider.dart'; import '../auth/login_page.dart'; /// 菜单项数据模型 class _MenuItem { final IconData icon; final String title; final String? subtitle; final VoidCallback onTap; const _MenuItem({ required this.icon, required this.title, this.subtitle, required this.onTap, }); } /// 我的页面 - 使用 shadcn_ui 现代化设计 class MinePage extends StatefulWidget { const MinePage({super.key}); @override State createState() => _MinePageState(); } class _MinePageState extends State with AutomaticKeepAliveClientMixin { @override bool get wantKeepAlive => true; @override Widget build(BuildContext context) { super.build(context); return Scaffold( body: Consumer( builder: (context, auth, _) { return SingleChildScrollView( padding: AppSpacing.pagePadding, child: Column( children: [ _UserCard(user: auth.user), SizedBox(height: AppSpacing.md), _MenuList(onShowComingSoon: _showComingSoon, onShowAbout: _showAboutDialog), SizedBox(height: AppSpacing.lg), _LogoutButton(onLogout: () => _handleLogout(auth)), ], ), ); }, ), ); } void _showComingSoon(String feature) { showShadDialog( context: context, builder: (context) => ShadDialog.alert( title: Row( children: [ const Icon(LucideIcons.construction, color: Color(0xFFFF9800), size: 20), SizedBox(width: AppSpacing.sm), const Text('功能开发中'), ], ), description: Text('$feature功能正在开发中,敬请期待~'), actions: [ ShadButton( child: const Text('知道了'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } void _showAboutDialog() { final theme = ShadTheme.of(context); showShadDialog( context: context, builder: (context) => ShadDialog( title: Row( children: [ _AppLogo(radius: 20, fontSize: 20), SizedBox(width: AppSpacing.sm + AppSpacing.xs), const Text('模拟所'), ], ), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('虚拟货币模拟交易平台', style: theme.textTheme.muted), SizedBox(height: AppSpacing.md), _InfoRow(icon: LucideIcons.code, text: '版本: 1.0.0'), SizedBox(height: AppSpacing.sm), const _InfoRow(icon: LucideIcons.heart, text: 'Built with Flutter & shadcn_ui'), ], ), actions: [ ShadButton( child: const Text('确定'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } void _handleLogout(AuthProvider auth) { showShadDialog( context: context, builder: (ctx) => ShadDialog.alert( title: const Text('确认退出'), description: const Text('确定要退出登录吗?'), actions: [ ShadButton.outline( child: const Text('取消'), onPressed: () => Navigator.of(ctx).pop(), ), ShadButton.destructive( child: const Text('退出'), onPressed: () async { Navigator.of(ctx).pop(); await auth.logout(); if (ctx.mounted) { Navigator.of(ctx).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const LoginPage()), (route) => false, ); } }, ), ], ), ); } } /// 用户卡片组件 class _UserCard extends StatelessWidget { final dynamic user; const _UserCard({required this.user}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return ShadCard( padding: EdgeInsets.all(AppSpacing.lg + AppSpacing.sm), child: Row( children: [ _AppLogo(radius: 32, fontSize: 24, text: user?.avatarText), SizedBox(width: AppSpacing.md), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( user?.username ?? '未登录', style: theme.textTheme.h3.copyWith(fontWeight: FontWeight.bold), ), SizedBox(height: AppSpacing.sm - AppSpacing.xs), ShadBadge( backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.2), child: Text( '普通用户', style: TextStyle(fontSize: 12, color: theme.colorScheme.primary), ), ), ], ), ), Icon(LucideIcons.chevronRight, color: theme.colorScheme.mutedForeground), ], ), ); } } /// 应用 Logo 组件 class _AppLogo extends StatelessWidget { final double radius; final double fontSize; final String? text; const _AppLogo({required this.radius, required this.fontSize, this.text}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return CircleAvatar( radius: radius, backgroundColor: theme.colorScheme.primary.withValues(alpha: 0.2), child: Text( text ?? '₿', style: TextStyle( fontSize: fontSize, color: theme.colorScheme.primary, fontWeight: FontWeight.bold, ), ), ); } } /// 信息行组件 class _InfoRow extends StatelessWidget { final IconData icon; final String text; const _InfoRow({required this.icon, required this.text}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return Row( children: [ Icon(icon, size: 14, color: theme.colorScheme.mutedForeground), SizedBox(width: AppSpacing.sm - AppSpacing.xs), Text(text, style: theme.textTheme.muted.copyWith(fontSize: 12)), ], ); } } /// 菜单列表组件 class _MenuList extends StatelessWidget { final void Function(String) onShowComingSoon; final VoidCallback onShowAbout; const _MenuList({required this.onShowComingSoon, required this.onShowAbout}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); final themeProvider = context.watch(); return ShadCard( padding: EdgeInsets.zero, child: Column( children: [ // 主题切换开关(特殊处理) _ThemeToggleTile(isDarkMode: themeProvider.isDarkMode), Divider(color: theme.colorScheme.border, height: 1, indent: 56), // 普通菜单项 for (var i = 0; i < _buildMenuItems().length; i++) ...[ _MenuItemTile(item: _buildMenuItems()[i]), if (i < _buildMenuItems().length - 1) Divider(color: theme.colorScheme.border, height: 1, indent: 56), ], ], ), ); } List<_MenuItem> _buildMenuItems() { return [ _MenuItem(icon: LucideIcons.userCheck, title: '实名认证', subtitle: '完成实名认证,解锁更多功能', onTap: () => onShowComingSoon('实名认证')), _MenuItem(icon: LucideIcons.shield, title: '安全设置', subtitle: '密码、二次验证等安全设置', onTap: () => onShowComingSoon('安全设置')), _MenuItem(icon: LucideIcons.bell, title: '消息通知', subtitle: '管理消息推送设置', onTap: () => onShowComingSoon('消息通知')), _MenuItem(icon: LucideIcons.settings, title: '系统设置', subtitle: '主题、语言等偏好设置', onTap: () => onShowComingSoon('系统设置')), _MenuItem(icon: LucideIcons.info, title: '关于我们', subtitle: '版本信息与用户协议', onTap: onShowAbout), ]; } } /// 主题切换组件 class _ThemeToggleTile extends StatelessWidget { final bool isDarkMode; const _ThemeToggleTile({required this.isDarkMode}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); final themeProvider = context.read(); return InkWell( onTap: () => themeProvider.toggleTheme(), child: Padding( padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + AppSpacing.xs), child: Row( children: [ _MenuIcon(icon: isDarkMode ? LucideIcons.moon : LucideIcons.sun), SizedBox(width: AppSpacing.sm + AppSpacing.xs), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('深色模式', style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w500)), SizedBox(height: AppSpacing.xs / 2), Text( isDarkMode ? '当前:深色主题' : '当前:浅色主题', style: theme.textTheme.muted.copyWith(fontSize: 11), ), ], ), ), Switch( value: isDarkMode, onChanged: (_) => themeProvider.toggleTheme(), activeTrackColor: theme.colorScheme.primary.withValues(alpha: 0.5), activeColor: theme.colorScheme.primary, ), ], ), ), ); } } /// 菜单项组件 class _MenuItemTile extends StatelessWidget { final _MenuItem item; const _MenuItemTile({required this.item}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return InkWell( onTap: item.onTap, child: Padding( padding: EdgeInsets.symmetric(horizontal: AppSpacing.md, vertical: AppSpacing.sm + AppSpacing.xs), child: Row( children: [ _MenuIcon(icon: item.icon), SizedBox(width: AppSpacing.sm + AppSpacing.xs), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(item.title, style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w500)), if (item.subtitle != null) ...[ SizedBox(height: AppSpacing.xs / 2), Text(item.subtitle!, style: theme.textTheme.muted.copyWith(fontSize: 11)), ], ], ), ), Icon(LucideIcons.chevronRight, size: 18, color: theme.colorScheme.mutedForeground), ], ), ), ); } } /// 菜单图标组件 class _MenuIcon extends StatelessWidget { final IconData icon; const _MenuIcon({required this.icon}); @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return Container( width: 40, height: 40, decoration: BoxDecoration( color: theme.colorScheme.primary.withValues(alpha: 0.1), borderRadius: BorderRadius.circular(AppRadius.md + AppSpacing.xs), ), child: Icon(icon, size: 20, color: theme.colorScheme.primary), ); } } /// 退出登录按钮 class _LogoutButton extends StatelessWidget { final VoidCallback onLogout; const _LogoutButton({required this.onLogout}); @override Widget build(BuildContext context) { return SizedBox( width: double.infinity, height: 48, child: ShadButton.destructive( onPressed: onLogout, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Icon(LucideIcons.logOut, size: 18), SizedBox(width: AppSpacing.sm), const Text('退出登录', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600)), ], ), ), ); } }