feat(auth): 隐藏验证码登录和注册功能
- 移除登录方式切换(验证码登录选项卡) - 隐藏注册入口 - 简化登录页面,仅保留密码登录 - 清理未使用的变量和方法 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
d31bfc4221
commit
d332ef99a7
|
|
@ -15,82 +15,31 @@ class LoginPage extends ConsumerStatefulWidget {
|
||||||
class _LoginPageState extends ConsumerState<LoginPage> {
|
class _LoginPageState extends ConsumerState<LoginPage> {
|
||||||
// 设计色彩 - 与导航页面统一
|
// 设计色彩 - 与导航页面统一
|
||||||
static const Color _orange = Color(0xFFFF6B00);
|
static const Color _orange = Color(0xFFFF6B00);
|
||||||
static const Color _darkText = Color(0xFF1F2937);
|
|
||||||
static const Color _grayText = Color(0xFF6B7280);
|
|
||||||
static const Color _lightGray = Color(0xFF9CA3AF);
|
|
||||||
static const Color _bgGray = Color(0xFFF3F4F6);
|
|
||||||
static const Color _borderGray = Color(0xFFE5E7EB);
|
|
||||||
|
|
||||||
final _formKey = GlobalKey<FormState>();
|
final _formKey = GlobalKey<FormState>();
|
||||||
final _phoneController = TextEditingController();
|
final _phoneController = TextEditingController();
|
||||||
final _passwordController = TextEditingController();
|
final _passwordController = TextEditingController();
|
||||||
final _smsCodeController = TextEditingController();
|
|
||||||
|
|
||||||
bool _isPasswordLogin = true;
|
|
||||||
bool _obscurePassword = true;
|
bool _obscurePassword = true;
|
||||||
int _countDown = 0;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_phoneController.dispose();
|
_phoneController.dispose();
|
||||||
_passwordController.dispose();
|
_passwordController.dispose();
|
||||||
_smsCodeController.dispose();
|
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _sendSmsCode() async {
|
|
||||||
final phone = _phoneController.text.trim();
|
|
||||||
if (phone.isEmpty || !RegExp(r'^1[3-9]\d{9}$').hasMatch(phone)) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('请输入正确的手机号')),
|
|
||||||
);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await ref.read(userNotifierProvider.notifier).sendSmsCode(phone, 'LOGIN');
|
|
||||||
setState(() => _countDown = 60);
|
|
||||||
_startCountDown();
|
|
||||||
if (mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('验证码已发送')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (mounted) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
SnackBar(content: Text('发送失败: $e')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _startCountDown() {
|
|
||||||
Future.delayed(const Duration(seconds: 1), () {
|
|
||||||
if (_countDown > 0 && mounted) {
|
|
||||||
setState(() => _countDown--);
|
|
||||||
_startCountDown();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _login() async {
|
Future<void> _login() async {
|
||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
|
|
||||||
final phone = _phoneController.text.trim();
|
final phone = _phoneController.text.trim();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (_isPasswordLogin) {
|
// 仅支持密码登录
|
||||||
await ref.read(userNotifierProvider.notifier).loginWithPassword(
|
await ref.read(userNotifierProvider.notifier).loginWithPassword(
|
||||||
phone,
|
phone,
|
||||||
_passwordController.text,
|
_passwordController.text,
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
await ref.read(userNotifierProvider.notifier).loginWithSms(
|
|
||||||
phone,
|
|
||||||
_smsCodeController.text.trim(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
context.go(Routes.contribution);
|
context.go(Routes.contribution);
|
||||||
|
|
@ -163,68 +112,7 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
||||||
|
|
||||||
const SizedBox(height: 48),
|
const SizedBox(height: 48),
|
||||||
|
|
||||||
// 登录方式切换
|
// 仅显示密码登录(验证码登录已隐藏)
|
||||||
Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(color: AppColors.borderOf(context), width: 1),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => setState(() => _isPasswordLogin = true),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: _isPasswordLogin ? _orange : Colors.transparent,
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'密码登录',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: _isPasswordLogin ? FontWeight.bold : FontWeight.normal,
|
|
||||||
color: _isPasswordLogin ? _orange : AppColors.textMutedOf(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () => setState(() => _isPasswordLogin = false),
|
|
||||||
child: Container(
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
border: Border(
|
|
||||||
bottom: BorderSide(
|
|
||||||
color: !_isPasswordLogin ? _orange : Colors.transparent,
|
|
||||||
width: 2,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
'验证码登录',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: !_isPasswordLogin ? FontWeight.bold : FontWeight.normal,
|
|
||||||
color: !_isPasswordLogin ? _orange : AppColors.textMutedOf(context),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
|
|
||||||
|
|
@ -265,107 +153,44 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// 密码/验证码
|
// 密码输入
|
||||||
if (_isPasswordLogin)
|
TextFormField(
|
||||||
TextFormField(
|
controller: _passwordController,
|
||||||
controller: _passwordController,
|
obscureText: _obscurePassword,
|
||||||
obscureText: _obscurePassword,
|
style: TextStyle(color: AppColors.textPrimaryOf(context)),
|
||||||
style: TextStyle(color: AppColors.textPrimaryOf(context)),
|
decoration: InputDecoration(
|
||||||
decoration: InputDecoration(
|
labelText: '密码',
|
||||||
labelText: '密码',
|
labelStyle: TextStyle(color: AppColors.textSecondaryOf(context)),
|
||||||
labelStyle: TextStyle(color: AppColors.textSecondaryOf(context)),
|
prefixIcon: Icon(Icons.lock_outline, color: AppColors.textSecondaryOf(context)),
|
||||||
prefixIcon: Icon(Icons.lock_outline, color: AppColors.textSecondaryOf(context)),
|
suffixIcon: IconButton(
|
||||||
suffixIcon: IconButton(
|
icon: Icon(
|
||||||
icon: Icon(
|
_obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined,
|
||||||
_obscurePassword ? Icons.visibility_off_outlined : Icons.visibility_outlined,
|
color: AppColors.textSecondaryOf(context),
|
||||||
color: AppColors.textSecondaryOf(context),
|
|
||||||
),
|
|
||||||
onPressed: () => setState(() => _obscurePassword = !_obscurePassword),
|
|
||||||
),
|
),
|
||||||
border: OutlineInputBorder(
|
onPressed: () => setState(() => _obscurePassword = !_obscurePassword),
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: const BorderSide(color: _orange, width: 2),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: AppColors.cardOf(context),
|
|
||||||
),
|
),
|
||||||
validator: (value) {
|
border: OutlineInputBorder(
|
||||||
if (value == null || value.isEmpty) {
|
borderRadius: BorderRadius.circular(12),
|
||||||
return '请输入密码';
|
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
||||||
}
|
),
|
||||||
return null;
|
enabledBorder: OutlineInputBorder(
|
||||||
},
|
borderRadius: BorderRadius.circular(12),
|
||||||
)
|
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
||||||
else
|
),
|
||||||
Row(
|
focusedBorder: OutlineInputBorder(
|
||||||
children: [
|
borderRadius: BorderRadius.circular(12),
|
||||||
Expanded(
|
borderSide: const BorderSide(color: _orange, width: 2),
|
||||||
child: TextFormField(
|
),
|
||||||
controller: _smsCodeController,
|
filled: true,
|
||||||
keyboardType: TextInputType.number,
|
fillColor: AppColors.cardOf(context),
|
||||||
maxLength: 6,
|
|
||||||
style: TextStyle(color: AppColors.textPrimaryOf(context)),
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: '验证码',
|
|
||||||
labelStyle: TextStyle(color: AppColors.textSecondaryOf(context)),
|
|
||||||
prefixIcon: Icon(Icons.sms_outlined, color: AppColors.textSecondaryOf(context)),
|
|
||||||
counterText: '',
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
|
||||||
),
|
|
||||||
enabledBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: BorderSide(color: AppColors.borderOf(context)),
|
|
||||||
),
|
|
||||||
focusedBorder: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
borderSide: const BorderSide(color: _orange, width: 2),
|
|
||||||
),
|
|
||||||
filled: true,
|
|
||||||
fillColor: AppColors.cardOf(context),
|
|
||||||
),
|
|
||||||
validator: (value) {
|
|
||||||
if (value == null || value.isEmpty) {
|
|
||||||
return '请输入验证码';
|
|
||||||
}
|
|
||||||
if (value.length != 6) {
|
|
||||||
return '验证码为6位';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(width: 12),
|
|
||||||
SizedBox(
|
|
||||||
width: 120,
|
|
||||||
height: 56,
|
|
||||||
child: ElevatedButton(
|
|
||||||
onPressed: _countDown > 0 ? null : _sendSmsCode,
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
backgroundColor: _countDown > 0 ? AppColors.backgroundOf(context) : _orange.withOpacity(isDark ? 0.2 : 0.1),
|
|
||||||
foregroundColor: _countDown > 0 ? AppColors.textMutedOf(context) : _orange,
|
|
||||||
elevation: 0,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Text(
|
|
||||||
_countDown > 0 ? '${_countDown}s' : '获取验证码',
|
|
||||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
validator: (value) {
|
||||||
|
if (value == null || value.isEmpty) {
|
||||||
|
return '请输入密码';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
const SizedBox(height: 32),
|
const SizedBox(height: 32),
|
||||||
|
|
||||||
|
|
@ -405,40 +230,18 @@ class _LoginPageState extends ConsumerState<LoginPage> {
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// 忘记密码
|
// 忘记密码
|
||||||
if (_isPasswordLogin)
|
Align(
|
||||||
Align(
|
alignment: Alignment.centerRight,
|
||||||
alignment: Alignment.centerRight,
|
child: TextButton(
|
||||||
child: TextButton(
|
onPressed: () => context.push(Routes.forgotPassword),
|
||||||
onPressed: () => context.push(Routes.forgotPassword),
|
child: Text(
|
||||||
child: Text(
|
'忘记密码?',
|
||||||
'忘记密码?',
|
|
||||||
style: TextStyle(color: AppColors.textSecondaryOf(context)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 8),
|
|
||||||
|
|
||||||
// 注册入口
|
|
||||||
Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'还没有账号?',
|
|
||||||
style: TextStyle(color: AppColors.textSecondaryOf(context)),
|
style: TextStyle(color: AppColors.textSecondaryOf(context)),
|
||||||
),
|
),
|
||||||
TextButton(
|
),
|
||||||
onPressed: () => context.push(Routes.register),
|
|
||||||
child: const Text(
|
|
||||||
'立即注册',
|
|
||||||
style: TextStyle(
|
|
||||||
color: _orange,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
|
||||||
|
// 注册入口已隐藏
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue