import 'package:flutter/material.dart';
import 'package:newdemo/pages/auth/register_page.dart';
import 'package:newdemo/pages/auth/reset_password.dart';
import 'package:supabase_flutter/supabase_flutter.dart';
import '../../services/supabase_service.dart';
class LoginPage extends StatefulWidget {
const LoginPage({super.key});
@override
State<LoginPage> createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
final _emailController = TextEditingController();
final _passwordController = TextEditingController();
bool _isLoading = false;
bool _obscurePassword = true;
final _formKey = GlobalKey<FormState>();
@override
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
Future<void> _signIn() async {
if (!_formKey.currentState!.validate()) return;
setState(() => _isLoading = true);
try {
// 使用Supabase进行邮箱/密码登录[^2]
final response = await Supabase.instance.client.auth.signInWithPassword(
email: _emailController.text.trim(),
password: _passwordController.text.trim(),
);
if (response.user != null) {
// 登录成功后导航到首页
if (mounted) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => const HomePage()),
);
}
}
} on AuthException catch (e) {
// 处理认证错误
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('登录失败: ${e.message}'),
backgroundColor: Colors.red,
),
);
}
} catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('登录失败,请稍后重试'),
backgroundColor: Colors.red,
),
);
}
} finally {
if (mounted) setState(() => _isLoading = false);
}
}
Future<void> _resetPassword() async {
final email = _emailController.text.trim();
if (email.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('请输入邮箱地址'),
backgroundColor: Colors.orange,
),
);
return;
}
setState(() => _isLoading = true);
try {
// 发送密码重置邮件[^2]
await Supabase.instance.client.auth.resetPasswordForEmail(email);
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('密码重置邮件已发送至 $email'),
backgroundColor: Colors.green,
),
);
}
} on AuthException catch (e) {
if (mounted) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('错误: ${e.message}'),
backgroundColor: Colors.red,
),
);
}
} finally {
if (mounted) setState(() => _isLoading = false);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xFF1E3A8A), Color(0xFF3B82F6)],
),
),
child: Center(
child: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Card(
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Form(
key: _formKey,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SizedBox(height: 16),
const FlutterLogo(size: 80),
const SizedBox(height: 24),
Text(
'欢迎回来',
style: Theme.of(context)
.textTheme
.headlineSmall
?.copyWith(
fontWeight: FontWeight.bold,
color: Colors.blueGrey[800],
),
),
const SizedBox(height: 8),
Text(
'使用您的账号登录',
style:
Theme.of(context).textTheme.bodyMedium?.copyWith(
color: Colors.grey[600],
),
),
const SizedBox(height: 32),
TextFormField(
controller: _emailController,
decoration: const InputDecoration(
labelText: '邮箱地址',
prefixIcon: Icon(Icons.email),
),
keyboardType: TextInputType.emailAddress,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入邮箱地址';
}
if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$')
.hasMatch(value)) {
return '请输入有效的邮箱地址';
}
return null;
},
),
const SizedBox(height: 20),
TextFormField(
controller: _passwordController,
decoration: InputDecoration(
labelText: '密码',
prefixIcon: const Icon(Icons.lock),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.grey,
),
onPressed: () {
setState(
() => _obscurePassword = !_obscurePassword);
},
),
),
obscureText: _obscurePassword,
validator: (value) {
if (value == null || value.isEmpty) {
return '请输入密码';
}
if (value.length < 6) {
return '密码长度至少为6位';
}
return null;
},
),
const SizedBox(height: 10),
Align(
alignment: Alignment.centerRight,
child: TextButton(
onPressed: _isLoading ? null : _resetPassword,
child: const Text(
'忘记密码?',
style: TextStyle(color: Color(0xFF3B82F6)),
),
),
),
const SizedBox(height: 24),
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: _isLoading ? null : _signIn,
child: _isLoading
? const SizedBox(
height: 24,
width: 24,
child: CircularProgressIndicator(
color: Colors.white,
strokeWidth: 2,
),
)
: const Text('登 录'),
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('没有账号?'),
TextButton(
onPressed: () {
// 导航到注册页面
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => RegisterPage(),
),
);
},
child: const Text(
'立即注册',
style: TextStyle(fontWeight: FontWeight.bold),
),
),
],
),
const SizedBox(height: 16),
],
),
),
),
),
),
),
),
),
);
}
}
在这个代码中加入保持登录状态的功能