import 'package:EasyDartModule/EasyDartModule.dart' as edm; import 'package:ef/ef.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutterflow_ui/flutterflow_ui.dart'; import 'package:fluwx/fluwx.dart'; import 'package:vbvs_app/common/color/appConstants.dart'; import 'package:vbvs_app/common/color/app_uri_status.dart'; import 'package:vbvs_app/common/util/CheckNetwork.dart'; import 'package:vbvs_app/common/util/CommonVariables.dart'; import 'package:vbvs_app/common/util/DailyLogUtils.dart'; import 'package:vbvs_app/common/util/FitTool.dart'; import 'package:vbvs_app/common/util/MyUtils.dart'; import 'package:vbvs_app/component/tool/ClickableContainer.dart'; import 'package:vbvs_app/component/tool/CustomCard.dart'; import 'package:vbvs_app/component/tool/TopSlideNotification.dart'; import 'package:vbvs_app/controller/login/login_controller.dart'; import 'package:vbvs_app/controller/main_bottom/global_controller.dart'; import 'package:vbvs_app/controller/theme_controller/ThemeController.dart'; import 'package:vbvs_app/controller/time/countdown_controller.dart'; import 'package:vbvs_app/controller/user_info_controller.dart'; import 'package:vbvs_app/controller/weather/weather_controller.dart'; import 'package:vbvs_app/enum/APPPackageType.dart'; import 'package:vbvs_app/main.dart'; import 'package:vbvs_app/model/api_response.dart'; import 'package:vbvs_app/pages/person/select_time.dart'; import 'dart:ui' as ui; import 'package:flutter/services.dart'; class OtherLoginPage extends StatefulWidget { const OtherLoginPage({super.key}); @override State createState() => _OtherLoginPageState(); } class _OtherLoginPageState extends State { GlobalController globalController = Get.find(); UserInfoController userInfoController = Get.find(); ThemeController themeController = Get.find(); CountdownController countdownController = Get.find(); LoginController loginController = Get.find(); late TapGestureRecognizer _tapRecognizer2; late TapGestureRecognizer _tapRecognizer4; @override void dispose() { _tapRecognizer2.dispose(); _tapRecognizer4.dispose(); loginController.fluwxCancelable?.cancel(); super.dispose(); } @override void initState() { // TODO: implement initState _tapRecognizer2 = TapGestureRecognizer() ..onTap = () { // 协议2点击事件逻辑 print('点击了协议2'); // Get.to(() => UserSchemePage()); // Get.toNamed("/userSchemePage"); Get.toNamed("/userPolicyPageNew", arguments: getPrivacy(2)); }; _tapRecognizer4 = TapGestureRecognizer() ..onTap = () { // 协议4点击事件逻辑 // print('点击了协议4'); // Get.toNamed("/privacyPage"); Get.toNamed("/privacyPolicyPageNew", arguments: getPrivacy(1)); }; super.initState(); LoginController loginController = Get.find(); Fluwx fluwx = loginController.fluwx; if (isiOS) { loginController.model.isIos = true; fluwx.isWeChatInstalled.then((isWeChatInstalled) { debugPrint('is wechat installed: $isWeChatInstalled'); if (!isWeChatInstalled) { // TODO ios未安装微信 隐藏微信一键登录按钮 loginController.model.isWeChatNotInstalled = true; } else { loginController.model.isWeChatNotInstalled = false; } loginController.updateAll(); }); } // 微信监听回调 loginController.fluwxCancelable = fluwx.addSubscriber((response) async { if (response is WeChatAuthResponse) { debugPrint('state :${response.state} \n code:${response.code}'); int errCode = response.errCode ?? -9999; if (errCode == 0) { // TODO 微信登录成功 传递code给后台 再操作逻辑 String code = response.code ?? ""; //把微信登录返回的code传给后台,剩下的事就交给后台处理 //首次未注册的用户引导去手机号填写页面 //已注册的用户直接跳转首页 if (CommonVariables.isNetWorkOn == false) { TopSlideNotification.show(context, text: "网络未连接,请开启设备网络后重试".tr, textColor: themeController.currentColor.sc9); // showToast("网络未连接,请开启设备网络后重试"); return; } ApiResponse msg = await loginController.loginByWechatCode(code); if (msg.code == HttpStatusCodes.ok) { // TODO 操作全部跳转页面前成功以后移除监听,防止重复监听,其他方式登录成功也需要移出监听 loginController.fluwxCancelable?.cancel(); // 登录成功移出网络检查监听 Checknetwork.subscription?.cancel(); if (Get.currentRoute != '/mianPageBottomChange') { Get.offAndToNamed("/mianPageBottomChange"); } } // TODO 操作全部跳转页面前成功以后移除监听,防止重复监听,其他方式登录成功也需要移出监听 // fluwxCancelable?.cancel(); } else if (errCode == -4) { TopSlideNotification.show(context, text: "用户拒绝授权".tr, textColor: themeController.currentColor.sc9); // showToast("用户拒绝授权"); } else if (errCode == -2) { TopSlideNotification.show(context, text: "用户取消授权".tr, textColor: themeController.currentColor.sc9); // showToast("用户取消授权"); } } }); } @override Widget build(BuildContext context) { return LayoutBuilder( builder: (context, bodysize) => GestureDetector( // onTap: () => FocusScope.of(context).unfocus(),, child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage(getBackgroundImage()), // 本地图片 fit: BoxFit.fill, // 填满整个 Container ), ), child: Scaffold( resizeToAvoidBottomInset: false, backgroundColor: Colors.transparent, appBar: AppBar( systemOverlayStyle: SystemUiOverlayStyle( statusBarColor: Colors.transparent, // 状态栏背景色 statusBarIconBrightness: Brightness.light, // 图标颜色(Android) statusBarBrightness: Brightness.light, // 图标颜色(iOS) ), // backgroundColor: themeController.currentColor.sc17, backgroundColor: Colors.transparent, automaticallyImplyLeading: false, iconTheme: IconThemeData(color: themeController.currentColor.sc3), titleSpacing: 0.rpx, // leading: returnIconButtom, title: Container( width: double.infinity, height: 180.rpx, child: Stack( alignment: Alignment.center, children: [ /// 左边返回按钮 Positioned( left: 0.rpx, child: returnIconButtom, ), ], ), ), actions: [], centerTitle: false, ), body: SafeArea( top: true, child: Padding( padding: EdgeInsetsDirectional.fromSTEB(75.rpx, 0.rpx, 75.rpx, 0), child: Column( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, children: [ // SizedBox( // height: 66.rpx, // ), // ClickableContainer( // backgroundColor: Colors.transparent, // 容器背景色 // highlightColor: // themeController.currentColor.sc21, // 点击时的背景色 // padding: EdgeInsets.zero, // 这里去掉外部的 padding,避免影响点击范围 // onTap: () { // Get.back(); // }, // child: Padding( // padding: EdgeInsetsDirectional.fromSTEB( // 0.rpx, 10.rpx, 16.rpx, 10.rpx), // // child: SvgPicture.asset( // // 'assets/img/icon/arrow_left.svg', // // width: 25.rpx, // // height: 25.rpx, // 如果 SVG 中没有固定颜色,使用 color 设置 // // color: themeController.currentColor.sc3, // // ), // child: returnIconButtomNew(), // ), // ), Expanded( child: SingleChildScrollView( child: Column( mainAxisSize: MainAxisSize.max, children: [ Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0, 141.rpx, 0, 0), child: Container( width: double.infinity, decoration: BoxDecoration(), child: Align( alignment: AlignmentDirectional(0, 0), child: Text( getWelcomeText(AppConstants().ent_type), style: TextStyle( fontFamily: 'Inter', fontSize: 48.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ), ), ), ), Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0, 15.rpx, 0, 0), child: Container( width: double.infinity, decoration: BoxDecoration(), child: Align( alignment: AlignmentDirectional(0, 0), child: Text( '登录页.科技睡眠 洞悉万千'.tr, style: TextStyle( fontFamily: 'Inter', fontSize: 30.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ), ), ), ), Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0, 95.rpx, 0, 0), child: Container( width: double.infinity, height: bodysize.maxHeight * 0.056, constraints: BoxConstraints( minHeight: 90.rpx, ), // ✅ 在这里塞进去 child: _buildLoginMethodSelector(bodysize), ), ), ), Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0, 26.rpx, 0, 0), child: Container( width: double.infinity, height: bodysize.maxHeight * 0.056, decoration: BoxDecoration( color: Colors.transparent, borderRadius: BorderRadius.circular( AppConstants().button_container_radius), border: Border.all( color: themeController.currentColor.sc4 .withOpacity(0.5), width: AppConstants().border_width, ), ), constraints: BoxConstraints( minHeight: 90.rpx, ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 35.rpx, 0, 35.rpx, 0), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Obx(() { if (userInfoController .select_login_method.value == 2) { return Container(); } return Padding( padding: EdgeInsetsDirectional.fromSTEB( 26.rpx, 0, 0, 0), child: Row( mainAxisSize: MainAxisSize.max, children: [ InkWell( onTap: () async { await showCountryCodePickerDialog( context, initialCode: userInfoController .select_country_code .value, // ✅ 来自 controller onConfirm: (String code) { print("选中的区号:$code"); userInfoController .select_country_code .value = code; userInfoController .updateAll(); // setState / controller.update }, title: "选择区号".tr, ); }, child: Obx(() { return Container( width: 80.rpx, alignment: Alignment.center, child: Text( "${userInfoController.select_country_code.value}", style: TextStyle( fontFamily: 'Readex Pro', color: themeController .currentColor.sc2, fontSize: AppConstants() .middler_text_fontSize, ), ), ); }), ), SizedBox( height: 30.rpx, child: VerticalDivider( thickness: 2.rpx, color: themeController .currentColor.sc4, ), ), ].divide(SizedBox(width: 10.rpx)), ), ); }), Obx(() { return Expanded( child: Container( child: Align( alignment: AlignmentDirectional(-1, 0), child: TextFormField( onChanged: (value) { loginController.model.phone = value; }, autofocus: false, obscureText: false, decoration: InputDecoration( isDense: true, labelStyle: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, ), hintText: userInfoController .select_login_method .value == 2 ? '输入邮箱'.tr : "输入手机号码".tr, hintStyle: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc4, ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red, width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red, width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), filled: false, fillColor: Colors.white, ), style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc3, ), cursorColor: themeController .currentColor.sc3, // validator: _model // .textControllerValidator // .asValidator(context), ), ), ), ); }), ], ), ), ), ), ), Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0, 26.rpx, 0, 0), child: Container( height: bodysize.maxHeight * 0.056, width: double.infinity, decoration: BoxDecoration( color: Colors.transparent, borderRadius: BorderRadius.circular( AppConstants().button_container_radius), border: Border.all( color: themeController.currentColor.sc4 .withOpacity(0.5), width: AppConstants().border_width, ), ), constraints: BoxConstraints( minHeight: 90.rpx, ), child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 35.rpx, 0, 35.rpx, 0), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Expanded( child: Container( child: Align( alignment: AlignmentDirectional(-1, 0), child: TextFormField( onChanged: (value) { loginController.model.code = value; }, autofocus: false, obscureText: false, decoration: InputDecoration( isDense: true, labelStyle: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, ), hintText: '其他手机登录页.输入验证码'.tr, hintStyle: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc4, ), enabledBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), focusedBorder: OutlineInputBorder( borderSide: BorderSide( color: Color(0x00000000), width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), errorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red, width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), focusedErrorBorder: OutlineInputBorder( borderSide: BorderSide( color: Colors.red, width: 1.rpx, ), borderRadius: BorderRadius.circular( 8.rpx), ), filled: true, fillColor: Colors.transparent, ), style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController .currentColor.sc3, ), cursorColor: themeController .currentColor.sc3, // validator: _model // .textControllerValidator // .asValidator(context), ), ), ), ), Padding( padding: EdgeInsetsDirectional.fromSTEB( 26.rpx, 0, 0, 0), child: Row( mainAxisSize: MainAxisSize.max, children: [ SizedBox( height: 30.rpx, child: VerticalDivider( thickness: 2.rpx, color: themeController .currentColor.sc7, ), ), Obx(() { final CountdownController countdownController = Get.find< CountdownController>(); return InkWell( onTap: () async { try { DailyLogUtils.writeLog( "点击获取验证码"); if (countdownController .countdown.value != 0) { return; } ApiResponse apiResponse = await loginController .getCode(context); if (apiResponse.code != HttpStatusCodes.ok) { TopSlideNotification.show( context, text: apiResponse.msg!, textColor: themeController .currentColor .sc9, ); await DailyLogUtils.writeLog( "获取验证码失败,${apiResponse}"); return; } else { TopSlideNotification.show( context, text: apiResponse.msg!, textColor: themeController .currentColor .sc2, ); await DailyLogUtils.writeLog( "获取验证码成功,${apiResponse}"); } countdownController .countdown .value == 0 ? countdownController .startCountdown( AppConstants .code_time) : null; } catch (e) { await DailyLogUtils .writeLog( "获取验证码异常,${e}"); edm.EasyDartModule.logger .info("获取验证码异常:${e}"); } }, child: Container( alignment: Alignment.center, constraints: BoxConstraints( minWidth: 150.rpx, ), child: Text( countdownController .countdown .value == 0 ? '其他手机登录页.获取验证码'.tr : '${countdownController.countdown.value}' + "其他手机登录页.秒".tr, style: TextStyle( fontFamily: 'Readex Pro', color: themeController .currentColor.sc2, fontSize: AppConstants() .middler_text_fontSize, letterSpacing: 0, ), ), ), ); }), ].divide(SizedBox(width: 26.rpx)), ), ), ], ), ), ), ), ), Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 26.rpx, 0, 0), child: CustomCard( borderRadius: AppConstants() .button_container_radius, // 圆角半径 onTap: () async { try { DailyLogUtils.writeLog("点击登录"); if (loginController.model.register_agree == null || loginController.model.register_agree! == false) { TopSlideNotification.show( context, text: "登录页.未同意协议".tr, textColor: themeController.currentColor.sc9, ); } else { ApiResponse apiResponse = await loginController.login(context); if (apiResponse.code != HttpStatusCodes.ok) { TopSlideNotification.show( context, text: apiResponse.msg!, textColor: themeController.currentColor.sc9, ); } else { await dealBindProcess(); CountdownController countdownController = Get.find(); countdownController.countdown.value = 0; // 登录成功,跳转到主页面 TopSlideNotification.show( context, text: "其他手机登录页.登录成功".tr, textColor: themeController.currentColor.sc2, ); // Get.offAllNamed('/homePage'); Get.offAllNamed("/mianPageBottomChange"); //获取天气 WeatherModelController weatherModelController = Get.find(); await weatherModelController .getCurrentLocation(); await weatherModelController .getCurrentWeather(); } } } catch (e) { await DailyLogUtils.writeLog("登录失败,${e}"); edm.EasyDartModule.logger.info("登录失败:${e}"); } }, colors: [ themeController.currentColor.sc1, themeController.currentColor.sc2, ], child: Container( width: bodysize.maxWidth, height: MediaQuery.sizeOf(context).height * 0.055, constraints: BoxConstraints( minWidth: 500.rpx, minHeight: 90.rpx, ), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( '其他手机登录页.登录'.tr, style: TextStyle( color: themeController.currentColor.sc3, fontFamily: 'Inter', fontSize: AppConstants().normal_text_fontSize, letterSpacing: 0.0, ), ), ].divide(SizedBox( width: 17.rpx, )), ), ), ), ), Padding( padding: EdgeInsetsDirectional.fromSTEB( 25.rpx, 42.rpx, 25.rpx, 50.rpx), child: Container( width: double.infinity, decoration: BoxDecoration(), child: Row( mainAxisSize: MainAxisSize.max, crossAxisAlignment: CrossAxisAlignment.start, children: [ Theme( data: ThemeData( checkboxTheme: CheckboxThemeData( visualDensity: VisualDensity.compact, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(64), ), ), unselectedWidgetColor: Color(0xFFD3D3D3), ), child: Obx( () => Checkbox( value: loginController .model.register_agree ?? false, onChanged: (newValue) async { loginController.model .register_agree = newValue; loginController.updateAll(); // 获取设备信息,需要用户点击确认隐私协议与用户协议选择框时才能获取 // if (newValue == true) { // Deviceconfig // .initPlatformState(); // } }, side: BorderSide( width: 1.5, color: Colors.white, ), activeColor: stringToColor("#FF9F66"), //固定 checkColor: Colors.white, ), )), // Expanded( // child: Padding( // padding: EdgeInsetsDirectional.fromSTEB( // 0.rpx, 10.rpx, 0.rpx, 0.rpx), // child: Container( // width: bodysize.maxWidth, // constraints: BoxConstraints( // minWidth: 500.rpx, // minHeight: 90.rpx, // ), // child: RichText( // text: TextSpan( // children: [ // TextSpan( // text: '登录页.协议1'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: themeController // .currentColor.sc3, // ), // ), // TextSpan( // text: '登录页.协议2'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: // stringToColor("#FF9F66"), // ), // ), // TextSpan( // text: '登录页.协议3'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: themeController // .currentColor.sc3, // ), // ), // TextSpan( // text: '登录页.协议4'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: // stringToColor("#FF9F66"), // ), // ), // TextSpan( // text: '登录页.协议5'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: themeController // .currentColor.sc3, // ), // ), // TextSpan( // text: '登录页.协议6'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: // stringToColor("#FF9F66"), // ), // ), // ], // ), // ), // ), // ), // ), Expanded( child: Padding( padding: EdgeInsetsDirectional.fromSTEB( 0.rpx, 10.rpx, 0.rpx, 0.rpx), child: Container( width: bodysize.maxWidth, constraints: BoxConstraints( minWidth: 500.rpx, minHeight: 90.rpx, ), child: RichText( text: TextSpan( children: [ TextSpan( text: '登录页.协议1'.tr, style: TextStyle( fontFamily: 'Inter', letterSpacing: 0.0, fontSize: 20.rpx, color: themeController .currentColor.sc3, ), ), TextSpan( text: '登录页.协议2'.tr, style: TextStyle( fontFamily: 'Inter', letterSpacing: 0.0, fontSize: 20.rpx, color: stringToColor("#FF9F66"), ), recognizer: _tapRecognizer2, ), TextSpan( text: '登录页.协议3'.tr, style: TextStyle( fontFamily: 'Inter', letterSpacing: 0.0, fontSize: 20.rpx, color: themeController .currentColor.sc3, ), ), TextSpan( text: '登录页.协议4'.tr, style: TextStyle( fontFamily: 'Inter', letterSpacing: 0.0, fontSize: 20.rpx, color: stringToColor("#FF9F66"), ), recognizer: _tapRecognizer4, ), // TextSpan( // text: '登录页.协议5'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: themeController // .currentColor.sc3, // ), // ), // TextSpan( // text: '登录页.协议6'.tr, // style: TextStyle( // fontFamily: 'Inter', // letterSpacing: 0.0, // fontSize: 20.rpx, // color: // stringToColor("#FF9F66"), // ), // ), ], ), ), ), ), ), ].divide(SizedBox(width: 18.rpx)), ), ), ), ], ), ), ), if (AppConstants().ent_type == APPPackageType.TH.code) Container( width: double.infinity, height: MediaQuery.sizeOf(context).height * 0.136, constraints: BoxConstraints( minHeight: 220.rpx, ), decoration: BoxDecoration(), child: Column( mainAxisSize: MainAxisSize.max, children: [ Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 0, 0, 36.rpx), child: Text( "登录页.其他登录方式".tr, style: TextStyle( fontFamily: 'Inter', fontSize: 26.rpx, letterSpacing: 0.0, color: themeController.currentColor.sc3, ), ), ), Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.center, children: [ Obx(() { var aa = loginController.model.isWeChatNotInstalled; if (isiOS && (loginController .model.isWeChatNotInstalled != null && loginController .model.isWeChatNotInstalled == true)) return Container(); return ClickableContainer( backgroundColor: Colors.white, // 背景色 highlightColor: Colors.grey, // 点击水波纹颜色 borderRadius: 999.rpx, padding: EdgeInsets.zero, onTap: () async { if (loginController.model.register_agree == null || loginController.model.register_agree != true) { TopSlideNotification.show( context, text: "登录页.未同意协议".tr, textColor: themeController.currentColor.sc9, ); return; } await loginController .wxLoginSendAuth(context); }, child: Container( width: 91.rpx, height: 91.rpx, clipBehavior: Clip.antiAlias, decoration: BoxDecoration( shape: BoxShape.circle, ), child: Image.asset( "assets/img/wechat.png", width: 30.rpx, height: 30.rpx, ), ), ); }), // ClickableContainer( // backgroundColor: Colors.white, // highlightColor: Colors.grey, // borderRadius: 999.rpx, // padding: EdgeInsets.zero, // onTap: () { // TopSlideNotification.show(context, // text: "待开发功能".tr); // }, // child: Container( // width: 91.rpx, // height: 91.rpx, // clipBehavior: Clip.antiAlias, // decoration: BoxDecoration( // shape: BoxShape.circle, // ), // child: Image.asset( // "assets/img/tel.png", // width: 30.rpx, // height: 30.rpx, // ), // ), // ), // ClickableContainer( // backgroundColor: Colors.white, // highlightColor: Colors.grey, // borderRadius: 999.rpx, // padding: EdgeInsets.zero, // onTap: () { // TopSlideNotification.show(context, // text: "待开发功能".tr); // }, // child: Container( // width: 91.rpx, // height: 91.rpx, // clipBehavior: Clip.antiAlias, // decoration: BoxDecoration( // shape: BoxShape.circle, // ), // child: Image.asset( // "assets/img/google.png", // width: 30.rpx, // height: 30.rpx, // ), // ), // ), ].divide(SizedBox(width: 35.rpx)), ), ], ), ), ], ), ), ), ), )), ); } Widget _buildLoginMethodSelector(BoxConstraints bodysize) { final userInfoController = Get.find(); // 文本样式 final textStyle = TextStyle( fontSize: 28.rpx, fontWeight: FontWeight.w600, ); // 两个 tab 之间的间距 final double gap = 60.rpx; // 左侧内边距 final double leftPadding = 40.rpx; // 下划线和文字的垂直间距 final double underlineGap = 20.rpx; // 下划线高度 final double underlineHeight = 6.rpx; return Align( alignment: AlignmentDirectional(-1, 0), child: Padding( padding: EdgeInsetsDirectional.fromSTEB(0, 0.rpx, 0, 0), child: Container( width: double.infinity, height: bodysize.maxHeight * 0.056, constraints: const BoxConstraints(minHeight: 90), child: Obx(() { final selectedIndex = userInfoController.select_login_method.value; // 1 or 2 // --- 计算文字宽高 --- final tp1 = TextPainter( text: TextSpan(text: '手机号登录'.tr, style: textStyle), textDirection: ui.TextDirection.ltr, )..layout(); final tp2 = TextPainter( text: TextSpan(text: '邮箱登录'.tr, style: textStyle), textDirection: ui.TextDirection.ltr, )..layout(); final double w1 = tp1.width; final double w2 = tp2.width; final double textHeight = tp1.height; // --- 每个 tab 的起始 X --- final double startX1 = leftPadding; final double startX2 = leftPadding + w1 + gap; // --- 下划线宽度(和文字等宽)--- final double underlineWidth1 = w1; final double underlineWidth2 = w2; // --- 下划线 left(始终居中文字)--- final double underlineLeft1 = startX1; final double underlineLeft2 = startX2; final double underlineLeft = selectedIndex == 1 ? underlineLeft1 : underlineLeft2; final double underlineWidth = selectedIndex == 1 ? underlineWidth1 : underlineWidth2; return Stack( clipBehavior: Clip.none, children: [ // ===== 文字行 ===== Positioned( left: 0, top: 0, child: Row( children: [ SizedBox(width: leftPadding), // 手机号登录 GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => userInfoController.select_login_method.value = 1, child: Padding( padding: EdgeInsets.symmetric(vertical: 6.rpx), child: Obx(() { final selected = userInfoController.select_login_method.value == 1; return Text( '手机号登录'.tr, style: textStyle.copyWith( color: selected ? themeController.currentColor.sc2 : themeController.currentColor.sc4, ), ); }), ), ), SizedBox(width: gap), // 邮箱登录 GestureDetector( behavior: HitTestBehavior.translucent, onTap: () => userInfoController.select_login_method.value = 2, child: Padding( padding: EdgeInsets.symmetric(vertical: 6.rpx), child: Obx(() { final selected = userInfoController.select_login_method.value == 2; return Text( '邮箱登录'.tr, style: textStyle.copyWith( color: selected ? themeController.currentColor.sc2 : themeController.currentColor.sc4, ), ); }), ), ), ], ), ), // ===== 下划线(文字正下方) ===== AnimatedPositioned( duration: const Duration(milliseconds: 280), curve: Curves.easeOutCubic, left: underlineLeft, top: textHeight + underlineGap, child: AnimatedContainer( duration: const Duration(milliseconds: 280), curve: Curves.easeOutCubic, width: underlineWidth, height: underlineHeight, decoration: BoxDecoration( color: themeController.currentColor.sc2, borderRadius: BorderRadius.circular(underlineHeight / 2), ), ), ), ], ); }), ), ), ); } Widget _buildLoginTab({ required String text, required int index, required UserInfoController controller, }) { return GestureDetector( onTap: () { controller.select_login_method.value = index; }, child: Obx(() { final selected = controller.select_login_method.value == index; return Text( text, style: TextStyle( fontSize: 28.rpx, fontWeight: FontWeight.w600, color: selected ? themeController.currentColor.sc2 : themeController.currentColor.sc4, ), ); }), ); } String getWelcomeText(int entType) { switch (entType) { case 1: return '登录页.欢迎使用太和e护'.tr; case 2: return '欢迎使用欢睡科技'.tr; case 4: return '欢迎使用东华智能睡眠'.tr; default: return '欢迎使用'.tr; } } }