import 'dart:async'; import 'package:dating_touchme_app/http/api.dart'; import 'package:dating_touchme_app/model/phone_code.dart'; import 'package:dating_touchme_app/router/route_paths.dart'; import 'package:dating_touchme_app/utils/storage.dart'; import 'package:dating_touchme_app/utils/utils.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:go_router/go_router.dart'; import 'package:roundcheckbox/roundcheckbox.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPageState(); } class _LoginPageState extends State { String phone = ''; final TextEditingController _phoneController = TextEditingController(); String code = ''; final TextEditingController _codeController = TextEditingController(); String selectPhoneCode = "86"; int s = 0; Timer? timer; bool checked = false; void toggleChecked(bool? value) { checked = value ?? false; setState(() { }); } sendMsg() async { var res = await Api().$getAuthCaptcha({ "purpose":1, "verifiableAccount":phone, "verifiableAccountType":1 }); if(res["message"] == "successful"){ toast("发送成功", context); setState(() { s = 60; timer = Timer.periodic(const Duration(seconds: 1), (timer) { setState(() { s--; if(s == 0){ timer.cancel(); } }); }); }); } else { toast(res["msg"], context); } } @override Widget build(BuildContext context) { return Scaffold( body: Stack( children: [ Image.asset( "assets/login_bg.png", width: 750.w, fit: BoxFit.cover, ), Positioned( top: 419.w, left: 246.w, child: Text( "心动就动我 幸福马上行动", style: TextStyle( fontSize: 22.w, color: const Color.fromRGBO(144, 144, 144, 1), fontWeight: FontWeight.w500 ), ), ), Positioned( top: 538.w, child: Container( width: 750.w, padding: EdgeInsets.only( left: 50.w, right: 50.w, top: 256.w ), child: Column( children: [ InputItem(child: TextField( controller: _phoneController, keyboardType: TextInputType.number, style: TextStyle( fontSize: ScreenUtil().setWidth(28), height: 1 ), decoration: InputDecoration( prefixIcon: Container( margin: EdgeInsets.only(right: 30.w), decoration: const BoxDecoration( border: Border( right: BorderSide(color: const Color.fromRGBO(230, 230, 230, 1), width: 2), ), ), child: TextButton( onPressed: (){ final RenderBox renderBox = context.findRenderObject() as RenderBox; final Rect size = renderBox.localToGlobal(Offset.zero) & renderBox.size; final RelativeRect position = RelativeRect.fromRect( Rect.fromPoints(size.topLeft, size.bottomRight), Offset.zero & MediaQuery.of(context).size, ); showMenu( context: context, position: position, items: phoneCode.map((item){ return PopupMenuItem( value: item["tel"], child: Container( height: ScreenUtil().setWidth(100), padding: EdgeInsets.symmetric(horizontal: ScreenUtil().setWidth(32)), decoration: BoxDecoration( border: Border( // 设置边框 bottom: BorderSide( color: const Color.fromRGBO(228, 231, 237, 1), // 边框颜色 width: ScreenUtil().setWidth(1), ) // 边框宽度 ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text( item["name"], style: TextStyle( fontSize: ScreenUtil().setWidth(28), color: selectPhoneCode != item["tel"] ? const Color.fromRGBO(96, 98, 102, 1) : const Color.fromRGBO(212, 15, 31, 1) ), ), Text( "+${item["tel"]}", style: TextStyle( fontSize: ScreenUtil().setWidth(28), color: selectPhoneCode != item["tel"] ? const Color.fromRGBO(96, 98, 102, 1) : const Color.fromRGBO(212, 15, 31, 1) ), ) ], ), ), onTap: (){ setState(() { selectPhoneCode = item["tel"]; }); }, ); }).toList(), ); }, child: Text( "+$selectPhoneCode", style: TextStyle( fontSize: ScreenUtil().setWidth(35), color: const Color.fromRGBO(51, 51, 51, 1) ), ), ), ), contentPadding: EdgeInsets.symmetric( vertical: 0, horizontal: 34.w ), hintText: "请输入你的手机号", border: const OutlineInputBorder( borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 ), // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder focusedBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), enabledBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), ), onChanged: (value){ phone = value; setState(() { }); }, )), InputItem(child: TextField( controller: _codeController, keyboardType: TextInputType.number, style: TextStyle( fontSize: ScreenUtil().setWidth(28), height: 1 ), decoration: InputDecoration( contentPadding: EdgeInsets.symmetric( vertical: 0, horizontal: 34.w ), hintText: "请输入验证码", suffixIcon: TextButton( onPressed: (){ if(s > 0) return; if(phone == ""){ toast("请输入你的手机号", context); return; } // RegExp reg = RegExp(r'^1[3,4,5,6,7,8,9][0-9]{9}$'); // if(!reg.hasMatch(phone)){ // toast("请输入正确的手机号", context); // return; // } sendMsg(); }, child: Text( s > 0 ? "${s}s后再获取" : "获取验证码", style: TextStyle( fontSize: ScreenUtil().setWidth(28), color: const Color.fromRGBO(117, 98, 249, 1) ), ), ), border: const OutlineInputBorder( borderSide: BorderSide.none, // 这将移除边框 // 可选:设置圆角 ), // 如果你希望聚焦时和未聚焦时都没有边框,也可以设置 focusedBorder 和 enabledBorder focusedBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), enabledBorder: const OutlineInputBorder( borderSide: BorderSide.none, borderRadius: BorderRadius.all(Radius.circular(8.0)), ), ), onChanged: (value){ code = value; setState(() { }); }, )), SizedBox(height: 12.w,), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ RoundCheckBox( onTap: toggleChecked, isChecked: checked, size: ScreenUtil().setWidth(20), checkedColor: const Color.fromRGBO(0, 115, 254, 1), checkedWidget: Icon( Icons.check, color: const Color.fromRGBO(255, 255, 255, 1), size: ScreenUtil().setWidth(10), ), ), Container( margin: EdgeInsets.only(left: ScreenUtil().setWidth(5)), child: RichText( text: TextSpan( style: TextStyle( fontSize: ScreenUtil().setWidth(22), ), children: [ TextSpan( text: "我已阅读并同意动我", style: const TextStyle( color: Color.fromRGBO(189, 189, 189, 1) ) ), TextSpan( text: "《用户协议》", style: const TextStyle( color: Color.fromRGBO(189, 189, 189, 1) ), recognizer: TapGestureRecognizer()..onTap = () { context.pushNamed(RouteNames.webview, queryParameters: {"url": Uri.encodeComponent("http://www.baidu.com")}); }, ), TextSpan( text: "和", style: const TextStyle( color: Color.fromRGBO(189, 189, 189, 1) ) ), TextSpan( text: "《隐私政策》", style: const TextStyle( color: Color.fromRGBO(189, 189, 189, 1) ), recognizer: TapGestureRecognizer()..onTap = () { context.pushNamed(RouteNames.webview, queryParameters: {"url": Uri.encodeComponent("http://www.baidu.com")}); }, ), ] ), ), ) ], ), SizedBox(height: 175.w,), InkWell( onTap: () async { context.goNamed(RouteNames.completeInfo); return; if(phone == ""){ toast("请输入手机号", context); return; } if(code == ""){ toast("请输入6位数字验证码", context); return; } if(!checked) { toast("请阅读并同意用户协议", context); return; } var res = await Api().$login({ "account":phone, "accountType":2, "captcha":code }); if(res["code"] == 200){ // toast("登录成功", context); // await Storage().removeStorage("token"); // await Storage().setStorage("token", res["data"]["token"]); } else { toast(res["msg"], context); } context.goNamed(RouteNames.completeInfo); }, child: Container( width: 654.w, height: 105.w, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(105.w)), color: const Color.fromRGBO(217, 217, 217, 1), gradient: phone != "" && code != "" ? LinearGradient( begin: Alignment.centerLeft, end: Alignment.centerRight, colors: [ Color.fromRGBO(131, 89, 255, 1), // 起始颜色 Color.fromRGBO(61, 138, 224, 1), // 结束颜色 ], ) : null, ), child: Center( child: Text( "注册并登录", style: TextStyle( fontSize: 35.w, color: Colors.white, fontWeight: FontWeight.w500 ), ), ), ), ) ], ), ), ), ], ), ); } } class InputItem extends StatelessWidget { final Widget child; const InputItem({super.key, required this.child}); @override Widget build(BuildContext context) { return Container( margin: EdgeInsets.only(bottom: ScreenUtil().setWidth(27)), padding: EdgeInsets.symmetric(horizontal: ScreenUtil().setWidth(24)), child: Container( height: ScreenUtil().setWidth(88), decoration: BoxDecoration( border: Border.all(width: 1, color: const Color.fromRGBO(230, 230, 230, 1)), borderRadius: BorderRadius.all(Radius.circular(18.w)) ), child: Center( child: child, ), ), ); } }