import 'dart:async'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; import 'package:lszlgl/base/base_state.dart'; import 'package:lszlgl/main.dart'; import 'package:lszlgl/network/my_api.dart'; import 'package:lszlgl/widget/button.dart'; import 'package:lszlgl/widget/password_textfield.dart'; /// 修改密码 class ChangePwdPage extends StatefulWidget { final bool startHome; const ChangePwdPage({ Key? key, bool? startHome, }) : startHome = startHome ?? false, super(key: key); @override State createState() => _ChangePwdPageState(); } class _ChangePwdPageState extends BaseState { late TextEditingController oldPwdCtrl; late TextEditingController newPwdCtrl; late TextEditingController confirmPwdCtrl; final ValueNotifier oldError = null.notifier(); final ValueNotifier newError = null.notifier(); final ValueNotifier confirmError = null.notifier(); void onChange() async { List verifyList = await Future.wait([verifyOldText(), verifyNewText(), verifyConfirmText()]); if (!verifyList.firstWhere((element) => !element, orElse: () => true)) { return; } MyNavigator.showLoading(msg: '密码修改中...'); try { var rsp = await MyApi.get().updatePassword({ 'oldPassword': oldPwdCtrl.text, 'newPassword': newPwdCtrl.text, }); if (rsp.data ?? false) { MyNavigator.showToast('修改成功'); if (widget.startHome) { // 进入主页 MyRouter.startMain(popAll: true); } else { MyNavigator.pop(); } } } catch (e) { logger.e(e); } MyNavigator.dismissLoading(); } Future verifyOldText() async { var text = oldPwdCtrl.text; if (text.isEmpty) { oldError.value = '请输入旧密码'; return false; } int length = text.length; if (length < 8) { oldError.value = '密码长度要大于8位'; return false; } oldError.value = null; return true; } Future verifyNewText() async { var text = newPwdCtrl.text; if (text.isEmpty) { newError.value = '请输入新密码'; return false; } int length = text.length; if (length < 8) { newError.value = '密码长度要大于8位'; return false; } var regex = RegExp(r'\d'); if (!regex.hasMatch(text)) { newError.value = '密码要包含数字'; return false; } regex = RegExp(r'[a-zA-Z]'); if (!regex.hasMatch(text)) { newError.value = '密码要包含大写字母或小写字母'; return false; } regex = RegExp(r'[!\"#$%&()*+,-./:;<=>?@\]\[^_`{|}~]'); if (!regex.hasMatch(text)) { newError.value = '密码要包含特殊字符'; return false; } newError.value = null; return true; } Future verifyConfirmText() async { var text = confirmPwdCtrl.text; if (text.isEmpty) { confirmError.value = '请输入确认密码'; return false; } if (text != newPwdCtrl.text) { confirmError.value = '两次输入密码不一致'; return false; } confirmError.value = null; return true; } @override void initState() { super.initState(); oldPwdCtrl = TextEditingController(); newPwdCtrl = TextEditingController(); confirmPwdCtrl = TextEditingController(); } @override void dispose() { super.dispose(); } @override Widget build(BuildContext context) { return myScaffold( child: KeyboardDismissOnTap( dismissOnCapturedTaps: true, child: buildBody(), ), ); } Widget buildBody() { return Column( children: [ myAppBar(title: '修改密码'), Expanded( child: SingleChildScrollView( child: Column( children: [ buildList(), const SizedBox(height: 32), MyButton( '确认修改', onTap: onChange, gradient: const LinearGradient(colors: [Color(0xFF3BD2E5), Color(0xFF247AF8)]), alignment: Alignment.center, minHeight: 40, margin: const EdgeInsets.symmetric(horizontal: 24), ), ], ), ), ), ], ); } Widget buildList() { var formatters = [FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z0-9!\"#$%&()*+,-./:;<=>?@\]\[^_`{|}~]'))]; return Container( margin: const EdgeInsets.symmetric(horizontal: 12), padding: const EdgeInsets.fromLTRB(16, 24, 16, 8), clipBehavior: Clip.hardEdge, decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(10)), color: Colors.white, ), child: Column( children: [ oldError.builder( (error) => buildEdit( ctrl: oldPwdCtrl, labelText: '旧密码', hint: '请输入', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, errorText: error, onChanged: (value) => verifyOldText(), ), ), const SizedBox(height: 12), newError.builder( (error) => buildEdit( ctrl: newPwdCtrl, labelText: '新密码', hint: '密码长度8-20位,需包含英文、数字及字符', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, maxLength: 20, onChanged: (value) => verifyNewText(), errorText: error, ), ), const SizedBox(height: 12), confirmError.builder( (error) => buildEdit( ctrl: confirmPwdCtrl, labelText: '确认密码', hint: '密码长度8-20位,需包含英文、数字及字符', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, maxLength: 20, onChanged: (value) => verifyConfirmText(), errorText: error, ), ), ], ), ); } Widget buildEdit({ required TextEditingController ctrl, String? hint, String? labelText, TextInputAction action = TextInputAction.next, bool obscureText = false, ValueChanged? onSubmit, ValueChanged? onChanged, List? formatters, int? maxLength, String? errorText, TextInputType? inputType, }) { return PasswordTextField( controller: ctrl, decoration: InputDecoration( prefixIcon: Padding( padding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), child: Image.asset(imgLoginPwd, height: 18), ), prefixIconConstraints: const BoxConstraints(), border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(100))), enabledBorder: const OutlineInputBorder( borderSide: BorderSide(color: Color(0xFFE6E6E6), width: 1), borderRadius: BorderRadius.all(Radius.circular(100)), ), labelText: labelText, hintText: hint, hintStyle: const TextStyle(color: Color(0xFFBBBBBB)), isDense: true, contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 12), errorText: errorText, ), maxLength: maxLength, style: const TextStyle(fontSize: 14), textInputAction: action, initialObscurity: obscureText, onSubmitted: onSubmit, onChanged: onChanged, inputFormatters: formatters, ); } }