import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import '../../core/network/api_exception.dart'; import '../../core/theme/app_theme.dart'; import '../../providers/auth_provider.dart'; import '../../services/auth_service.dart'; /// 登录页:账号(手机号/邮箱,含@自动识别)+ 密码登录 class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @override ConsumerState createState() => _LoginScreenState(); } class _LoginScreenState extends ConsumerState { final _phone = TextEditingController(); final _password = TextEditingController(); bool _loading = false; String? _error; Future _submit() async { final account = _phone.text.trim(); final password = _password.text; if (account.isEmpty || password.isEmpty) { setState(() => _error = '请输入账号和密码'); return; } setState(() { _loading = true; _error = null; }); try { // 含 @ 视为邮箱登录,否则手机号登录(服务端两种都支持密码登录) final isEmail = account.contains('@'); final result = await AuthService.login( type: isEmail ? 'email_password' : 'phone_password', phone: isEmail ? null : account, email: isEmail ? account : null, password: password, ); await ref.read(authProvider.notifier).onLoginSuccess(result.user); if (mounted) context.go('/home'); } on ApiException catch (e) { setState(() => _error = e.message); } catch (_) { setState(() => _error = '网络异常,请稍后重试'); } finally { if (mounted) setState(() => _loading = false); } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('登录')), body: SafeArea( child: ListView( padding: const EdgeInsets.all(24), children: [ const SizedBox(height: 32), const Text( '欢迎回来', style: TextStyle(fontSize: 26, fontWeight: FontWeight.w700), ), const SizedBox(height: 32), TextField( controller: _phone, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration(hintText: '手机号 / 邮箱'), ), const SizedBox(height: 16), TextField( controller: _password, obscureText: true, decoration: const InputDecoration(hintText: '密码'), ), if (_error != null) ...[ const SizedBox(height: 12), Text(_error!, style: const TextStyle(color: AppColors.primary, fontSize: 13)), ], const SizedBox(height: 24), ElevatedButton( onPressed: _loading ? null : _submit, child: _loading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : const Text('登录'), ), const SizedBox(height: 16), TextButton( onPressed: () => context.push('/register'), child: const Text( '没有账号?去注册', style: TextStyle(color: AppColors.textSecondary), ), ), ], ), ), ); } }