66 lines
2.0 KiB
Dart
66 lines
2.0 KiB
Dart
/// 登录 / 注册页的表单状态与提交逻辑。
|
|
///
|
|
/// 校验规则与后端一致(邮箱格式、密码 8-64 位且含字母数字),本地先拦一次是为了少一次网络往返、
|
|
/// 也让用户立刻看到哪个字段不合格;后端仍会再校验一遍(前端校验不作为安全边界)。
|
|
class AuthLogic {
|
|
bool signUpMode;
|
|
String email = '';
|
|
String password = '';
|
|
bool busy = false;
|
|
String? errorMessage;
|
|
AuthFieldError? fieldError;
|
|
|
|
AuthLogic({this.signUpMode = false, this.errorMessage});
|
|
|
|
void toggleMode() {
|
|
signUpMode = !signUpMode;
|
|
errorMessage = null;
|
|
fieldError = null;
|
|
}
|
|
|
|
/// 返回 null 表示校验通过,否则返回错误文案(由视图用 l10n 映射)
|
|
AuthFieldError? validate() {
|
|
final mail = email.trim();
|
|
if (mail.isEmpty) return _record(AuthFieldError.emailRequired);
|
|
if (!_emailPattern.hasMatch(mail)) {
|
|
return _record(AuthFieldError.emailInvalid);
|
|
}
|
|
if (password.isEmpty) return _record(AuthFieldError.passwordRequired);
|
|
if (password.length < 8 || password.length > 64) {
|
|
return _record(AuthFieldError.passwordLength);
|
|
}
|
|
if (!_hasLetter.hasMatch(password) || !_hasDigit.hasMatch(password)) {
|
|
return _record(AuthFieldError.passwordWeak);
|
|
}
|
|
fieldError = null;
|
|
return null;
|
|
}
|
|
|
|
/// 清除当前字段错误;输入变化时由页面调用。
|
|
void clearFieldError() {
|
|
fieldError = null;
|
|
}
|
|
|
|
AuthFieldError _record(AuthFieldError error) {
|
|
fieldError = error;
|
|
return error;
|
|
}
|
|
|
|
String get normalizedEmail => email.trim().toLowerCase();
|
|
|
|
static final _emailPattern = RegExp(
|
|
r'^[A-Za-z0-9._%+\-]{1,64}@[A-Za-z0-9]([A-Za-z0-9\-]{0,61}[A-Za-z0-9])?'
|
|
r'(\.[A-Za-z0-9]([A-Za-z0-9\-]{0,61}[A-Za-z0-9])?)*\.[A-Za-z]{2,}$',
|
|
);
|
|
static final _hasLetter = RegExp('[A-Za-z]');
|
|
static final _hasDigit = RegExp('[0-9]');
|
|
}
|
|
|
|
enum AuthFieldError {
|
|
emailRequired,
|
|
emailInvalid,
|
|
passwordRequired,
|
|
passwordLength,
|
|
passwordWeak,
|
|
}
|