import 'package:flutter/material.dart'; import 'package:flutter_common/utils/sp_utils.dart'; import 'package:flutter_common/utils/toast_util.dart'; import 'package:flutter_common/widget/loading_widget.dart'; import 'package:flutter_form_builder/flutter_form_builder.dart'; import 'package:food_hub_app/apis/session.dart'; import 'package:food_hub_app/models/session.dart'; import 'package:food_hub_app/widgets/common/form.dart'; import 'package:food_hub_app/widgets/common/index.dart'; import 'package:form_builder_validators/form_builder_validators.dart'; class LoginPage extends StatefulWidget { const LoginPage({super.key}); @override State createState() => _LoginPage(); } class _LoginPage extends State { final GlobalKey _formKey = GlobalKey(); String _username = "Cxx0822", _password = "19940822Cxx"; bool _isRemember = false; bool _isObscure = true; bool _isLoading = false; Color _eyeColor = Colors.grey; final List _loginMethod = [ {"title": "phone", "icon": Icons.phone_android}, {"title": "email", "icon": Icons.email}, {"title": "wechat", "icon": Icons.wechat}, ]; @override void initState() { super.initState(); _loadRememberState(); } Future _loadRememberState() async { bool? isRemember = SPUtil.getBool('isRemember'); if (isRemember) { setState(() { _isRemember = true; _username = SPUtil.getString('username'); _password = SPUtil.getString('password'); }); } } void handleRememberState() { if (_isRemember) { SPUtil.set('isRemember', true); SPUtil.set('username', _username); SPUtil.set('password', _password); } else { SPUtil.set('isRemember', false); SPUtil.remove('username'); SPUtil.remove('password'); } } void handleTokenState(String token) { SPUtil.set('token', token); } void handleUserInfo(User user) { SPUtil.set('userId', user.id); } void loginClick() async { setState(() { _isLoading = true; }); // 表单校验通过才会继续执行 if ((_formKey.currentState as FormState).validate()) { (_formKey.currentState as FormState).save(); try { LoadingDialog.show(context, message: '登录中'); Session session = await loginApi(_username, _password); ToastUtil.success('登录成功'); handleRememberState(); handleTokenState(session.saToken.tokenValue); handleUserInfo(session.userInfo); LoadingDialog.hide(context); Navigator.pushNamed(context, '/home'); } catch (e) { LoadingDialog.hide(context); ToastUtil.error(e.toString()); } } setState(() { _isLoading = false; }); } @override Widget build(BuildContext context) { return Scaffold( body: Form( key: _formKey, child: Column( children: [ Expanded(child: buildLoginForm()), Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 50), child: Column( children: [ buildOtherLoginText(), const SizedBox(height: 15), buildOtherMethod(context), const SizedBox(height: 20), buildRegisterText(context), ], ), ), ], ), ), ); } Widget buildTitle() { return const Text( '食光集', textAlign: TextAlign.center, style: TextStyle(fontSize: 42), ); } Widget buildLoginForm() { return ListView( padding: const EdgeInsets.symmetric(horizontal: 20), children: [ const SizedBox(height: kToolbarHeight), buildTitle(), const SizedBox(height: 60), buildUsernameTextField(), const SizedBox(height: 20), buildPasswordTextField(), const SizedBox(height: 10), buildRememberPasswordCheckbox(), const SizedBox(height: 20), buildLoginButton(), ], ); } Widget buildUsernameTextField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ formLabelText(labelText: "账号:"), const SizedBox(height: 10), FormBuilderTextField( name: 'username', initialValue: _username, keyboardType: TextInputType.text, decoration: buildInputDecoration( context: context, hintText: "请输入账号", prefixIcon: Icons.person, ), validator: FormBuilderValidators.required(), onSaved: (v) => _username = v!, ), ], ); } Widget buildPasswordTextField() { return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ formLabelText(labelText: "密码:"), const SizedBox(height: 10), FormBuilderTextField( name: 'password', initialValue: _password, keyboardType: TextInputType.visiblePassword, obscureText: _isObscure, onSaved: (v) => _password = v!, validator: FormBuilderValidators.required(), decoration: buildInputDecoration( context: context, hintText: "请输入密码", prefixIcon: Icons.lock, ).copyWith( suffixIcon: IconButton( icon: Icon(Icons.remove_red_eye, color: _eyeColor), onPressed: () { final colors = Theme.of(context).colorScheme; setState(() { _isObscure = !_isObscure; _eyeColor = (_isObscure ? Colors.grey : colors.surface); }); }, ), ), ), ], ); } Widget buildRememberPasswordCheckbox() { return Row( children: [ Checkbox( materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, visualDensity: VisualDensity.compact, value: _isRemember, onChanged: (bool? value) { setState(() { _isRemember = value ?? false; }); }, ), const Text('记住密码', style: TextStyle(color: Colors.grey, fontSize: 14)), ], ); } Widget buildLoginButton() { return SizedBox( height: 45, width: double.infinity, child: ElevatedButton( onPressed: _isLoading ? null : loginClick, style: ElevatedButton.styleFrom( backgroundColor: Theme.of(context).colorScheme.primary, foregroundColor: Colors.white, elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), ), child: const Text( '登录', style: TextStyle(fontSize: 16, fontWeight: FontWeight.w600), ), ), ); } Widget buildOtherLoginText() { return Row( children: [ Expanded(child: Divider(color: Colors.grey[300], thickness: 1)), Padding( padding: const EdgeInsets.symmetric(horizontal: 16), child: Text( '其他方式登录', style: TextStyle(color: Colors.grey, fontSize: 14), ), ), Expanded(child: Divider(color: Colors.grey[300], thickness: 1)), ], ); } Widget buildOtherMethod(context) { return OverflowBar( alignment: MainAxisAlignment.center, children: _loginMethod .map( (item) => Builder( builder: (context) { return IconButton( icon: Icon( item['icon'], color: Theme.of(context).iconTheme.color, ), onPressed: () { //TODO: 第三方登录方法 ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('${item['title']}登录'), action: SnackBarAction( label: '取消', onPressed: () {}, ), ), ); }, ); }, ), ) .toList(), ); } Widget buildRegisterText(context) { return Center( child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ const Text('没有账号?', style: TextStyle(fontSize: 18)), GestureDetector( child: const Text( '点击注册', style: TextStyle(fontSize: 18, color: Colors.green), ), onTap: () { print("点击注册"); }, ), ], ), ); } }