import 'package:autosos_flutter/api/_api_client.dart'; import 'package:autosos_flutter/model/user.dart'; import 'package:autosos_flutter/provider/providers.dart'; import 'package:autosos_flutter/router/app_router.dart'; import 'package:autosos_flutter/util/sp_util.dart'; import 'package:autosos_flutter/widget/multi_state_view.dart'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; /// 我的中心(对应 Android MeFragment) class MePage extends ConsumerStatefulWidget { const MePage({super.key}); @override ConsumerState createState() => _MePageState(); } class _MePageState extends ConsumerState { MultiState _state = MultiState.loading; UserInfo? _user; @override void initState() { super.initState(); _load(); } Future _load() async { setState(() => _state = MultiState.loading); try { final resp = await ref.read(userApiProvider).info(); if (!mounted) return; if (!resp.isSuccess || resp.data == null) { setState(() => _state = MultiState.error); return; } ref.read(currentUserProvider.notifier).state = resp.data; setState(() { _user = resp.data; _state = MultiState.success; }); } catch (e) { if (mounted) setState(() => _state = MultiState.error); } } Future _logout() async { final ok = await showDialog( context: context, builder: (ctx) => AlertDialog( title: const Text('退出登录'), content: const Text('确定要退出当前账号吗?'), actions: [ TextButton( onPressed: () => Navigator.pop(ctx, false), child: const Text('取消'), ), ElevatedButton( style: ElevatedButton.styleFrom(backgroundColor: Colors.red), onPressed: () => Navigator.pop(ctx, true), child: const Text('退出'), ), ], ), ); if (ok != true) return; EasyLoading.show(status: '退出中…'); try { await ref.read(userApiProvider).logout(); } catch (_) {} // 清 token + sp SPUtil().remove('accessToken'); SPUtil().remove('user'); ApiClient.instance.clearToken(); ref.read(accessTokenProvider.notifier).state = null; ref.read(currentUserProvider.notifier).state = null; EasyLoading.dismiss(); if (mounted) context.go(Routes.login); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.grey.shade100, body: RefreshIndicator( onRefresh: _load, child: MultiStateView( state: _state, onRetry: _load, child: _user == null ? const SizedBox.shrink() : ListView( children: [ _header(_user!), const SizedBox(height: 8), _statsRow(_user!), const SizedBox(height: 8), _menu(), const SizedBox(height: 24), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: OutlinedButton.icon( onPressed: _logout, icon: const Icon(Icons.logout, color: Colors.red), label: const Text( '退出登录', style: TextStyle(color: Colors.red), ), style: OutlinedButton.styleFrom( side: const BorderSide(color: Colors.red), minimumSize: const Size.fromHeight(44), ), ), ), ], ), ), ), ); } Widget _header(UserInfo u) { return Container( padding: const EdgeInsets.fromLTRB(16, 36, 16, 16), decoration: BoxDecoration( gradient: LinearGradient( colors: [Colors.red.shade400, Colors.red.shade700], ), ), child: Row( children: [ CircleAvatar( radius: 32, backgroundColor: Colors.white, child: u.avatar != null && u.avatar!.isNotEmpty ? ClipOval( child: CachedNetworkImage( imageUrl: u.avatar!, width: 60, height: 60, fit: BoxFit.cover, ), ) : Text( (u.realName?.isNotEmpty == true ? u.realName![0] : (u.username?.isNotEmpty == true ? u.username![0] : '?')) .toUpperCase(), style: const TextStyle( fontSize: 24, color: Colors.red, fontWeight: FontWeight.bold, ), ), ), const SizedBox(width: 12), Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( u.realName ?? u.username ?? '—', style: const TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), ), const SizedBox(height: 4), Row( children: [ Text(u.phone ?? '—', style: const TextStyle(color: Colors.white70)), const SizedBox(width: 8), _badge(u.authStatus ?? 'none'), ], ), if (u.company != null && u.company!.isNotEmpty) ...[ const SizedBox(height: 4), Text(u.company!, style: const TextStyle(color: Colors.white70)), ], ], ), ), IconButton( onPressed: () => context.push(Routes.setting), icon: const Icon(Icons.settings, color: Colors.white), ), ], ), ); } Widget _badge(String status) { Color bg; String text; switch (status) { case 'personal': bg = Colors.blue; text = '个人认证'; break; case 'enterprise': bg = Colors.purple; text = '企业认证'; break; case 'driver': bg = Colors.orange; text = '司机认证'; break; default: bg = Colors.grey; text = '未认证'; } return Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: bg, borderRadius: BorderRadius.circular(4), ), child: Text(text, style: const TextStyle(color: Colors.white, fontSize: 11)), ); } Widget _statsRow(UserInfo u) { return Container( color: Colors.white, padding: const EdgeInsets.symmetric(vertical: 12), child: Row( children: [ _stat('余额', '¥${u.balance?.toStringAsFixed(2) ?? "0.00"}'), _divider(), _stat('今日订单', '${u.todayOrders ?? 0}'), _divider(), _stat('累计订单', '${u.totalOrders ?? 0}'), ], ), ); } Widget _stat(String label, String value) { return Expanded( child: Column( children: [ Text(value, style: const TextStyle( fontSize: 18, fontWeight: FontWeight.bold, color: Colors.red, )), const SizedBox(height: 2), Text(label, style: const TextStyle(fontSize: 12, color: Colors.grey)), ], ), ); } Widget _divider() => Container(width: 1, height: 30, color: Colors.grey.shade300); Widget _menu() { return Container( color: Colors.white, child: Column( children: [ _menuItem(Icons.account_balance_wallet, '提现', () { context.push(Routes.withdrawal); }), _menuItem(Icons.history, '提现记录', () { context.push(Routes.withdrawalRecord); }), _menuItem(Icons.payment, '充值', () { context.push(Routes.recharge); }), _menuItem(Icons.list_alt, '金额明细', () { context.push(Routes.amountList); }), _dividerLine(), _menuItem(Icons.edit, '完善资料', () { context.push(Routes.perfect); }), _menuItem(Icons.verified_user, '认证', () { context.push(Routes.auth); }), _dividerLine(), _menuItem(Icons.message, '消息中心', () { context.push(Routes.messenger); }), _menuItem(Icons.bug_report, '问题反馈', () { context.push(Routes.feedback); }), _menuItem(Icons.tune, '性能优化', () { context.push(Routes.optimization); }), ], ), ); } Widget _menuItem(IconData icon, String label, VoidCallback onTap) { return InkWell( onTap: onTap, child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), child: Row( children: [ Icon(icon, color: Colors.red, size: 22), const SizedBox(width: 12), Expanded(child: Text(label, style: const TextStyle(fontSize: 15))), const Icon(Icons.chevron_right, color: Colors.grey), ], ), ), ); } Widget _dividerLine() => Divider( height: 1, thickness: 1, color: Colors.grey.shade200, indent: 16, ); }