import 'package:flutter/material.dart'; import 'package:shadcn_ui/shadcn_ui.dart'; import 'package:provider/provider.dart'; import '../../../providers/auth_provider.dart'; import '../main/main_page.dart'; import 'register_page.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final formKey = GlobalKey(); static const _maxFormWidth = 400.0; static const _logoSize = 64.0; static const _loadingIndicatorSize = 16.0; @override Widget build(BuildContext context) { final theme = ShadTheme.of(context); return Scaffold( body: Center( child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: _maxFormWidth), child: Padding( padding: const EdgeInsets.all(24), child: ShadForm( key: formKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ _buildHeader(theme), const SizedBox(height: 48), _buildUsernameField(), const SizedBox(height: 16), _buildPasswordField(), const SizedBox(height: 24), _buildLoginButton(), const SizedBox(height: 16), _buildRegisterLink(theme), ], ), ), ), ), ), ); } Widget _buildHeader(ShadThemeData theme) { return Column( children: [ Icon( LucideIcons.trendingUp, size: _logoSize, color: theme.colorScheme.primary, ), const SizedBox(height: 24), Text( '模拟所', style: theme.textTheme.h1, textAlign: TextAlign.center, ), const SizedBox(height: 8), Text( '虚拟货币模拟交易平台', style: theme.textTheme.muted, textAlign: TextAlign.center, ), ], ); } Widget _buildUsernameField() { return ShadInputFormField( id: 'username', label: const Text('用户名'), placeholder: const Text('请输入用户名'), leading: const Icon(LucideIcons.user), validator: _validateUsername, ); } Widget _buildPasswordField() { return ShadInputFormField( id: 'password', label: const Text('密码'), placeholder: const Text('请输入密码'), obscureText: true, leading: const Icon(LucideIcons.lock), validator: _validatePassword, ); } Widget _buildLoginButton() { return Consumer( builder: (context, auth, _) { return ShadButton( onPressed: auth.isLoading ? null : () => _handleLogin(auth), child: auth.isLoading ? const SizedBox.square( dimension: _loadingIndicatorSize, child: CircularProgressIndicator( strokeWidth: 2, color: Colors.white, ), ) : const Text('登录'), ); }, ); } Widget _buildRegisterLink(ShadThemeData theme) { return Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '还没有账号?', style: theme.textTheme.muted, ), ShadButton.link( onPressed: _navigateToRegister, child: const Text('立即注册'), ), ], ); } // Validators String? _validateUsername(String? value) { if (value == null || value.isEmpty) { return '请输入用户名'; } if (value.length < 3) { return '用户名至少 3 个字符'; } return null; } String? _validatePassword(String? value) { if (value == null || value.isEmpty) { return '请输入密码'; } if (value.length < 6) { return '密码至少 6 个字符'; } return null; } // Actions Future _handleLogin(AuthProvider auth) async { if (!formKey.currentState!.saveAndValidate()) return; final values = formKey.currentState!.value; final response = await auth.login( values['username'], values['password'], ); if (!mounted) return; if (response.success) { _navigateToMainPage(); } else { _showErrorDialog(response.message ?? '用户名或密码错误'); } } void _navigateToMainPage() { Navigator.of(context).pushAndRemoveUntil( MaterialPageRoute(builder: (_) => const MainPage()), (route) => false, ); } void _navigateToRegister() { Navigator.push( context, MaterialPageRoute(builder: (context) => const RegisterPage()), ); } void _showErrorDialog(String message) { showShadDialog( context: context, builder: (context) => ShadDialog.alert( title: const Text('登录失败'), description: Text(message), actions: [ ShadButton( child: const Text('确定'), onPressed: () => Navigator.of(context).pop(), ), ], ), ); } }