// ignore_for_file: slash_for_doc_comments import 'package:cs_resources/constants/color_constants.dart'; import 'package:cs_resources/generated/assets.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:get/get.dart'; import 'package:plugin_basic/base/base_stateful_page.dart'; import 'package:plugin_basic/base/base_state.dart'; import 'package:plugin_basic/base/mixin_state_lifecycle.dart'; import 'package:plugin_basic/service/app_config_service.dart'; import 'package:plugin_basic/utils/ext_get_nav.dart'; import 'package:router/path/router_path.dart'; import 'package:shared/utils/device_utils.dart'; import 'package:shared/utils/log_utils.dart'; import 'package:shared/utils/screen_util.dart'; import 'package:widgets/ext/ex_widget.dart'; import 'package:widgets/my_button.dart'; import 'package:widgets/my_load_image.dart'; import 'package:widgets/my_text_field.dart'; import 'package:widgets/my_text_view.dart'; import 'package:widgets/shatter/custom_radio_check.dart'; import 'package:widgets/widget_export.dart'; import 'login_controller.dart'; import 'login_state.dart'; /* App 登录页面 */ class LoginPage extends BaseStatefulPage { LoginPage({super.key}); //启动当前页面 static void startInstance() { return Get.start(RouterPath.authLogin, launchModel: LaunchModel.standard); } static void startWithPopAll() { Get.offAllNamed(RouterPath.authLogin); } @override State createState() => _LoginPageState(); @override LoginController createRawController() { return LoginController(); } } /** * 页面 */ class _LoginPageState extends BaseState with StateLifecycle { late LoginState state; @override void initState() { super.initState(); state = controller.state; } @override void dispose() { Get.delete(); super.dispose(); } @override Widget build(BuildContext context) { Log.d("LoginPage Lifecycle - build走了一遍"); return autoCtlGetBuilder( builder: (controller) { return Scaffold( body: Container( width: double.infinity, height: double.infinity, decoration: const BoxDecoration( gradient: LinearGradient( colors: [ Color(0xFF091D44), Color(0xFF245A8A), Color(0xFF7F7CEC), ], begin: Alignment.topCenter, end: Alignment.bottomCenter, ), ), child: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ //当前选择的国家,这个不跟随滚动 Align( alignment: Alignment.topRight, child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ Obx(() { return MyTextView( ConfigService.to.curSelectCountry == 0 ? "Vietnam".tr : "Singapore".tr, textColor: ColorConstants.white, isFontMedium: true, marginRight: 5, fontSize: 15, ); }), const MyAssetImage( Assets.baseServiceTriangleDropDown, width: 8, height: 5, ), ], ).onTap(() => controller.gotoSelectCountryPage()).marginOnly(right: 20, top: ScreenUtil.getStatusBarH(context) + 20), ), // 底部滚动的布局 SingleChildScrollView( scrollDirection: Axis.vertical, physics: const BouncingScrollPhysics(), child: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.center, children: [ MyTextView( "Casual Labour System", textColor: ColorConstants.white, isFontBold: true, fontSize: 35, marginTop: 20, fontStyle: FontStyle.italic, textAlign: TextAlign.center, marginLeft: 50, marginRight: 50, ), //中间的输入框布局 Container( width: double.infinity, margin: EdgeInsets.symmetric(vertical: 45, horizontal: 15), padding: EdgeInsets.symmetric(vertical: 33, horizontal: 20), decoration: BoxDecoration( color: Color(0xFF4DCFF6).withOpacity(0.2), // 设置背景颜色和不透明度 borderRadius: BorderRadius.circular(5.0), // 设置圆角 ), child: Center( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ //登录文本 MyTextView( "Email".tr, isFontMedium: true, fontSize: 17, textColor: ColorConstants.white, ), // 登录表单 - 账号 _buildInputLayout( "code", textInputAction: TextInputAction.next, errorText: state.codeErrorText, onSubmit: (formKey, value) { state.formData[formKey]!['focusNode'].unfocus(); FocusScope.of(context).requestFocus(state.formData['password']!['focusNode']); }, ), //密码文本 MyTextView( "Password".tr, isFontMedium: true, fontSize: 17, textColor: ColorConstants.white, marginTop: 18, ), // 登录表单 - 密码 _buildInputLayout( "password", obscureText: !state.pwdVisibility, errorText: state.passwordErrorText, showRightIcon: true, rightWidget: IconButton( highlightColor: Colors.transparent, splashColor: Colors.transparent, icon: state.pwdVisibility ? const MyAssetImage( Assets.cptAuthPasswordShowIcon, width: 21, height: 21, color: ColorConstants.white, ) : const MyAssetImage( Assets.cptAuthPasswordHideIcon, width: 21, height: 21, color: ColorConstants.white, ), onPressed: () { controller.switchPwdVisibility(); }, ), onSubmit: (formKey, value) { state.formData[formKey]!['focusNode'].unfocus(); controller.doInputLogin(); }, ), //选择签到功能还是全功能 Obx(() { return Visibility( visible: ConfigService.to.curSelectCountry == 0, child: CustomRadioCheck( options: state.loginOption, onOptionSelected: (index, text) { state.loginOptionPosition = index; }, ).marginOnly(top: 20), ); }), //登录按钮 MyButton( type: ClickType.throttle, milliseconds: 500, onPressed: () { FocusScope.of(context).unfocus(); controller.doInputLogin(); }, text: "Log in".tr, textColor: ColorConstants.white, fontSize: 16, radius: 22.5, backgroundColor: hexToColor("#FFBB1B"), fontWeight: FontWeight.w500, ).marginOnly(top: 20), //注册入口 Visibility( visible: !DeviceUtils.isAndroid, child: _buildRichText(), ), ], ), ), // 传递子部件 ), ], )).expanded(), ], ), ), ); }, ); } @override void onStart() { Log.d("LoginPage Lifecycle - onStart"); } @override void onStop() { Log.d("LoginPage Lifecycle - onStop"); } @override void onResume() { Log.d("LoginPage Lifecycle - onResume"); } @override void onPause() { Log.d("LoginPage Lifecycle - onPause"); } //底部的注册文本 Widget _buildRichText() { return Align( alignment: Alignment.center, child: RichText( text: TextSpan( style: TextStyle(fontSize: 14.0, fontWeight: FontWeight.w500, color: ColorConstants.textGrayAECAE5), children: [ TextSpan( text: "Don’t have an account?".tr, style: TextStyle(color: ColorConstants.textGrayAECAE5), ), TextSpan( text: "Sign up".tr, style: TextStyle(color: ColorConstants.textYellowFFBB1B), recognizer: TapGestureRecognizer() ..onTap = () { //去登录页面 controller.gotoSignUpPage(); }, ), ], ), ), ).marginOnly(top: 23); } /// 输入框 账号与密码 Widget _buildInputLayout( String key, { double marginTop = 0, bool? showRightIcon = false, //是否展示右侧的布局 Widget? rightWidget, //右侧的布局 TextInputType textInputType = TextInputType.text, String? errorText, bool obscureText = false, TextInputAction textInputAction = TextInputAction.done, Function? onSubmit, }) { return IgnoreKeyboardDismiss( child: MyTextField( key, state.formData[key]!['value'], hintText: state.formData[key]!['hintText'], hintStyle: TextStyle( color: hexToColor("#AECAE5"), fontSize: 15.0, fontWeight: FontWeight.w500, ), controller: state.formData[key]!['controller'], focusNode: state.formData[key]!['focusNode'], margin: EdgeInsets.only(top: marginTop), showDivider: true, dividerColor: hexToColor("#7BABC8"), style: TextStyle( color: ColorConstants.white, fontSize: 15.0, fontWeight: FontWeight.w500, ), inputType: textInputType, height: 35, textInputAction: textInputAction, onSubmit: onSubmit, cursorColor: ColorConstants.white, obscureText: obscureText, errorText: errorText, showLeftIcon: true, showRightIcon: showRightIcon, rightWidget: rightWidget, ), ); } }