279 lines
9.3 KiB
Dart
279 lines
9.3 KiB
Dart
import 'dart:convert';
|
||
|
||
import 'package:flutter/material.dart';
|
||
import 'package:qhd_prevention/customWidget/custom_button.dart';
|
||
import 'package:qhd_prevention/customWidget/toast_util.dart';
|
||
import 'package:qhd_prevention/pages/my_appbar.dart';
|
||
import 'package:qhd_prevention/pages/user/login_page.dart';
|
||
import 'package:qhd_prevention/services/SessionService.dart';
|
||
import 'package:shared_preferences/shared_preferences.dart';
|
||
import '../../http/ApiService.dart';
|
||
|
||
class MineSetPwdPage extends StatefulWidget {
|
||
const MineSetPwdPage(this.type, {super.key});
|
||
|
||
final String type;
|
||
@override
|
||
State<MineSetPwdPage> createState() => _MineSetPwdPageState();
|
||
}
|
||
|
||
class _MineSetPwdPageState extends State<MineSetPwdPage> {
|
||
final _formKey = GlobalKey<FormState>();
|
||
|
||
final _oldPwdController = TextEditingController();
|
||
final _newPwdController = TextEditingController();
|
||
final _confirmPwdController = TextEditingController();
|
||
|
||
bool _obscureOld = true;
|
||
bool _obscureNew = true;
|
||
bool _obscureConfirm = true;
|
||
|
||
String textString =
|
||
"为了您的账户安全,请确保密码长度为 8-18 位,必须包含大小写字母+数字+特殊字符,例如:Aa@123456";
|
||
|
||
Map<String, dynamic> passData = {
|
||
"id": '',
|
||
"password": "",
|
||
"newPassword": "",
|
||
};
|
||
|
||
@override
|
||
void initState() {
|
||
super.initState();
|
||
switch (widget.type) {
|
||
case "0":
|
||
textString =
|
||
"密码长度8-18位,需包含数字、字母、英文符号至少2种或以上元素";
|
||
break;
|
||
case "1":
|
||
textString =
|
||
"检测到您的密码为弱密码,请修改密码后重新登录。为了您的账户安全,请确保密码长度为 8-18 位,必须包含大小写字母+数字+特殊字符,例如:Aa@123456";
|
||
break;
|
||
case "2":
|
||
textString =
|
||
"检测到您30天内未修改密码,请修改密码后重新登录。为了您的账户安全,请确保密码长度为 8-18 位,必须包含大小写字母+数字+特殊字符,例如:Aa@123456";
|
||
break;
|
||
case "3":
|
||
textString =
|
||
"检测到您的密码为弱密码,请修改密码后重新登录。为了您的账户安全,请确保密码长度为 8-18 位,必须包含大小写字母+数字+特殊字符,例如:Aa@123456";
|
||
break;
|
||
case "4":
|
||
textString =
|
||
"检测到您30天内未修改密码,请修改密码后重新登录。为了您的账户安全,请确保密码长度为 8-18 位,必须包含大小写字母+数字+特殊字符,例如:Aa@123456";
|
||
break;
|
||
}
|
||
}
|
||
|
||
@override
|
||
void dispose() {
|
||
_oldPwdController.dispose();
|
||
_newPwdController.dispose();
|
||
_confirmPwdController.dispose();
|
||
super.dispose();
|
||
}
|
||
|
||
// 与登录页一致的输入框样式
|
||
Widget _buildRoundedInput({
|
||
required TextEditingController controller,
|
||
required String hint,
|
||
bool obscure = false,
|
||
VoidCallback? toggleObscure,
|
||
FormFieldValidator<String>? validator,
|
||
}) {
|
||
return TextFormField(
|
||
controller: controller,
|
||
obscureText: obscure,
|
||
validator: validator,
|
||
decoration: InputDecoration(
|
||
hintText: hint,
|
||
hintStyle: const TextStyle(color: Colors.grey),
|
||
filled: true,
|
||
fillColor: const Color(0xFFE2EBF4),
|
||
contentPadding: const EdgeInsets.symmetric(horizontal: 20, vertical: 14),
|
||
suffixIcon: toggleObscure == null
|
||
? null
|
||
: IconButton(
|
||
icon: Icon(
|
||
obscure ? Icons.visibility_off : Icons.visibility,
|
||
color: Colors.grey,
|
||
),
|
||
onPressed: toggleObscure,
|
||
),
|
||
enabledBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(30),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
focusedBorder: OutlineInputBorder(
|
||
borderRadius: BorderRadius.circular(30),
|
||
borderSide: BorderSide.none,
|
||
),
|
||
),
|
||
style: const TextStyle(color: Colors.black),
|
||
);
|
||
}
|
||
|
||
// 密码复杂度校验
|
||
bool isPasswordValid(String password) {
|
||
final hasUpperCase = RegExp(r'[A-Z]');
|
||
final hasLowerCase = RegExp(r'[a-z]');
|
||
final hasNumber = RegExp(r'[0-9]');
|
||
final hasSpecialChar = RegExp(r'[!@#\$%\^&\*\(\)_\+\-=\[\]\{\};:"\\|,.<>\/\?~`]');
|
||
return hasUpperCase.hasMatch(password) &&
|
||
hasLowerCase.hasMatch(password) &&
|
||
hasNumber.hasMatch(password) &&
|
||
hasSpecialChar.hasMatch(password);
|
||
}
|
||
|
||
void _handleSubmit() async {
|
||
// 使用 Form 验证必填
|
||
if (!(_formKey.currentState?.validate() ?? false)) return;
|
||
|
||
final oldPwd = _oldPwdController.text.trim();
|
||
final newPwd = _newPwdController.text.trim();
|
||
final confirmPwd = _confirmPwdController.text.trim();
|
||
|
||
if (newPwd != confirmPwd) {
|
||
ToastUtil.showNormal(context, '新密码和确认密码两次输入的密码不一致');
|
||
return;
|
||
}
|
||
|
||
if (newPwd.length < 8) {
|
||
ToastUtil.showNormal(context, '新密码需要大于8位');
|
||
return;
|
||
}
|
||
|
||
if (newPwd.length > 32) {
|
||
ToastUtil.showNormal(context, '新密码需要小于32位');
|
||
return;
|
||
}
|
||
|
||
if (!isPasswordValid(newPwd)) {
|
||
ToastUtil.showNormal(context, '新密码必须包含大小写字母、数字和特殊符号。');
|
||
return;
|
||
}
|
||
|
||
await _changePass(oldPwd, newPwd, confirmPwd);
|
||
}
|
||
|
||
Future<void> _changePass(String oldPwd, String newPwd, String confirmPwd) async {
|
||
try {
|
||
passData['id'] = SessionService.instance.accountId ?? "";
|
||
passData['password'] = oldPwd;
|
||
passData['newPassword'] = newPwd;
|
||
passData['confirmPassword'] = confirmPwd;
|
||
|
||
final raw = await AuthApi.changePassWord(passData);
|
||
|
||
if (raw['success'] == true) {
|
||
ToastUtil.showNormal(context, '新密码修改成功!');
|
||
Navigator.pop(context, true);
|
||
|
||
// 清除用户登录状态
|
||
await _clearUserSession();
|
||
|
||
// 跳转到登录页并清除所有历史路由
|
||
Navigator.pushAndRemoveUntil(
|
||
context,
|
||
MaterialPageRoute(builder: (context) => const LoginPage()),
|
||
(Route<dynamic> route) => false,
|
||
);
|
||
} else if (raw['success'] == false) {
|
||
ToastUtil.showNormal(context, '当前密码密码有误');
|
||
} else {
|
||
ToastUtil.showNormal(context, '登录错误!请联系管理员');
|
||
}
|
||
} catch (e) {
|
||
print('修改密码出错:$e');
|
||
ToastUtil.showNormal(context, '登录错误!请联系管理员');
|
||
}
|
||
}
|
||
|
||
Future<void> _clearUserSession() async {
|
||
final prefs = await SharedPreferences.getInstance();
|
||
await prefs.remove('isLoggedIn'); // 清除登录状态
|
||
// 根据你项目的实际 key 再删除 token 等(如果有)
|
||
// await prefs.remove('user_token');
|
||
}
|
||
|
||
@override
|
||
Widget build(BuildContext context) {
|
||
return Scaffold(
|
||
backgroundColor: Colors.white,
|
||
appBar: const MyAppbar(title: '修改密码'),
|
||
body: SafeArea(
|
||
child: Padding(
|
||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 20),
|
||
child: Form(
|
||
key: _formKey,
|
||
child: Column(
|
||
crossAxisAlignment: CrossAxisAlignment.start,
|
||
children: [
|
||
const Text(
|
||
'修改密码',
|
||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||
),
|
||
const SizedBox(height: 30),
|
||
|
||
// 当前密码
|
||
_buildRoundedInput(
|
||
controller: _oldPwdController,
|
||
hint: '当前密码',
|
||
obscure: _obscureOld,
|
||
toggleObscure: () => setState(() => _obscureOld = !_obscureOld),
|
||
validator: (v) {
|
||
if (v == null || v.isEmpty) return '请输入当前密码';
|
||
return null;
|
||
},
|
||
),
|
||
const SizedBox(height: 20),
|
||
|
||
// 新密码
|
||
_buildRoundedInput(
|
||
controller: _newPwdController,
|
||
hint: '新密码',
|
||
obscure: _obscureNew,
|
||
toggleObscure: () => setState(() => _obscureNew = !_obscureNew),
|
||
validator: (v) {
|
||
if (v == null || v.isEmpty) return '请输入新密码';
|
||
return null;
|
||
},
|
||
),
|
||
const SizedBox(height: 20),
|
||
|
||
// 确认新密码
|
||
_buildRoundedInput(
|
||
controller: _confirmPwdController,
|
||
hint: '确认新密码',
|
||
obscure: _obscureConfirm,
|
||
toggleObscure: () => setState(() => _obscureConfirm = !_obscureConfirm),
|
||
validator: (v) {
|
||
if (v == null || v.isEmpty) return '请输入确认密码';
|
||
return null;
|
||
},
|
||
),
|
||
const SizedBox(height: 15),
|
||
|
||
Text(
|
||
textString,
|
||
style: const TextStyle(color: Colors.red, fontSize: 13),
|
||
),
|
||
const SizedBox(height: 30),
|
||
|
||
SizedBox(
|
||
width: double.infinity,
|
||
height: 45,
|
||
child: CustomButton(
|
||
onPressed: _handleSubmit,
|
||
text: "提交",
|
||
backgroundColor: Colors.blue,
|
||
),
|
||
),
|
||
],
|
||
),
|
||
),
|
||
),
|
||
),
|
||
);
|
||
}
|
||
}
|