import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:provider/provider.dart'; import '../../auth/models/user_model.dart'; import '../../auth/services/auth_provider.dart'; import '../../../config/app_routes.dart'; /// 个人中心页面(对应 Issue #79:个人中心) /// /// 展示当前登录用户信息 + 功能菜单(个人信息/消息/设置/帮助/关于)+ 退出登录。 class ProfilePage extends StatelessWidget { const ProfilePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('个人中心')), body: Consumer( builder: (context, auth, _) { final user = auth.currentUser; return ListView( children: [ _UserHeader(user: user), const SizedBox(height: 8), _MenuGroup(items: const [ _MenuItem(icon: Icons.person_outline, title: '个人信息'), _MenuItem(icon: Icons.notifications_outlined, title: '我的消息'), _MenuItem(icon: Icons.settings_outlined, title: '设置'), ]), const SizedBox(height: 8), _MenuGroup(items: const [ _MenuItem(icon: Icons.help_outline, title: '帮助与反馈'), _MenuItem(icon: Icons.info_outline, title: '关于'), ]), const SizedBox(height: 16), _LogoutButton(onLogout: () => _handleLogout(context, auth)), const SizedBox(height: 24), ], ); }, ), ); } Future _handleLogout(BuildContext context, AuthProvider auth) async { final confirmed = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('退出登录'), content: const Text('确定要退出当前账号吗?'), actions: [ TextButton(onPressed: () => Navigator.of(ctx).pop(false), child: const Text('取消')), TextButton( onPressed: () => Navigator.of(ctx).pop(true), child: const Text('退出', style: TextStyle(color: Colors.red)), ), ], ), ); if (confirmed == true) { await auth.logout(); // 登出后跳转登录页(go_router 守卫也会拦截,这里显式跳转) if (context.mounted) { GoRouter.of(context).go(AppRoutes.login); } } } } /// 用户信息头部(头像 + 姓名 + 角色/部门) class _UserHeader extends StatelessWidget { final UserModel? user; const _UserHeader({this.user}); @override Widget build(BuildContext context) { final name = user?.name ?? '未登录'; final role = user?.role ?? ''; final department = user?.department; final phone = user?.phone; return Container( width: double.infinity, padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 16), color: Theme.of(context).colorScheme.primary, child: Column( children: [ CircleAvatar( radius: 40, backgroundColor: Colors.white24, child: _buildAvatar(user, name), ), const SizedBox(height: 12), Text(name, style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: Colors.white)), if (role.isNotEmpty) ...[ const SizedBox(height: 4), Text(_roleLabel(role), style: const TextStyle(color: Colors.white70)), ], if (department != null || phone != null) ...[ const SizedBox(height: 4), Text( [department, phone].whereType().join(' · '), style: const TextStyle(color: Colors.white60, fontSize: 13), ), ], ], ), ); } String _roleLabel(String role) { const map = {'admin': '管理员', 'inspector': '巡检员', 'operator': '操作员'}; return map[role] ?? role; } /// 头像:有 avatar 用网络图,否则取姓名首字 Widget _buildAvatar(UserModel? user, String name) { final avatar = user?.avatar; if (avatar != null && avatar.isNotEmpty) { return ClipOval(child: Image.network(avatar, width: 80, height: 80, fit: BoxFit.cover)); } return Text( name.isNotEmpty ? name.substring(0, 1) : '?', style: const TextStyle(fontSize: 32, color: Colors.white), ); } } /// 菜单组(带卡片容器) class _MenuGroup extends StatelessWidget { final List<_MenuItem> items; const _MenuGroup({required this.items}); @override Widget build(BuildContext context) { return Card( margin: const EdgeInsets.symmetric(horizontal: 12), child: Column( children: [ for (int i = 0; i < items.length; i++) ...[ items[i], if (i < items.length - 1) const Divider(height: 1, indent: 56), ], ], ), ); } } /// 单个菜单项(占位 onTap,待后续接入具体页面) class _MenuItem extends StatelessWidget { final IconData icon; final String title; final VoidCallback? onTap; const _MenuItem({required this.icon, required this.title, this.onTap}); @override Widget build(BuildContext context) { return ListTile( leading: Icon(icon, color: Theme.of(context).colorScheme.primary), title: Text(title), trailing: const Icon(Icons.chevron_right, color: Colors.grey), onTap: onTap ?? () => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('$title(待实现)'))), ); } } /// 退出登录按钮 class _LogoutButton extends StatelessWidget { final VoidCallback onLogout; const _LogoutButton({required this.onLogout}); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 12), child: OutlinedButton.icon( onPressed: onLogout, icon: const Icon(Icons.logout, color: Colors.red), label: const Text('退出登录', style: TextStyle(color: Colors.red)), style: OutlinedButton.styleFrom( minimumSize: const Size(double.infinity, 48), side: const BorderSide(color: Colors.red), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), ), ); } }