Files

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,
}