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), const Text('密码长度8-20位,需包含英文、数字及字符',style: TextStyle(color: Colors.grey),), const SizedBox(height: 12), MyButton( '保 存', onTap: onChange, gradient: const LinearGradient(colors: [Color(0xFF3BD2E5), Color(0xFF247AF8)]), radius: 10, fountSize: 18, fontWeight: FontWeight.w600, margin: const EdgeInsets.symmetric(horizontal: 12), ), ], ), ), ), ], ); } 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, 12, 16, 12), clipBehavior: Clip.hardEdge, decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(10)), color: Colors.white, ), child: Column( children: [ oldError.builder( (error) => buildEdit( titleName: '旧密码', ctrl: oldPwdCtrl, hint: '请填写旧密码', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, errorText: error, onChanged: (value) => verifyOldText(), ), ), const SizedBox(height: 12), newError.builder( (error) => buildEdit( titleName: '新密码', ctrl: newPwdCtrl, hint: '请输入新的密码', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, onChanged: (value) => verifyNewText(), errorText: error, ), ), const SizedBox(height: 12), confirmError.builder( (error) => buildEdit( titleName: '新密码', ctrl: confirmPwdCtrl, hint: '请再次输入新的密码', formatters: formatters, inputType: TextInputType.visiblePassword, obscureText: true, onChanged: (value) => verifyConfirmText(), errorText: error, ), ), ], ), ); } Widget buildEdit({ required TextEditingController ctrl, required String titleName, String? hint, TextInputAction action = TextInputAction.next, bool obscureText = false, ValueChanged? onSubmit, ValueChanged? onChanged, List? formatters, int? maxLength, String? errorText, TextInputType? inputType, }) { return PasswordTextField( controller: ctrl, textAlign: TextAlign.end, decoration: InputDecoration( prefixIcon: Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Text(titleName), ), prefixIconConstraints: const BoxConstraints(), border: const UnderlineInputBorder( borderSide: BorderSide(width: 1,color: Color(0xffF6F6F8)) ), enabledBorder: const UnderlineInputBorder( borderSide: BorderSide(width: 1,color: Color(0xffF6F6F8)) ), focusedBorder: const UnderlineInputBorder( borderSide: BorderSide(width: 1,color: Color(0xffF6F6F8)) ), 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, ); } }