import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:sales_chat/providers/auth_provider.dart'; import 'package:sales_chat/theme/app_theme.dart'; /// 登录页面 —— 微信风格,简约现代 class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final _formKey = GlobalKey(); final _accountController = TextEditingController(); final _passwordController = TextEditingController(); bool _obscurePassword = true; @override void dispose() { _accountController.dispose(); _passwordController.dispose(); super.dispose(); } /// 处理登录请求 Future _handleLogin() async { if (!_formKey.currentState!.validate()) return; final authProvider = context.read(); final account = _accountController.text.trim(); // 判断输入是邮箱还是用户名 final isEmail = account.contains('@'); final success = await authProvider.login( email: isEmail ? account : null, username: isEmail ? null : account, password: _passwordController.text, ); if (success && mounted) { Navigator.of(context).pushReplacementNamed('/home'); } } /// 访客登录弹窗 Future _handleGuestLogin() async { final nickname = await showDialog( context: context, builder: (context) { final controller = TextEditingController(); return AlertDialog( title: const Text('访客登录'), content: TextField( controller: controller, decoration: const InputDecoration( labelText: '昵称', hintText: '请输入昵称', ), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), ElevatedButton( onPressed: () => Navigator.pop(context, controller.text.trim()), child: const Text('登录'), ), ], ); }, ); if (nickname != null && nickname.isNotEmpty && mounted) { final authProvider = context.read(); final success = await authProvider.loginAsGuest(nickname: nickname); if (success && mounted) { Navigator.of(context).pushReplacementNamed('/home'); } } } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: AppTheme.scaffoldBackground, body: SafeArea( child: Center( child: SingleChildScrollView( padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 24), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Column( children: [ // 顶部品牌区域 const SizedBox(height: 48), Text( '销售聊天', style: Theme.of(context).textTheme.headlineLarge?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, fontSize: 28, ), textAlign: TextAlign.center, ), const SizedBox(height: 40), // 白色卡片容器 —— 表单区域 Container( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 28, ), decoration: BoxDecoration( color: AppTheme.cardBackground, borderRadius: BorderRadius.circular(12), ), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 账号输入框(邮箱或用户名) TextFormField( controller: _accountController, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration( labelText: '邮箱 / 用户名', hintText: '请输入邮箱或用户名', prefixIcon: Icon(Icons.person_outline), ), validator: (value) { if (value == null || value.isEmpty) { return '请输入邮箱或用户名'; } return null; }, ), const SizedBox(height: 14), // 密码输入框 TextFormField( controller: _passwordController, obscureText: _obscurePassword, decoration: InputDecoration( labelText: '密码', hintText: '请输入密码', prefixIcon: const Icon(Icons.lock_outlined), suffixIcon: IconButton( icon: Icon( _obscurePassword ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), ), validator: (value) { if (value == null || value.isEmpty) { return '请输入密码'; } if (value.length < 6) { return '密码至少需要6个字符'; } return null; }, onFieldSubmitted: (_) => _handleLogin(), ), const SizedBox(height: 24), // 登录按钮 Consumer( builder: (context, auth, _) { return ElevatedButton( onPressed: auth.isLoading ? null : _handleLogin, style: ElevatedButton.styleFrom( backgroundColor: AppTheme.primaryColor, padding: const EdgeInsets.symmetric(vertical: 14), shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(8), ), ), child: auth.isLoading ? const SizedBox( height: 20, width: 20, child: CircularProgressIndicator( strokeWidth: 2, valueColor: AlwaysStoppedAnimation( Colors.white), ), ) : const Text( '登录', style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, ), ), ); }, ), ], ), ), ), // 错误信息 —— 卡片下方,红色提示文字 Consumer( builder: (context, auth, _) { if (auth.error != null) { return Padding( padding: const EdgeInsets.only(top: 12), child: Text( auth.error!, style: TextStyle( color: AppTheme.errorColor, fontSize: 13, ), textAlign: TextAlign.center, ), ); } return const SizedBox.shrink(); }, ), const SizedBox(height: 20), // 访客登录 —— 文字按钮,低调 Consumer( builder: (context, auth, _) { return TextButton( onPressed: auth.isLoading ? null : _handleGuestLogin, style: TextButton.styleFrom( foregroundColor: AppTheme.textSecondary, ), child: const Text( '访客登录', style: TextStyle(fontSize: 14), ), ); }, ), const SizedBox(height: 8), // 注册链接 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '没有账号?', style: TextStyle( color: AppTheme.textSecondary, fontSize: 14, ), ), TextButton( onPressed: () { Navigator.of(context).pushReplacementNamed('/register'); }, style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 4), minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), child: const Text( '注册', style: TextStyle(fontSize: 14), ), ), ], ), ], ), ), ), ), ), ); } }