import 'dart:async'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:game/common/func.dart'; import 'package:game/network/NetworkConfig.dart'; import '../me/set/agreement_page.dart'; import 'login_model.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { final TextEditingController _phoneController = TextEditingController(); final TextEditingController _codeController = TextEditingController(); late StreamSubscription subscription; final LoginModel _viewModel = LoginModel(); int _timeLeft = 60; // 倒计时时间,单位为秒 bool _isCountingDown = false; Timer? _timer; //协议 bool isCheck = true; @override void initState() { // TODO: implement initState super.initState(); subscription = _viewModel.streamController.stream.listen((event) { String code = event['code']; if (code.isNotEmpty) { switch (code) { case "sendPhoneNumber": _startCountdown(); EasyLoading.showToast("${event['data']}"); break; case "login": // EasyLoading.showToast(event['data']); if (_timer != null) { _timer!.cancel(); } Navigator.pushReplacementNamed(context, "/HomePage"); break; case "sendPhoneError": EasyLoading.showToast("${event['data']}"); break; } } }); } @override void dispose() { // TODO: implement dispose super.dispose(); _phoneController.dispose(); _codeController.dispose(); subscription.cancel(); _timer?.cancel(); } ///获取验证码 void getCode() { if (_phoneController.text == "") { EasyLoading.showToast("请输入手机号"); return; } FunctionUtil.loading(); _viewModel.sendPhoneNumber(_phoneController.text); } ///登录 void login() { if (_phoneController.text == "") { EasyLoading.showToast("请输入手机号"); return; } if (_codeController.text == "") { EasyLoading.showToast("请输入验证码"); return; } if (!isCheck) { EasyLoading.showToast("请勾选协议"); return; } FunctionUtil.loading(); _viewModel.login(_phoneController.text, _codeController.text); } ///倒计时读秒 void _startCountdown() { setState(() { _isCountingDown = true; }); _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (_timeLeft > 0) { setState(() { _timeLeft--; }); } else { timer.cancel(); setState(() { _isCountingDown = false; _timeLeft = 60; }); } }); } @override Widget build(BuildContext context) { final size = MediaQuery.of(context).size; final w253 = size.width / 1.422924901185771; final t174 = size.width / 2.068965517241379; final l21 = size.width / 17.14285714285714; final w50 = size.width / 7.2; final t187 = size.width / 1.925133689839572; final l30 = size.width / 12; final w331 = size.width / 1.08761329305136; final h52 = size.width / 6.923076923076923; final l20 = size.width / 18; final c90 = size.width / 4; final s14 = size.width / 25.714285714285; final s13 = size.width / 27.692307692307; final t87 = size.width / 4.1379310344827; final t13 = size.width / 27.692307692307; final t60 = size.width / 6; final w10 = size.width / 36; final s12 = size.width / 30; return Scaffold( backgroundColor: Color(0xFF17181A), body: SizedBox( width: size.width, height: size.height, child: Stack( children: [ Positioned( top: 0, right: 0, child: Image(width: w253, image: const AssetImage('assets/images/ic_login1.png')), ), Positioned( top: t174, left: l21, child: Image(width: w50, height: w50, image: const AssetImage('assets/images/ic_login2.png')), ), SingleChildScrollView( child: Column( children: [ Container( alignment: Alignment.centerLeft, margin: EdgeInsets.only(top: t187, left: l30), child: Text( "登录/注册", style: TextStyle(fontSize: s14, color: Color(0x8AFFFFFF)), ), ), ///手机号 Container( width: w331, height: h52, margin: EdgeInsets.only(top: t87), alignment: Alignment.center, padding: EdgeInsets.only(left: l20), decoration: BoxDecoration( color: const Color(0xFF30343B), borderRadius: BorderRadius.all(Radius.circular(c90)), border: Border.all(color: const Color(0x1AFFFFFF)), ), child: TextField( controller: _phoneController, style: TextStyle(fontSize: s14, color: Colors.white), keyboardType: TextInputType.number, decoration: InputDecoration( border: InputBorder.none, hintText: '请输入您的手机号码', hintStyle: TextStyle(fontSize: s13, color: Color(0x80FFFFFF)), ), inputFormatters: [ LengthLimitingTextInputFormatter(11), // 设置输入长度限制 FilteringTextInputFormatter.digitsOnly, // 只允许输入数字 ], ), ), ///验证码 Container( width: w331, height: h52, margin: EdgeInsets.only(top: t13), padding: EdgeInsets.only(left: l20, right: l20), decoration: BoxDecoration( color: const Color(0xFF30343B), borderRadius: BorderRadius.all(Radius.circular(c90)), border: Border.all(color: const Color(0x1AFFFFFF)), ), child: Row( children: [ Expanded( child: TextField( controller: _codeController, cursorColor: const Color(0xFF074CE7), style: TextStyle(fontSize: s14, color: Colors.white), keyboardType: TextInputType.number, decoration: const InputDecoration( border: InputBorder.none, ), ), ), GestureDetector( onTap: () { if (!_isCountingDown) { getCode(); } }, child: Text( !_isCountingDown ? "获取验证码" : "$_timeLeft后重新获取", style: TextStyle(fontSize: s13, color: Color(0xFF969798)), ), ), ], ), ), ///登录 GestureDetector( onTap: () { login(); }, child: Container( width: w331, height: h52, margin: EdgeInsets.only(top: t60), alignment: Alignment.center, decoration: BoxDecoration( color: const Color(0xFF074CE7), borderRadius: BorderRadius.all(Radius.circular(c90)), ), child: Text( "登录", style: TextStyle(fontSize: s14, color: Colors.white), ), ), ), Container( width: MediaQuery.of(context).size.width, margin: EdgeInsets.only(top: t60, bottom: t13), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ GestureDetector( onTap: () { isCheck = !isCheck; setState(() {}); }, child: Container( width: w10, height: w10, alignment: Alignment.center, child: Image(image: isCheck ? const AssetImage('assets/images/ic_ck_s.png') : const AssetImage('assets/images/ic_ck.png')), ), ), Container( margin: EdgeInsets.only(left: w10), child: RichText( text: TextSpan(children: [ TextSpan(text: '我已阅读并同意', style: TextStyle(fontSize: s12, color: Color(0xFF5F5F5F))), TextSpan( text: '《用户协议》', style: TextStyle(fontSize: s12, color: Color(0xFF074CE7)), recognizer: TapGestureRecognizer() ..onTap = () { Navigator.push( context, MaterialPageRoute( builder: (context) => AgreementPage( title: "用户协议", url: "${NetworkConfig.configBean?.userAgreement}", )), ); }), TextSpan(text: '和', style: TextStyle(fontSize: s12, color: Color(0xFF5F5F5F))), TextSpan( text: '《隐私政策》', style: TextStyle(fontSize: s12, color: Color(0xFF074CE7)), recognizer: TapGestureRecognizer() ..onTap = () { Navigator.push( context, MaterialPageRoute( builder: (context) => AgreementPage( title: "隐私政策", url: "${NetworkConfig.configBean?.privacyAgreement}", )), ); }), ]), ), ) ], ), ) ], ), ), ], ), ), ); } }