import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:get/get.dart'; import 'package:starwork_flutter/common/constant/login_type.dart'; import 'package:starwork_flutter/routes/app_routes.dart'; import 'login_controller.dart'; class LoginView extends GetView { const LoginView({super.key}); @override Widget build(BuildContext context) { return GestureDetector( onTap: () { // 收起键盘 FocusScope.of(context).unfocus(); }, child: Scaffold( resizeToAvoidBottomInset: true, body: SafeArea( child: SingleChildScrollView( child: _buildBody(), ), ), ), ); } Widget _buildBody() { return SizedBox( height: 0.9.sh, child: Column( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, children: [ _buildTop(), _buildPrivacyPolicy(), ], ), ); } _buildTop() { return Container( margin: EdgeInsets.symmetric(horizontal: 40.w, vertical: 40.h), child: Column( children: [ _buildTitle(), SizedBox(height: 20.h), _buildPhoneInputAndLoginButton(), SizedBox(height: 20.h), ], ), ); } Widget _buildTitle() { return SizedBox( width: double.infinity, child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( '欢迎使用斯凯签勤'.tr, style: TextStyle( fontSize: 22.sp, fontWeight: FontWeight.w500, ), ), Text( '未注册手机号验证后将自动创建账号'.tr, style: TextStyle( fontSize: 14.sp, fontWeight: FontWeight.w500, color: Colors.grey, ), ), ], ), ); } _buildPhoneInputAndLoginButton() { return Obx( () => Column( children: [ TextField( controller: controller.phoneController, keyboardType: TextInputType.phone, textInputAction: TextInputAction.done, maxLength: controller.phoneNumberSize, decoration: InputDecoration( counterText: '', hintText: '请输入手机号码'.tr, border: const UnderlineInputBorder(), suffixIcon: controller.phoneController.text.isNotEmpty ? IconButton( icon: const Icon(Icons.clear, color: Colors.grey), onPressed: () { controller.phoneController.clear(); // 清空输入 }, ) : null, // 如果没有内容,就不显示清除按钮, // 获取焦点时的边框 focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: controller.isFormValid.value ? Colors.blue : Colors.blue.withOpacity(0.5), ), // ), ), ), Visibility( visible: controller.loginType.value == LoginType.phonePassword, child: SizedBox( height: 18.h, ), ), Visibility( visible: controller.loginType.value == LoginType.phonePassword, child: TextField( controller: controller.passwordController, keyboardType: TextInputType.visiblePassword, textInputAction: TextInputAction.done, obscureText: controller.isPasswordVisible.value, decoration: InputDecoration( counterText: '', hintText: '请输入密码'.tr, border: const UnderlineInputBorder(), suffixIcon: IconButton( icon: Icon( controller.isPasswordVisible.value ? Icons.visibility : Icons.visibility_off, ), onPressed: () => controller.isPasswordVisible.value = !controller.isPasswordVisible.value, ), focusedBorder: UnderlineInputBorder( borderSide: BorderSide( color: controller.isFormValid.value ? Colors.blue : Colors.blue.withOpacity(0.5), ), // ), ), ), ), SizedBox( height: 48.h, ), ElevatedButton( onPressed: controller.isFormValid.value ? controller.requestPhoneCode : null, style: ButtonStyle( minimumSize: MaterialStateProperty.all(Size(double.infinity, 44.h)), shape: MaterialStateProperty.all( RoundedRectangleBorder( borderRadius: BorderRadius.circular(8.r), ), ), backgroundColor: MaterialStateProperty.all( controller.isFormValid.value ? Colors.blue : Colors.blue.withOpacity(0.5), ), ), child: Text( controller.loginType.value == LoginType.phoneCodeLogin ? '获取验证码'.tr : '登录'.tr, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.white, ), ), ), SizedBox(height: 20.h), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Visibility( visible: LoginType.phoneCodeLogin == controller.loginType.value, child: TextButton( onPressed: () { controller.loginType.value = LoginType.phonePassword; }, child: Text( '密码登录'.tr, textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.grey, ), ), ), ), Visibility( visible: LoginType.phonePassword == controller.loginType.value, child: TextButton( onPressed: () { controller.loginType.value = LoginType.phoneCodeLogin; }, child: Text( '验证码登录'.tr, textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.grey, ), ), ), ), Visibility( visible: LoginType.phonePassword == controller.loginType.value, child: Text( '|', style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.grey, ), ), ), Visibility( visible: LoginType.phonePassword == controller.loginType.value, child: TextButton( style: ButtonStyle( overlayColor: MaterialStateProperty.all(Colors.transparent), // 墨水覆盖 side: MaterialStateProperty.all(null), // 取消边框 ), onPressed: () { Get.toNamed( AppRoutes.forgotPassword, parameters: { 'phone': controller.phoneController.text, }, ); }, child: Text( '忘记密码'.tr, textAlign: TextAlign.center, style: TextStyle( fontSize: 16.sp, fontWeight: FontWeight.w500, color: Colors.grey, ), ), ), ) ], ) ], ), ); } _handleLoginButtonText() { if (controller.loginType.value == LoginType.phoneCodeLogin) { return; } else if (controller.loginType.value == LoginType.phonePassword) { return '验证码登录'.tr + ' | '.tr + '忘记密码'.tr; } } _buildPrivacyPolicy() { return GestureDetector( onTap: () { controller.isPrivacyAgreementValid.value = controller.isPrivacyAgreementValid.value == 1 ? 0 : 1; }, child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Obx( () => Checkbox( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(4.r), ), activeColor: Colors.blue, value: controller.isPrivacyAgreementValid.value == 1, // 转换为 bool onChanged: (bool? value) { controller.isPrivacyAgreementValid.value = value == true ? 1 : 0; }, ), ), RichText( textAlign: TextAlign.center, text: TextSpan( children: [ TextSpan( text: '我已阅读并同意'.tr, style: TextStyle( fontSize: 13.sp, color: Colors.grey, ), ), TextSpan( text: '《用户协议》'.tr, style: TextStyle( fontSize: 13.sp, color: Colors.blue, ), ), TextSpan( text: '和'.tr, style: TextStyle( fontSize: 13.sp, color: Colors.grey, ), ), TextSpan( text: '《隐私政策》'.tr, style: TextStyle( fontSize: 13.sp, color: Colors.blue, ), ), ], ), ) ], ), ); } }