import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:sales_chat/providers/auth_provider.dart'; import 'package:sales_chat/services/api_service.dart'; import 'package:sales_chat/theme/app_theme.dart'; /// 注册页面 —— 微信风格,简约现代 class RegisterPage extends StatefulWidget { const RegisterPage({super.key}); @override State createState() => _RegisterPageState(); } class _RegisterPageState extends State { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _emailController = TextEditingController(); final _nicknameController = TextEditingController(); final _passwordController = TextEditingController(); final _confirmPasswordController = TextEditingController(); final _inviteCodeController = TextEditingController(); bool _obscurePassword = true; bool _obscureConfirmPassword = true; @override void dispose() { _usernameController.dispose(); _emailController.dispose(); _nicknameController.dispose(); _passwordController.dispose(); _confirmPasswordController.dispose(); _inviteCodeController.dispose(); super.dispose(); } /// 处理注册请求 Future _handleRegister() async { if (!_formKey.currentState!.validate()) return; final authProvider = context.read(); final apiService = context.read(); final inviteCode = _inviteCodeController.text.trim(); final success = await authProvider.register( username: _usernameController.text.trim(), email: _emailController.text.trim(), nickname: _nicknameController.text.trim().isNotEmpty ? _nicknameController.text.trim() : null, password: _passwordController.text, ); if (success && mounted) { // 如果有邀请码,注册后自动加入群组 if (inviteCode.isNotEmpty) { try { await apiService.joinInvite(inviteCode); } catch (e) { // 加入群组失败不影响注册流程,静默处理 debugPrint('邀请码加入失败: $e'); } } 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: 32), Text( '注册', style: Theme.of(context).textTheme.headlineLarge?.copyWith( fontWeight: FontWeight.bold, color: AppTheme.textPrimary, fontSize: 28, ), textAlign: TextAlign.center, ), const SizedBox(height: 28), // 白色卡片容器 —— 表单区域 Container( padding: const EdgeInsets.symmetric( horizontal: 24, vertical: 24, ), decoration: BoxDecoration( color: AppTheme.cardBackground, borderRadius: BorderRadius.circular(12), ), child: Form( key: _formKey, child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // 用户名输入框 TextFormField( controller: _usernameController, decoration: const InputDecoration( labelText: '用户名', hintText: '3-20位,字母/数字/下划线', prefixIcon: Icon(Icons.person_outline), ), validator: (value) { if (value == null || value.isEmpty) { return '请输入用户名'; } if (!RegExp(r'^[a-zA-Z0-9_]{3,20}$').hasMatch(value)) { return '用户名:3-20位,字母/数字/下划线'; } return null; }, ), const SizedBox(height: 14), // 邮箱输入框 TextFormField( controller: _emailController, keyboardType: TextInputType.emailAddress, decoration: const InputDecoration( labelText: '邮箱', hintText: '请输入邮箱', prefixIcon: Icon(Icons.email_outlined), ), validator: (value) { if (value == null || value.isEmpty) { return '请输入邮箱'; } if (!value.contains('@')) { return '请输入有效的邮箱地址'; } return null; }, ), const SizedBox(height: 14), // 昵称输入框(可选) TextFormField( controller: _nicknameController, decoration: const InputDecoration( labelText: '昵称(可选)', hintText: '显示名称', prefixIcon: Icon(Icons.badge_outlined), ), ), const SizedBox(height: 14), // 密码输入框 TextFormField( controller: _passwordController, obscureText: _obscurePassword, decoration: InputDecoration( labelText: '密码', hintText: '至少6个字符', 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; }, ), const SizedBox(height: 14), // 确认密码输入框 TextFormField( controller: _confirmPasswordController, obscureText: _obscureConfirmPassword, decoration: InputDecoration( labelText: '确认密码', hintText: '再次输入密码', prefixIcon: const Icon(Icons.lock_outlined), suffixIcon: IconButton( icon: Icon( _obscureConfirmPassword ? Icons.visibility_off : Icons.visibility, ), onPressed: () { setState(() { _obscureConfirmPassword = !_obscureConfirmPassword; }); }, ), ), validator: (value) { if (value == null || value.isEmpty) { return '请确认密码'; } if (value != _passwordController.text) { return '两次密码不一致'; } return null; }, ), const SizedBox(height: 14), // 邀请码输入框(可选) TextFormField( controller: _inviteCodeController, decoration: const InputDecoration( labelText: '邀请码(可选)', hintText: '输入邀请码加入群组', prefixIcon: Icon(Icons.card_giftcard_outlined), ), ), const SizedBox(height: 24), // 注册按钮 Consumer( builder: (context, auth, _) { return ElevatedButton( onPressed: auth.isLoading ? null : _handleRegister, 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), // 返回登录链接 Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '已有账号?', style: TextStyle( color: AppTheme.textSecondary, fontSize: 14, ), ), TextButton( onPressed: () { Navigator.of(context).pushReplacementNamed('/login'); }, style: TextButton.styleFrom( padding: const EdgeInsets.symmetric(horizontal: 4), minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, ), child: const Text( '登录', style: TextStyle(fontSize: 14), ), ), ], ), ], ), ), ), ), ), ); } }