Browse Source

refactor(登录): 移除验证码视图并简化控制器状态管理

移除登录流程中的验证码输入页面,将登录简化为单一步骤。删除 LoginViewState 枚举及相关状态变量,清理不再使用的 UI 组件和方法,使代码结构更清晰。
weicu
lxm 8 months ago
parent
commit
544a427c65
  1. 107
      lib/modules/login/controllers/login_controller.dart
  2. 224
      lib/modules/login/views/login_view.dart

107
lib/modules/login/controllers/login_controller.dart

@ -24,11 +24,6 @@ import '../../../data/services/version_update_service.dart';
import '../../../modules/common/widgets/privacy_policy_dialog.dart';
import '../constants/country_codes.dart';
enum LoginViewState {
welcome, // 欢迎页面
verification // 验证码页面
}
class LoginController extends GetxController {
static LoginController get to => Get.find();
final GetStorage _storage = GetStorage();
@ -73,20 +68,12 @@ class LoginController extends GetxController {
}
// 状态管理
final _viewState = LoginViewState.welcome.obs;
final _isLoading = false.obs;
final _countdownSeconds = 0.obs;
final _contactValue = ''.obs;
final _displayContact = ''.obs;
final _verificationCode = ['', '', '', ''].obs;
int loginType = 0;
// Getters
LoginViewState get viewState => _viewState.value;
bool get isLoading => _isLoading.value;
int get countdownSeconds => _countdownSeconds.value;
String get contactValue => _contactValue.value;
String get displayContact => _displayContact.value;
List<String> get verificationCode => _verificationCode;
final versionService = VersionUpdateService.to;
// 文本控制器 - 延迟初始化
@ -107,8 +94,6 @@ class LoginController extends GetxController {
@override
void onInit() {
super.onInit();
_viewState.value = LoginViewState.welcome;
// 初始化控制器
_contactController = TextEditingController();
_verificationCodeController = TextEditingController();
@ -297,78 +282,9 @@ class LoginController extends GetxController {
return;
}
_contactValue.value = contactController.text;
_formatDisplayContact();
_sendVerificationCode();
}
// 使用验证码直接登录
void loginWithVerificationCode() {
_isLoading.value = true;
// 模拟验证过程
Future.delayed(const Duration(seconds: 2), () {
_isLoading.value = false;
// 验证成功,跳转到配对页面
Get.offAllNamed(Routes.pairing);
});
}
// 切换到验证码页面
void showVerificationView() {
_syncContactLoginType();
if (contactController.text.isEmpty) {
Get.snackbar(
'tip'.tr,
'pleaseEnterContactInfo'.tr,
snackPosition: SnackPosition.TOP,
backgroundColor: Colors.red.withOpacity(0.1),
colorText: Colors.red,
);
return;
}
_contactValue.value = contactController.text;
_formatDisplayContact();
_viewState.value = LoginViewState.verification;
_sendVerificationCode();
}
// 返回欢迎页面
void showWelcomeView() {
_viewState.value = LoginViewState.welcome;
_resetVerificationCode();
}
// 格式化显示的联系方式(隐藏部分字符)
void _formatDisplayContact() {
String contact = _contactValue.value;
if (contact.contains('@')) {
// 邮箱逻辑保持不变
final parts = contact.split('@');
if (parts[0].length > 3) {
_displayContact.value = parts[0].substring(0, 3) + '****@' + parts[1];
} else {
_displayContact.value = contact;
}
loginType = 0;
} else if (RegExp(r'^\d+$').hasMatch(contact)) {
// 手机号格式化时包含国家编码
if (contact.length > 7) {
_displayContact.value = '$selectedCountryCode ' +
contact.substring(0, 3) +
'****' +
contact.substring(contact.length - 4);
} else {
_displayContact.value = '$selectedCountryCode $contact';
}
loginType = 1;
} else {
_displayContact.value = contact;
}
}
// 开始倒计时
void _startCountdown() {
_countdownSeconds.value = 60;
@ -406,29 +322,6 @@ class LoginController extends GetxController {
}
}
// 重新发送验证码
void resendVerificationCode() {
_syncContactLoginType();
if (_countdownSeconds.value > 0) return;
_startCountdown();
_sendVerificationCode();
}
// 更新验证码输入
void updateVerificationCode(int index, String value) {
Logger().d("updateVerificationCode=$index$value");
if (index >= 0 && index < 4) {
var newList = [..._verificationCode];
newList[index] = value;
_verificationCode.value = newList;
}
}
// 重置验证码
void _resetVerificationCode() {
_verificationCode.value = ['', '', '', ''];
}
// 检查邮箱格式
bool isEmailContactController() {
// 检查每个元素是否为单个字母或数字字符

224
lib/modules/login/views/login_view.dart

@ -4,7 +4,6 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import '../controllers/login_controller.dart';
import '../../common/webview_page.dart';
import 'package:get_storage/get_storage.dart';
class LoginView extends GetView<LoginController> {
const LoginView({Key? key}) : super(key: key);
@ -20,9 +19,7 @@ class LoginView extends GetView<LoginController> {
child: Scaffold(
backgroundColor: isDarkMode ? Colors.black : Colors.grey[50],
body: SafeArea(
child: Obx(() => controller.viewState == LoginViewState.welcome
? _buildWelcomeView(isDarkMode)
: _buildVerificationView(context, isDarkMode)),
child: _buildWelcomeView(isDarkMode),
),
),
);
@ -66,44 +63,6 @@ class LoginView extends GetView<LoginController> {
);
}
// 验证码页面
Widget _buildVerificationView(BuildContext context, bool isDarkMode) {
return Padding(
padding: EdgeInsets.all(24.w),
child: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 返回按钮
_buildBackButton(isDarkMode),
// 验证码标题
SizedBox(height: 24.h),
_buildVerificationTitle(isDarkMode),
// 验证码输入框
SizedBox(height: 32.h),
_buildVerificationInputs(context, isDarkMode),
// 重新发送验证码
SizedBox(height: 16.h),
_buildResendButton(isDarkMode),
// 登录按钮
SizedBox(height: 32.h),
_buildLoginButton(isDarkMode),
// 使用密码登录
SizedBox(height: 16.h),
_buildUsePasswordButton(isDarkMode),
SizedBox(height: 24.h),
],
),
),
);
}
// 应用标志和标题
Widget _buildAppLogo(bool isDarkMode) {
return Column(
@ -684,185 +643,4 @@ class LoginView extends GetView<LoginController> {
],
);
}
// 返回按钮
Widget _buildBackButton(bool isDarkMode) {
return Container(
width: 40.w,
height: 40.w,
decoration: BoxDecoration(
color: isDarkMode ? Colors.grey[800] : Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(20.r),
),
child: IconButton(
icon: Icon(
Icons.arrow_back,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
size: 20.sp,
),
onPressed: () => controller.showWelcomeView(),
),
);
}
// 验证码标题
Widget _buildVerificationTitle(bool isDarkMode) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'enterVerificationCode'.tr, // 输入验证码
style: TextStyle(
fontSize: 20.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
),
SizedBox(height: 8.h),
Obx(() => Text(
'${'verificationCodeSentTo'.tr} ${controller.displayContact}', // 验证码已发送至
style: TextStyle(
fontSize: 14.sp,
color: isDarkMode ? Colors.grey[400] : Colors.grey[600],
),
)),
],
);
}
// 验证码输入框
Widget _buildVerificationInputs(BuildContext context, bool isDarkMode) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(
4, (index) => _buildVerificationInput(index, context, isDarkMode)),
);
}
// 单个验证码输入框
Widget _buildVerificationInput(
int index, BuildContext context, bool isDarkMode) {
return Container(
width: 60.w,
height: 60.w,
decoration: BoxDecoration(
color: isDarkMode
? Colors.grey[900]!.withOpacity(0.3)
: Colors.grey.withOpacity(0.1),
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!,
width: 1,
),
),
child: Center(
child: TextField(
textAlign: TextAlign.center,
keyboardType: TextInputType.number,
maxLength: 1,
onChanged: (value) {
controller.updateVerificationCode(index, value);
if (value.isNotEmpty && index < 3) {
FocusScope.of(context).nextFocus();
}
},
decoration: InputDecoration(
counterText: '',
border: InputBorder.none,
fillColor: Colors.transparent,
filled: true,
),
style: TextStyle(
fontSize: 24.sp,
fontWeight: FontWeight.w600,
color: isDarkMode ? Colors.white : Colors.black,
),
),
),
);
}
// 重新发送验证码按钮
Widget _buildResendButton(bool isDarkMode) {
return Center(
child: Obx(() => TextButton.icon(
onPressed: controller.countdownSeconds > 0
? null
: controller.resendVerificationCode,
icon: Icon(
Icons.refresh,
size: 14.sp,
color: controller.countdownSeconds > 0
? (isDarkMode ? Colors.grey[600] : Colors.grey[500])
: const Color(0xFF3B82F6),
),
label: Text(
controller.countdownSeconds > 0
? '${'resendVerificationCode'.tr} (${controller.countdownSeconds}s)' // 重新发送验证码 (倒计时)
: 'resendVerificationCode'.tr, // 重新发送验证码
style: TextStyle(
fontSize: 14.sp,
color: controller.countdownSeconds > 0
? (isDarkMode ? Colors.grey[600] : Colors.grey[500])
: const Color(0xFF3B82F6),
),
),
)),
);
}
// 登录按钮
Widget _buildLoginButton(bool isDarkMode) {
return SizedBox(
width: double.infinity,
child: Obx(() => ElevatedButton(
onPressed: controller.isLoading ? null : () => controller.login(),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xFF3B82F6),
foregroundColor: Colors.white,
padding: EdgeInsets.symmetric(vertical: 14.h),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16.r),
),
elevation: 0,
disabledBackgroundColor: const Color(0xFF3B82F6).withOpacity(0.7),
disabledForegroundColor: Colors.white,
),
child: controller.isLoading
? SizedBox(
height: 20.h,
width: 20.h,
child: CircularProgressIndicator(
strokeWidth: 2.w,
valueColor:
const AlwaysStoppedAnimation<Color>(Colors.white),
),
)
: Text(
'login'.tr, // 登录
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.w600,
),
),
)),
);
}
// 使用密码登录按钮
Widget _buildUsePasswordButton(bool isDarkMode) {
return Center(
child: TextButton(
onPressed: controller.usePasswordLogin,
child: Text(
'usePasswordLogin'.tr, // 使用密码登录
style: TextStyle(
fontSize: 14.sp,
color:
isDarkMode ? const Color(0xFF3B82F6) : const Color(0xFF3B82F6),
),
),
),
);
}
}

Loading…
Cancel
Save