diff --git a/lib/constants/api.dart b/lib/constants/api.dart index 412388c..12ecfc2 100644 --- a/lib/constants/api.dart +++ b/lib/constants/api.dart @@ -54,6 +54,12 @@ class _App { ///会员体验 String get trialVip => '/app/user/trialVip'; + + ///输入密码 + String get psdAdd=>'/app/register'; + + ///密码登录 + String get psdLogin=>'/app/loginByPwd'; } class _Content { diff --git a/lib/ui/login/login_page.dart b/lib/ui/login/login_page.dart index f24b7b5..eebf22b 100644 --- a/lib/ui/login/login_page.dart +++ b/lib/ui/login/login_page.dart @@ -6,6 +6,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:project_telephony/ui/login/login_psd_page.dart'; import 'package:project_telephony/ui/widget/plone_back_button.dart'; import 'package:project_telephony/utils/headers.dart'; import 'package:provider/provider.dart'; @@ -23,8 +24,7 @@ import '../widget/image_scaffold.dart'; import '../widget/plone_bottom.dart'; class LoginPage extends StatefulWidget { - const - LoginPage({Key? key}) : super(key: key); + const LoginPage({Key? key}) : super(key: key); @override _LoginPageState createState() => _LoginPageState(); @@ -118,9 +118,26 @@ class _LoginPageState extends State { style: TextStyle(fontSize: 32.sp, color: const Color(0xFF999999)), ), 80.hb, - _getBox('+86', 36, _phoneTFWidget()), - _getBox('验证码', 32, _codeWidget()), - 112.hb, + LoginBoxWidget(text: '+86', fontSize: 36, plone: _phoneTFWidget()), + LoginBoxWidget(text: '验证码', fontSize: 32, plone: _codeWidget()), + Row( + children: [ + const Spacer(), + TextButton( + onPressed: () { + Get.to(()=>const LoginPsdPage()); + }, + child: const Text( + '密码登录', + style: TextStyle( + fontSize: 15, + decoration: TextDecoration.underline, + ), + ), + ), + ], + ), + 60.hb, PloneBottom( blM: false, border: _phoneController.text.length != 11, @@ -134,8 +151,8 @@ class _LoginPageState extends State { } else if (!_chooseAgreement) { BotToast.showText(text: "请同意并勾选隐私政策"); } else { - - if (_lastTap != null && DateTime.now().difference(_lastTap!).inSeconds < 2) { + if (_lastTap != null && + DateTime.now().difference(_lastTap!).inSeconds < 2) { // BotToast.showText(text: "过快"); return; } @@ -145,7 +162,7 @@ class _LoginPageState extends State { 'code': _smsCodeController.text }); if (base.code == 0) { - await UserTool.userProvider.setToken(base.data['token']); + await UserTool.userProvider.setToken(base.data['token']); Get.offAll(const TabNavigator()); } else { CloudToast.show(base.msg); @@ -162,39 +179,6 @@ class _LoginPageState extends State { ); } - _getBox(String text, int fontSize, Widget plone) { - return Container( - height: 144.w, - width: double.infinity, - padding: EdgeInsets.symmetric(vertical: 48.w), - decoration: BoxDecoration( - // color: Colors.black12, - border: Border( - bottom: BorderSide(color: const Color(0xFFE8E8E8), width: 1.w), - ), - ), - child: Row(children: [ - SizedBox( - width: 112.w, - child: Text( - text, - style: TextStyle( - fontSize: fontSize.sp, - color: BaseStyle.color333333, - fontWeight: FontWeight.bold), - ), - ), - Container( - width: 2.w, - height: 48.w, - margin: EdgeInsets.symmetric(horizontal: 32.w), - color: const Color(0xFFE8E8E8), - ), - plone, - ]), - ); - } - // 输入手机号 _phoneTFWidget() { return SizedBox( @@ -368,3 +352,45 @@ class _LoginPageState extends State { ); } } + +class LoginBoxWidget extends StatelessWidget { + final String text; + final int fontSize; + final Widget plone; + const LoginBoxWidget({Key? key, required this.text, required this.fontSize, required this.plone}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Container( + height: 144.w, + width: double.infinity, + padding: EdgeInsets.symmetric(vertical: 48.w), + decoration: BoxDecoration( + // color: Colors.black12, + border: Border( + bottom: BorderSide(color: const Color(0xFFE8E8E8), width: 1.w), + ), + ), + child: Row(children: [ + SizedBox( + width: 112.w, + child: Text( + text, + style: TextStyle( + fontSize: fontSize.sp, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + ), + ), + Container( + width: 2.w, + height: 48.w, + margin: EdgeInsets.symmetric(horizontal: 32.w), + color: const Color(0xFFE8E8E8), + ), + plone, + ]), + ); + } +} + diff --git a/lib/ui/login/login_psd_page.dart b/lib/ui/login/login_psd_page.dart new file mode 100644 index 0000000..37784d1 --- /dev/null +++ b/lib/ui/login/login_psd_page.dart @@ -0,0 +1,273 @@ +import 'package:bot_toast/bot_toast.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:project_telephony/extensions/num_ext.dart'; +import 'package:project_telephony/ui/login/login_page.dart'; + +import '../../base/base_style.dart'; +import '../../constants/api.dart'; +import '../../gen/assets.gen.dart'; +import '../../model/network/api_client.dart'; +import '../../utils/toast/cloud_toast.dart'; +import '../../utils/user_tool.dart'; +import '../tab_navigator.dart'; +import '../user/content_authority_page.dart'; +import '../widget/image_scaffold.dart'; +import '../widget/plone_back_button.dart'; +import '../widget/plone_bottom.dart'; + +class LoginPsdPage extends StatefulWidget { + const LoginPsdPage({Key? key}) : super(key: key); + + @override + _LoginPsdPageState createState() => _LoginPsdPageState(); +} + +class _LoginPsdPageState extends State { + bool _chooseAgreement = false; + late TextEditingController _phoneController; + late TextEditingController _pwdController; + DateTime? _lastTap; + late bool _showPwd = true; + + @override + void initState() { + super.initState(); + _phoneController = TextEditingController(); + _pwdController = TextEditingController(); + } + + @override + void dispose() { + _phoneController.dispose(); + _pwdController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return CloudScaffold( + systemStyle: const SystemUiOverlayStyle( + statusBarIconBrightness: Brightness.dark, + ), + path: Assets.images.bg.path, + appbar: Row( + children: [ + Padding( + padding: EdgeInsets.only(top: 88.w, left: 8.w), + child: const CloudBackButton(isSpecial: true), + ), + Padding( + padding: EdgeInsets.only(left: 186.w, top: 88.w), + child: Text( + "", + style: TextStyle( + fontSize: BaseStyle.fontSize34, + color: BaseStyle.color333333, + fontWeight: FontWeight.bold), + )) + ], + ), + extendBody: true, + body: Container( + padding: EdgeInsets.only(left: 64.w, right: 64.w, top: 124.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + "短信帮手", + style: TextStyle( + fontSize: 64.sp, + fontWeight: FontWeight.bold, + color: Colors.black), + ), + 32.hb, + Text( + "希望能成为您的短信小助手", + style: TextStyle(fontSize: 32.sp, color: const Color(0xFF999999)), + ), + 80.hb, + LoginBoxWidget(text: "+86", fontSize: 36, plone: _phoneTFWidget()), + LoginBoxWidget(text: "密码", fontSize: 32, plone: _pwdWidget()), + Row( + children: [ + const Spacer(), + TextButton( + onPressed: () { + Get.to(() => const LoginPage()); + }, + child: const Text( + '验证码登录', + style: TextStyle( + fontSize: 15, + decoration: TextDecoration.underline, + ), + ), + ), + ], + ), + 60.hb, + PloneBottom( + blM: false, + border: _phoneController.text.length != 11, + opacity: _phoneController.text.length == 11 ? 1 : 0.4, + onTap: () async { + // DateTime? _lastTap; + if (_phoneController.text.length < 11) { + BotToast.showText(text: "请输入手机号"); + } else if (!_chooseAgreement) { + BotToast.showText(text: "请同意并勾选隐私政策"); + } else { + if (_lastTap != null && + DateTime.now().difference(_lastTap!).inSeconds < 2) { + // BotToast.showText(text: "过快"); + return; + } + _lastTap = DateTime.now(); + var base = await apiClient.request(API.app.psdLogin, data: { + 'phone': _phoneController.text, + 'password': _pwdController.text + }); + if (base.code == 0) { + await UserTool.userProvider.setToken(base.data['token']); + Get.offAll(const TabNavigator()); + } else { + CloudToast.show(base.msg); + } + } + }, + text: "立即登录", + ), + 32.hb, + _getText() + ], + ), + ), + ); + } + + _getText() { + return GestureDetector( + onTap: () { + _chooseAgreement = !_chooseAgreement; + setState(() {}); + }, + child: Row( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Container( + width: 50.w, + height: 50.w, + padding: EdgeInsets.only(top: 6.w, right: 5.w), + child: !_chooseAgreement + ? const Icon(CupertinoIcons.circle, + size: 18, color: Color(0xFFdddddd)) + : const Icon(CupertinoIcons.checkmark_circle, + size: 18, color: Colors.blue), + ), + RichText( + text: TextSpan( + text: "我已阅读并同意", + style: + TextStyle(color: BaseStyle.colorcccccc, fontSize: 12 * 2.sp), + children: [ + // TextSpan( + // text: '《用户服务协议》', + // style: TextStyle(color: kPrimaryColor, fontSize: 12 * 2.sp), + // recognizer: _recognizer(context, 2)), + // TextSpan( + // text: "和", + // style: TextStyle( + // color: BaseStyle.colorcccccc, fontSize: 12 * 2.sp), + // ), + TextSpan( + text: '《短信帮手隐私协议》', + style: TextStyle(color: kPrimaryColor, fontSize: 12 * 2.sp), + recognizer: _recognizer(context, 2)), + ], + ), + ), + ], + ), + ); + } + + _recognizer(context, int type) { + final TapGestureRecognizer recognizer = TapGestureRecognizer(); + recognizer.onTap = () { + if (kDebugMode) { + Get.to(() => const ContentAuthorityPage()); + // print("点击协议了"); + } + + ///跳转到用户协议页面 + }; + return recognizer; + } + + _phoneTFWidget() { + return SizedBox( + // alignment: Alignment.centerLeft, + // padding: EdgeInsets.symmetric(horizontal: 72.w), + width: 430.w, + height: 50.w, + child: TextField( + maxLength: 11, + inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))], + textCapitalization: TextCapitalization.none, + onChanged: (text) { + _phoneController.text = text; + setState(() {}); + }, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(bottom: 20.w), + border: InputBorder.none, + counterText: "", + //textfield占位语,类似于iOS中的placeholder + hintText: "请输入手机号", + //占位语颜色 + hintStyle: const TextStyle(color: Colors.black12), + ), + ), + ); + } + + _pwdWidget() { + return SizedBox( + width: 430.w, + height: 50.w, + child: TextField( + obscureText: _showPwd, + maxLength: 16, + textCapitalization: TextCapitalization.none, + onChanged: (text) { + _pwdController.text = text; + setState(() {}); + }, + decoration: InputDecoration( + contentPadding: EdgeInsets.only(bottom: 20.w), + border: InputBorder.none, + counterText: "", + hintText: "请输入密码", + //占位语颜色 + hintStyle: const TextStyle(color: Colors.black12), + suffixIcon: IconButton( + padding: EdgeInsets.zero, + onPressed: () { + _showPwd = !_showPwd; + setState((){}); + }, + icon: Icon(Icons.remove_red_eye,color: _showPwd?Colors.black38:Colors.blue,), + ), + ), + ), + ); + } +} diff --git a/lib/ui/user/set_password_page.dart b/lib/ui/user/set_password_page.dart new file mode 100644 index 0000000..bb9bc02 --- /dev/null +++ b/lib/ui/user/set_password_page.dart @@ -0,0 +1,157 @@ +import 'package:bot_toast/bot_toast.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:project_telephony/utils/headers.dart'; + +import '../../constants/api.dart'; +import '../../model/network/api_client.dart'; +import '../../model/network/base_model.dart'; +import '../widget/scaffold_theme_widget.dart'; + +class SetPasswordPage extends StatefulWidget { + const SetPasswordPage({Key? key}) : super(key: key); + + @override + _SetPasswordPageState createState() => _SetPasswordPageState(); +} + +class _SetPasswordPageState extends State { + late TextEditingController _psdController; + late TextEditingController _psdTwiceController; + final _isOk=false; + + static bool isLoginPassword(String input) { + RegExp mobile = RegExp(r"(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,16}$"); + return mobile.hasMatch(input); + } + + @override + void initState() { + super.initState(); + _psdController = TextEditingController(); + _psdTwiceController = TextEditingController(); + } + + @override + void dispose() { + _psdController.dispose(); + _psdTwiceController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return ScaffoldThemeWidget( + title: "设置密码", + bottom: "确认", + onTap: () async { + if(_psdController.text==_psdTwiceController.text){ + BaseModel res = await apiClient.request(API.app.psdAdd, + data: {"password": _psdController.text}); + if(res.code==0){ + BotToast.showText(text: "设置成功"); + }else{ + BotToast.showText(text:"设置密码出错"); + } + Get.back(); + }else{ + BotToast.showText(text: "两次输入的密码不相同"); + } + }, + isOpacity:_psdController.text.isNotEmpty&&isLoginPassword(_psdController.text), + child: Container( + padding: EdgeInsets.all(40.w), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text( + '新 密 码 ', + style: TextStyle( + fontSize: 30.sp, + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 10.w), + child: TextField( + onChanged: (value){ + _psdController.text=value; + _psdController.value = TextEditingValue( + text: _psdController.text, + selection: + TextSelection.fromPosition(TextPosition( + affinity: TextAffinity.downstream, + offset: + _psdController.text.length, + ))); + setState((){}); + }, + inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9_]'))], + controller: _psdController, + decoration: const InputDecoration( + hintText: '填写新密码', + hintStyle: TextStyle( + color: Colors.black38, + ), + ), + ), + ) + , + ), + ], + ), + 20.hb, + Row( + children: [ + Text( + '确认密码 ', + style: TextStyle( + fontSize: 30.sp, + ), + ), + Expanded( + child: Padding( + padding: EdgeInsets.only(left: 10.w), + child: TextField( + onChanged: (value){ + _psdTwiceController.text=value; + _psdTwiceController.value = TextEditingValue( + text: _psdTwiceController.text, + selection: + TextSelection.fromPosition(TextPosition( + affinity: TextAffinity.downstream, + offset: + _psdTwiceController.text.length, + ))); + setState((){}); + }, + inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[A-Za-z0-9_]'))], + controller: _psdTwiceController, + decoration: const InputDecoration( + hintText: '再次确认密码', + hintStyle: TextStyle( + color: Colors.black38, + ), + ), + ), + ) + , + ), + ], + ), + 20.hb, + Text( + '密码必须是6~16位字母、数字、字符的组合', + style: TextStyle( + fontSize: 26.sp, + color: Colors.black38, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/ui/user/setting_page.dart b/lib/ui/user/setting_page.dart new file mode 100644 index 0000000..5575416 --- /dev/null +++ b/lib/ui/user/setting_page.dart @@ -0,0 +1,78 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; +import 'package:get/get.dart'; +import 'package:get/get_core/src/get_main.dart'; +import 'package:project_telephony/ui/user/set_password_page.dart'; +import 'package:project_telephony/ui/widget/scaffold_theme_widget.dart'; +import 'package:project_telephony/utils/user_tool.dart'; + +class SettingPage extends StatefulWidget { + const SettingPage({Key? key}) : super(key: key); + + @override + _SettingPageState createState() => _SettingPageState(); +} + +class _SettingPageState extends State { + @override + Widget build(BuildContext context) { + return ScaffoldThemeWidget( + title: "个人信息", + child: Container( + padding: EdgeInsets.all(40.w), + child: Column( + children: [ + Row( + children: [ + const Text( + '手机号', + style: TextStyle( + fontSize: 18, + ), + ), + const Spacer(), + Text( + UserTool.userProvider.userInfo.phone, + style: const TextStyle( + fontSize: 18, + color: Colors.black38, + ), + ), + Icon( + Icons.arrow_forward_ios, + size: 30.w, + ), + ], + ), + const Divider(), + GestureDetector( + + behavior: HitTestBehavior.opaque, + onTap: (){ + Get.to(()=>const SetPasswordPage()); + }, + child: Row( + children: [ + const Text( + '密码', + style: TextStyle( + fontSize: 18, + ), + ), + const Spacer(), + Icon( + Icons.arrow_forward_ios, + size: 30.w, + ), + ], + ), + ), + const Divider(), + ], + ), + ), + onTap: () {}, + ); + } +} diff --git a/lib/ui/user/user_page.dart b/lib/ui/user/user_page.dart index 9006a9b..12698a9 100644 --- a/lib/ui/user/user_page.dart +++ b/lib/ui/user/user_page.dart @@ -6,14 +6,14 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_background_service/flutter_background_service.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; -import 'package:flutter_update_dialog/update_dialog.dart'; - import 'package:project_telephony/base/base_style.dart'; import 'package:project_telephony/ui/login/login_page.dart'; import 'package:project_telephony/ui/tab_navigator.dart'; import 'package:project_telephony/ui/user/content_authority_page.dart'; import 'package:project_telephony/ui/user/members_page.dart'; import 'package:project_telephony/ui/user/privacy_rights_page.dart'; +import 'package:project_telephony/ui/user/set_password_page.dart'; +import 'package:project_telephony/ui/user/setting_page.dart'; import 'package:project_telephony/ui/user/user_card_page.dart'; import 'package:project_telephony/ui/widget/image_scaffold.dart'; import 'package:project_telephony/ui/widget/plone_bottom.dart'; @@ -217,6 +217,8 @@ class _UserPageState extends State { onTap: () { if (!userProvider.isLogin) { Get.to(() => const LoginPage()); + } else { + Get.to(() => const SettingPage()); } }, child: Column( @@ -236,9 +238,10 @@ class _UserPageState extends State { Text( UserTool.userProvider.isLogin ? "欢迎您登录短信帮手" : "登录获取更多信息", style: TextStyle( - fontSize: BaseStyle.fontSize28, - color: BaseStyle.color333333), - ) + fontSize: BaseStyle.fontSize28, + color: BaseStyle.color333333, + ), + ), ], ), ), diff --git a/lib/ui/widget/scaffold_theme_widget.dart b/lib/ui/widget/scaffold_theme_widget.dart index b6b0159..4d2ab00 100644 --- a/lib/ui/widget/scaffold_theme_widget.dart +++ b/lib/ui/widget/scaffold_theme_widget.dart @@ -4,6 +4,7 @@ import 'package:get/get.dart'; import 'package:project_telephony/model/sms_content_model.dart'; import 'package:project_telephony/utils/user_tool.dart'; import 'package:provider/provider.dart'; +import 'package:velocity_x/velocity_x.dart'; import '../../base/base_style.dart'; import '../../constants/api.dart'; @@ -28,7 +29,7 @@ class ScaffoldThemeWidget extends StatefulWidget { Key? key, required this.title, required this.child, - required this.bottom, + this.bottom='', this.isBorder = true, this.isOpacity = true, required this.onTap, @@ -61,13 +62,15 @@ class _ScaffoldThemeWidgetState extends State { backgroundColor: kForeGroundColor), backgroundColor: Colors.white, body: widget.child, - bottomNavigationBar: - PloneBottom( - onTap: widget.onTap, - border: widget.isBorder, - opacity: widget.isOpacity ? 1 : 0.4, - text: widget.bottom, - ).paddingOnly(bottom: 30.w), + bottomNavigationBar:Offstage( + offstage: widget.bottom.isEmpty, + child: PloneBottom( + onTap: widget.onTap, + border: widget.isBorder, + opacity: widget.isOpacity ? 1 : 0.4, + text: widget.bottom, + ).paddingOnly(bottom: 30.w), + ) ); } }