import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import '../../providers/auth_provider.dart'; import '../../theme/colors.dart'; class LoginScreen extends ConsumerStatefulWidget { const LoginScreen({super.key}); @override ConsumerState createState() => _LoginScreenState(); } class _LoginScreenState extends ConsumerState { final _phoneController = TextEditingController(); final _passwordController = TextEditingController(); final _formKey = GlobalKey(); @override void dispose() { _phoneController.dispose(); _passwordController.dispose(); super.dispose(); } String? _validatePhone(String? value) { if (value == null || value.isEmpty) { return '请输入手机号'; } if (value.length != 11) { return '手机号必须为11位'; } return null; } String? _validatePassword(String? value) { if (value == null || value.isEmpty) { return '请输入密码'; } if (value.length < 6) { return '密码至少6位'; } return null; } Future _handleLogin() async { if (!_formKey.currentState!.validate()) return; final phone = _phoneController.text; final password = _passwordController.text; await ref.read(authProvider.notifier).login(phone, password); final authState = ref.read(authProvider); if (authState.isLoggedIn && mounted) { Navigator.pop(context); } } @override Widget build(BuildContext context) { final authState = ref.watch(authProvider); final isLoading = authState.isLoading; return Scaffold( body: Container( decoration: const BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ Color(0xFFFF6B35), Color(0xFFFF9F5B), ], ), ), child: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 32), child: Form( key: _formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text( '登录', style: TextStyle( fontSize: 32, fontWeight: FontWeight.bold, color: Colors.white, ), ), const SizedBox(height: 8), const Text( '欢迎回来', style: TextStyle( fontSize: 16, color: Colors.white70, ), ), const SizedBox(height: 48), _buildGlassInput( child: TextFormField( controller: _phoneController, keyboardType: TextInputType.phone, style: const TextStyle(color: AppColors.textPrimary), decoration: const InputDecoration( hintText: '请输入手机号', hintStyle: TextStyle(color: AppColors.textSecondary), border: InputBorder.none, prefixIcon: Icon(Icons.phone_android, color: AppColors.brand), ), inputFormatters: [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(11), ], validator: _validatePhone, ), ), const SizedBox(height: 16), _buildGlassInput( child: TextFormField( controller: _passwordController, obscureText: true, style: const TextStyle(color: AppColors.textPrimary), decoration: const InputDecoration( hintText: '请输入密码', hintStyle: TextStyle(color: AppColors.textSecondary), border: InputBorder.none, prefixIcon: Icon(Icons.lock_outline, color: AppColors.brand), ), validator: _validatePassword, ), ), const SizedBox(height: 32), SizedBox( width: double.infinity, height: 56, child: ElevatedButton( onPressed: isLoading ? null : _handleLogin, style: ElevatedButton.styleFrom( backgroundColor: Colors.white, foregroundColor: AppColors.brand, disabledBackgroundColor: Colors.white.withOpacity(0.6), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(16), ), elevation: 0, ), child: isLoading ? const Text( '登录中...', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ) : const Text( '登录', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ), ), if (authState.error != null) ...[ const SizedBox(height: 16), Text( authState.error!, style: const TextStyle( color: Colors.white, fontSize: 14, ), ), ], ], ), ), ), ), ), ), ); } Widget _buildGlassInput({required Widget child}) { return Container( decoration: BoxDecoration( color: Colors.white.withOpacity(0.8), borderRadius: BorderRadius.circular(14), border: Border.all(color: Colors.white.withOpacity(0.8)), boxShadow: [ BoxShadow( color: AppColors.brand.withOpacity(0.06), blurRadius: 32, offset: const Offset(0, 8), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(14), child: BackdropFilter( filter: ImageFilter.blur(sigmaX: 30, sigmaY: 30), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), child: child, ), ), ), ); } }