329 lines
12 KiB
Dart
329 lines
12 KiB
Dart
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<LoginPage> createState() => _LoginPageState();
|
|
}
|
|
|
|
class _LoginPageState extends State<LoginPage> {
|
|
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>[
|
|
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}",
|
|
)),
|
|
);
|
|
}),
|
|
]),
|
|
),
|
|
)
|
|
],
|
|
),
|
|
)
|
|
],
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|