import 'dart:async'; import 'dart:io'; import 'package:eitc_erm_app/register.dart'; import 'package:eitc_erm_app/utils/Component.dart'; import 'package:eitc_erm_app/utils/Constants.dart'; import 'package:eitc_erm_app/utils/Utils.dart'; import 'package:eitc_erm_app/utils/logger.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:http/http.dart' as http; import 'package:http/http.dart'; import 'bean/login_entity.dart'; import 'bean/normal_response.dart'; import 'bottom_navigation.dart'; import 'doctor_talk_list.dart'; void main() { WidgetsFlutterBinding.ensureInitialized(); runApp(Login()); } class Login extends StatefulWidget { @override State createState() => LoginState(); } class LoginState extends State { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('登录'), centerTitle: true), body: Center( child: MyBody(), ), ); } } class MyBody extends StatefulWidget { @override _MyBodyState createState() => _MyBodyState(); } class _MyBodyState extends State { bool isButtonEnable = true; //按钮状态 是否可点击 String buttonText = '发送验证码'; //初始文本 int count = 60; //初始倒计时时间 Timer? timer; //倒计时的计时器 TextEditingController mController = TextEditingController(); TextEditingController phoneController = TextEditingController(); bool isPasswordLogin = false; String passText = "验证码"; String loginText = "密码登录"; String hintText = "请输入验证码"; int patientOrDoctor = 1; void _buttonClickListen() { if (!Utils.isChinaPhoneLegal(phoneController.text)) { Component.toast("请输入正确手机号码!", 0); return null; } setState(() { sendCaptchaCode(); if (isButtonEnable) { isButtonEnable = false; //按钮状态标记 _initTimer(); return null; //返回null按钮禁止点击 } else { return null; //返回null按钮禁止点击 } }); } void _initTimer() { timer = Timer.periodic(const Duration(seconds: 1), (Timer timer) { count--; setState(() { if (count == 0) { timer.cancel(); //倒计时结束取消定时器 isButtonEnable = true; //按钮可点击 count = 60; //重置时间 buttonText = '发送验证码'; //重置按钮文本 } else { buttonText = '重新发送($count)'; //更新文本内容 } }); }); } @override void dispose() { timer?.cancel(); //销毁计时器 super.dispose(); } @override Widget build(BuildContext context) { return SingleChildScrollView( child: Container( padding: const EdgeInsets.only(top: 10.0, left: 10.0, right: 10.0), child: Column( children: [ Container( color: Colors.white, padding: const EdgeInsets.only(left: 10, right: 10), child: Column( children: [ const Padding( padding: EdgeInsets.fromLTRB(0, 80, 0, 80), child: Center( child: Image( image: AssetImage('assets/images/logo.png'), ), ), ), Opacity( opacity: patientOrDoctor == 1 ? 1 : 0, child: const Align( alignment: Alignment.centerLeft, child: Text( '未注册的手机号验证后自动创建您的账号', style: TextStyle(color: Colors.blue, fontSize: 15), textAlign: TextAlign.left, overflow: TextOverflow.ellipsis, ), )), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ SizedBox( width: 50, child: Text( patientOrDoctor == 1 ? "+86" : "用户名", style: const TextStyle( fontSize: 13, color: Color(0xff333333)), ), ), Expanded( child: Padding( padding: const EdgeInsets.only(left: 0, right: 15, top: 5), child: TextFormField( maxLines: 1, onSaved: (value) {}, controller: phoneController, textAlign: TextAlign.left, inputFormatters: patientOrDoctor == 1 ? [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(11) ] : [], decoration: InputDecoration( hintText: (patientOrDoctor == 1 ? '请填写手机号' : "请填写用户名"), hintStyle: const TextStyle( color: Color(0xff999999), fontSize: 13, ), alignLabelWithHint: true, border: const OutlineInputBorder( borderSide: BorderSide.none), ), ), ), ), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.baseline, textBaseline: TextBaseline.alphabetic, children: [ SizedBox( width: 50, child: Text( passText, style: TextStyle( fontSize: 13, color: Color(0xff333333)), )), Expanded( child: Padding( padding: EdgeInsets.only(left: 0, right: 15, top: 0), child: TextFormField( maxLines: 1, onSaved: (value) {}, controller: mController, textAlign: TextAlign.left, obscureText: isPasswordLogin, inputFormatters: isPasswordLogin ? [] : [ FilteringTextInputFormatter.digitsOnly, LengthLimitingTextInputFormatter(6) ], decoration: InputDecoration( counterText: "", hintText: (hintText), hintStyle: TextStyle( color: Color(0xff999999), fontSize: 13, ), alignLabelWithHint: true, border: OutlineInputBorder( borderSide: BorderSide.none), ), ), ), ), Container( padding: const EdgeInsets.all(0), width: 120, child: Visibility( visible: !isPasswordLogin, child: ElevatedButton( style: ButtonStyle( backgroundColor: WidgetStateProperty.resolveWith( (states) { if (states.contains(WidgetState.disabled)) { return Colors.brown; // Disabled color } return Colors.blue; // Regular color }), foregroundColor: const WidgetStatePropertyAll(Colors.white), ), // backgroundColor : isButtonEnable // ? Color(0xff44c5fe) // : Colors.grey.withOpacity(0.1), //按钮的颜色 // splashColor: isButtonEnable // ? Colors.white.withOpacity(0.1) // : Colors.transparent, // shape: StadiumBorder(side: BorderSide.none), onPressed: () { if (isButtonEnable) { setState(() { _buttonClickListen(); }); } }, child: Text( buttonText, style: const TextStyle( fontSize: 12, ), ), ), ), ), ], ), ], ), ), Container( width: double.infinity, height: 45, margin: const EdgeInsets.only(top: 30, left: 10, right: 10), child: ElevatedButton( style: ButtonStyle( backgroundColor: MaterialStateProperty.resolveWith((states) { return Colors.blue; // Regular color }), ), onPressed: () { logd('手机号:${phoneController.text},验证码:${mController.text}'); login(); }, // shape: StadiumBorder(side: BorderSide.none), // color: Color(0xff44c5fe), child: Text( '登录', style: TextStyle(color: Colors.white, fontSize: 15), ), ), ), Padding( padding: EdgeInsets.all(20), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Text("患者"), Radio( value: 1, onChanged: (value) { setState(() { this.patientOrDoctor = value!; }); }, groupValue: patientOrDoctor, ), SizedBox( width: 20, ), Text("医生"), Radio( value: 2, onChanged: (value) { setState(() { patientOrDoctor = value!; isPasswordLogin = true; _updateText(); }); }, groupValue: patientOrDoctor, ), ], ), Visibility( visible: patientOrDoctor == 1, child: GestureDetector( onTap: () { isPasswordLogin = !isPasswordLogin; logd(isPasswordLogin); setState(() { _updateText(); }); }, child: Text( loginText, style: const TextStyle( color: Colors.blue, fontSize: 15), textAlign: TextAlign.right, ), )), ]), ) ], ), ), ); } void _updateText() { if (isPasswordLogin) { passText = "密 码"; loginText = "验证码登录"; hintText = "请输入密码"; } else { passText = "验证码"; loginText = "密码登录"; hintText = "请输入验证码"; } } Future launchAndroid() async { const platform = MethodChannel('com.example.xcx_dashan_app/channel'); try { var result = await platform.invokeMethod('launchApp'); // var result = await platform.invokeMethod('launchAppOne',{'param1': "这是一个参数"}); // var result = await platform.invokeMethod('launchAppOne',{'param1': "这是一个参数",'param2': "这是一个参数"}); logd("结果$result"); } on PlatformException catch (e) { logd("Failed to invoke method: '${e.message}'."); } } Future sendCaptchaCode() async { var params = { 'phoneNumber': phoneController.text, }; var response = await http.post( Uri.parse('${Global.BaseUrl}sendCaptchaCode'), headers: jsonHeaders(), body: encodeBody(params)); logd("encoded=${encodeBody(params)}"); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd(json); NormalResponse mNormalResponse = NormalResponse.fromJson(json); if (mNormalResponse.code == Global.responseSuccessCode) { Component.toast("短信发送成功,请查收!", 2); } else { Component.toast(mNormalResponse.msg.toString(), 0); } return response.toString(); } else { Component.toast("出错了,请稍后再试!", 0); return null; } } Future login() async { if (patientOrDoctor == 1) { if (!Utils.isChinaPhoneLegal(phoneController.text)) { Component.toast("请输入正确手机号码!", 0); return null; } } else { if (phoneController.text.isEmpty) { Component.toast("请输入用户名!", 0); return null; } } if (!isPasswordLogin && !Utils.isVerifyCode(mController.text)) { Component.toast("请输入正确验证码!", 0); return null; } //验证码登录 if (!isPasswordLogin) { bool bo = await _checkCaptchaCode(); if (!bo) { Component.toast("验证码错误!", 0); return null; } } Map params; if (isPasswordLogin) { params = { 'phoneNumber': phoneController.text, 'password': aesEncrypt(mController.text), 'type': patientOrDoctor, }; } else { params = { 'phoneNumber': phoneController.text, 'captchaCode': mController.text, 'type': patientOrDoctor, }; } String url = 'captcha/login'; if (isPasswordLogin) { url = 'password/login'; } logd("提交数据=$params"); var response = await http.post(Uri.parse(Global.BaseUrl + url), body: encodeBody(params), headers: jsonHeaders()); logd(response.body.toString()); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd(json); LoginEntity mLoginEntity = LoginEntity.fromJson(json); if (mLoginEntity.code == Global.responseSuccessCode) { Component.toast("登录成功!", 2); Global.loginPhoneNo = phoneController.text; Global.token = mLoginEntity.data!.token!; Global.user = mLoginEntity; if (patientOrDoctor == 2) { Utils.saveData("doctorToken", Global.token); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => DoctorTalkList()), ); } else { Utils.saveData("token", Global.token); Utils.saveData("userId", Global.user.data!.id.toString()); Utils.saveData("userAvatar", mLoginEntity.data?.avatar ?? ""); Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => BottomNavigationWidget()), ); } } else { Component.toast(mLoginEntity.msg.toString(), 0); if (mLoginEntity.msg.toString().contains("用户不存在") && patientOrDoctor == 1) { Navigator.push( context, MaterialPageRoute(builder: (context) => Register()), ); } } return response.toString(); } else { Component.toast("出错了,请稍后再试!", 0); return null; } } ///检查验证码 Future _checkCaptchaCode() async { Map params = { "phoneNumber": phoneController.text, "captchaCode": mController.text }; Uri uri = Uri.parse("${Global.BaseUrl}api/checkCaptchaCode"); logd("检查验证码,uri=$uri"); Response response = await http.post(uri, body: encodeBody(params), headers: jsonHeaders()); if (response.statusCode == 200) { final json = decodeBodyToJson(response.bodyBytes); logd("检查验证码结果$json"); NormalResponse mNormalResponse = NormalResponse.fromJson(json); return mNormalResponse.code == 200; } else { logd("检查验证码异常${response.body}"); } return false; } }