hi-client/lib/app/modules/kr_login/controllers/kr_login_controller.dart
speakeloudest 9123d5f0e4
Some checks failed
Build Windows / 编译 libcore (Windows) (20.15.1) (push) Successful in 20m33s
Build Windows / build (push) Has been cancelled
feat: 登录接口修改
2025-11-21 01:24:44 -08:00

715 lines
21 KiB
Dart
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/services/api_service/kr_auth_api.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/model/enum/kr_request_type.dart';
import 'package:kaer_with_panels/app/model/kr_area_code.dart';
import 'package:kaer_with_panels/app/utils/kr_common_util.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/utils/kr_event_bus.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import 'package:kaer_with_panels/app/widgets/dialogs/hi_dialog.dart';
import '../../../localization/kr_language_utils.dart';
import 'package:kaer_with_panels/app/services/kr_subscribe_service.dart';
import 'package:kaer_with_panels/app/modules/hi_user_info/controllers/hi_user_info_controller.dart';
/// 登录类型
enum KRLoginProgressStatus {
/// 检查是否注册
kr_check,
/// 验证码登陆
kr_loginByCode,
/// 密码登陆
kr_loginByPsd,
/// 注册发送验证码
kr_registerSendCode,
/// 这次设置密码
kr_registerSetPsd,
/// 忘记密码发送验证码
kr_forgetPsdSendCode,
/// 忘记密码设置密码
kr_forgetPsdSetPsd,
}
extension KRLoginTypeExt on KRLoginProgressStatus {
int get value {
switch (this) {
case KRLoginProgressStatus.kr_check:
return 0;
case KRLoginProgressStatus.kr_loginByCode:
return 2;
case KRLoginProgressStatus.kr_loginByPsd:
return 3;
case KRLoginProgressStatus.kr_registerSendCode:
return 4;
case KRLoginProgressStatus.kr_registerSetPsd:
return 5;
case KRLoginProgressStatus.kr_forgetPsdSendCode:
return 6;
case KRLoginProgressStatus.kr_forgetPsdSetPsd:
return 7;
}
}
}
class KRLoginController extends GetxController
with GetSingleTickerProviderStateMixin {
/// 订阅服务
final KRSubscribeService kr_subscribeService = KRSubscribeService();
/// 是否注册
RxBool kr_isRegistered = false.obs;
/// 登陆类型
var kr_loginType = KRLoginType.kr_email.obs;
/// 登陆进度状态
var kr_loginStatus = KRLoginProgressStatus.kr_registerSendCode.obs;
/// 是否使用密码登录手机号模式下有效true=密码登录false=验证码登录)
var kr_isPasswordLogin = true.obs;
/// 验证码倒计时
var _countdown = 60; // 倒计时初始值
late Timer _timer;
var kr_countdownText = AppTranslations.kr_login.sendCode.obs;
/// 是否允许发送验证码
RxBool kr_canSendCode = true.obs;
/// 国家编码列表
late List<KRAreaCodeItem> kr_areaCodeList = KRAreaCode.kr_getCodeList();
var kr_cutSeleteCodeIndex = 0.obs;
/// 是否加密密码
var kr_obscureText = true.obs;
/// 匹配邮箱列表
RxList kr_emailList = [].obs;
RxBool kr_isDropdownVisible = false.obs;
/// 定位
final LayerLink kr_layerLink = LayerLink();
OverlayEntry? overlayEntry; // 悬浮框
bool isDropdownVisible = false; // 控制悬浮框显示状态
/// 动画
late AnimationController animationController;
late Animation<double> animation;
var height = 100.0.obs;
/// 账号编辑控制器
late TextEditingController accountController = TextEditingController();
/// 验证码编辑控制器
late TextEditingController codeController = TextEditingController();
/// 密码编辑控制器
late TextEditingController psdController = TextEditingController();
/// 密码编辑控制器
late TextEditingController agPsdController = TextEditingController();
var kr_accountHasText = false.obs;
var kr_codeHasText = false.obs;
var kr_psdHasText = false.obs;
var kr_agPsdHasText = false.obs;
// 添加邀请码相关控制
final TextEditingController inviteCodeController = TextEditingController();
final RxBool kr_inviteCodeHasText = false.obs;
// 添加 FocusNode
late FocusNode kr_accountFocusNode;
late FocusNode kr_passwordFocusNode;
late FocusNode kr_confirmPasswordFocusNode;
late FocusNode kr_codeFocusNode;
late FocusNode kr_inviteCodeFocusNode;
// 添加获取按钮文本的方法
String kr_getNextBtnText() {
switch (kr_loginStatus.value) {
case KRLoginProgressStatus.kr_check:
return AppTranslations.kr_login.passwordLogin; // 显示"登录"
case KRLoginProgressStatus.kr_loginByCode:
return AppTranslations.kr_login.passwordLogin; // 已废弃,保留以防兼容性问题
case KRLoginProgressStatus.kr_loginByPsd:
return AppTranslations.kr_login.passwordLogin;
case KRLoginProgressStatus.kr_registerSendCode:
return AppTranslations.kr_login.next;
case KRLoginProgressStatus.kr_registerSetPsd:
return AppTranslations.kr_login.passwordLogin;
case KRLoginProgressStatus.kr_forgetPsdSendCode:
return AppTranslations.kr_login.next;
case KRLoginProgressStatus.kr_forgetPsdSetPsd:
return AppTranslations.kr_login.setAndLogin;
}
}
@override
void onInit() {
super.onInit();
// 1. 检查并获取路由参数
if (Get.arguments != null && Get.arguments is Map<String, dynamic>) {
final String? entry = Get.arguments['entry'];
print('entry: $entry');
// 2. 根据 entry 的值设置初始的 kr_loginStatus
if (entry == 'forget_psd') {
// 如果是从“忘记密码”进入,直接设置为“忘记密码-发送验证码”状态
kr_loginStatus.value = KRLoginProgressStatus.kr_forgetPsdSendCode;
} else if (entry == 'bind_email') {
// 如果是从“绑定邮箱”进入,直接设置为“注册-发送验证码”状态
kr_loginStatus.value = KRLoginProgressStatus.kr_registerSetPsd;
}else if (entry == 'login') {
// 登录
kr_loginStatus.value = KRLoginProgressStatus.kr_loginByPsd;
}
// 如果没有匹配的 entry 值,则保持默认的 kr_loginByPsd 状态
}
// 初始化计时器
_timer = Timer(Duration.zero, () {});
animationController = AnimationController(
duration: Duration(milliseconds: 500),
vsync: this,
);
animation = Tween<double>(begin: 300.0, end: 300.0).animate(
CurvedAnimation(parent: animationController, curve: Curves.easeInOut),
)..addListener(() {
height.value = animation.value;
});
// 初始化 FocusNode
kr_accountFocusNode = FocusNode();
kr_passwordFocusNode = FocusNode();
kr_confirmPasswordFocusNode = FocusNode();
kr_codeFocusNode = FocusNode();
kr_inviteCodeFocusNode = FocusNode();
// 监听 kr_loginStatus 的变化
ever(kr_loginStatus, (status) {
switch (status) {
case KRLoginProgressStatus.kr_check:
kr_isDropdownVisible.value = true;
accountController.clear();
codeController.clear();
psdController.clear();
agPsdController.clear();
inviteCodeController.clear();
break;
case KRLoginProgressStatus.kr_loginByCode:
kr_isDropdownVisible.value = false;
break;
case KRLoginProgressStatus.kr_loginByPsd:
kr_isDropdownVisible.value = false;
break;
case KRLoginProgressStatus.kr_registerSendCode:
kr_isDropdownVisible.value = false;
break;
case KRLoginProgressStatus.kr_registerSetPsd:
kr_isDropdownVisible.value = false;
break;
case KRLoginProgressStatus.kr_forgetPsdSendCode:
kr_isDropdownVisible.value = false;
break;
case KRLoginProgressStatus.kr_forgetPsdSetPsd:
kr_isDropdownVisible.value = false;
break;
}
});
// accountController 监听器(仅支持邮箱)
accountController.addListener(() {
String input = accountController.text.trim();
// 延迟执行状态更新
Future.microtask(() {
// 始终保持邮箱类型
kr_loginType.value = KRLoginType.kr_email;
// 更新邮箱建议列表
kr_emailList.value = kr_generateAndSortEmailList(input);
kr_accountHasText.value = input.isNotEmpty;
});
});
/// 验证码
codeController.addListener(() {
kr_codeHasText.value = !codeController.text.isEmpty;
});
/// 密码
psdController.addListener(() {
kr_psdHasText.value = !psdController.text.isEmpty;
});
/// 密码
agPsdController.addListener(() {
kr_agPsdHasText.value = !agPsdController.text.isEmpty;
});
// 添加邀请码输入监听
inviteCodeController.addListener(() {
kr_inviteCodeHasText.value = inviteCodeController.text.isNotEmpty;
});
// 语言变化时更新所有翻译文本
/*ever(KRLanguageUtils.kr_language, (_) {
if (kr_canSendCode.value) {
kr_countdownText.value = "";
kr_countdownText.value = AppTranslations.kr_login.sendCode;
}
});*/
kr_initFocus();
}
// 判断是否是手机号
bool _isNumeric(String input) {
final numericRegex = RegExp(r'^\d+$'); // 匹配纯数字
return numericRegex.hasMatch(input);
}
/// 直接登录(不再检查是否注册)
void kr_check() async {
if (accountController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterAccount);
return;
}
if (psdController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterPassword);
return;
}
// 直接调用登录
kr_login();
}
/// 发送验证码(仅支持邮箱)
void kr_sendCode() async {
if (accountController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterAccount);
return;
}
int type;
final check = await KRAuthApi().kr_isRegister(accountController.text);
final result = check.fold((l) {
KRCommonUtil.kr_showToast(l.msg);
return null;
}, (isRegistered) {
print('isRegistered $isRegistered');
return isRegistered ? 2 : 1;
});
if (result == null) return;
type = result;
final either = await KRAuthApi().kr_sendCode(accountController.text, type);
either.fold((l) {
KRCommonUtil.kr_showToast(l.msg);
}, (r) async {
_startCountdown();
});
}
/// 开始登录(仅支持邮箱+密码)
void kr_login() async {
if (psdController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterPassword);
return;
}
final either = await KRAuthApi().kr_login(
accountController.text,
psdController.text);
either.fold((l) {
KRCommonUtil.kr_showToast(l.msg);
}, (r) async {
_saveLoginData(r);
});
}
/// 开始注册(仅支持邮箱,验证码和邀请码可选)
void kr_register() async {
// 验证邮箱
if (accountController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterAccount);
return;
}
// if (psdController.text.isEmpty) {
// KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterPassword);
// return;
// }
// if (agPsdController.text.isEmpty) {
// KRCommonUtil.kr_showToast(AppTranslations.kr_login.reenterPassword);
// return;
// }
// if (psdController.text != agPsdController.text) {
// KRCommonUtil.kr_showToast(AppTranslations.kr_login.passwordMismatch);
// return;
// }
// 检查是否需要验证码(基于站点配置)
// final siteConfig = KRSiteConfigService();
// final needVerification = siteConfig.isEmailVerificationEnabled() ||
// siteConfig.isRegisterVerificationEnabled();
if (codeController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterCode);
return;
}
// 定义注册请求逻辑
Future<void> performRegister() async {
final either = await KRAuthApi().kr_register(
accountController.text,
psdController.text,
code: codeController.text.isEmpty ? null : codeController.text,
inviteCode: inviteCodeController.text.isEmpty ? null : inviteCodeController.text,
);
either.fold(
(l) => KRCommonUtil.kr_showToast(l.msg),
(r) async {
_saveLoginData(r);
KRCommonUtil.kr_showToast('登录成功');
},
);
}
// 检查是否已有订阅
final subscriptionResult = await KRAuthApi().kr_checkSubscription(accountController.text);
subscriptionResult.fold(
(error) {
KRCommonUtil.kr_showToast(error.msg);
},
(isFullySubscribed) async {
if (isFullySubscribed) {
HIDialog.show(
message: '当前邮箱已有套餐,继续绑定会丢失设备当前套餐,是否继续?',
confirmText: '继续',
cancelText: '取消',
onConfirm: performRegister,
);
} else {
await performRegister();
}
},
);
}
void kr_checkCode() {
if (codeController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterCode);
return;
}
switch (kr_loginStatus.value) {
case KRLoginProgressStatus.kr_check:
break;
case KRLoginProgressStatus.kr_loginByCode:
break;
case KRLoginProgressStatus.kr_loginByPsd:
break;
case KRLoginProgressStatus.kr_registerSendCode:
kr_checkVerificationCode(KRLoginProgressStatus.kr_registerSendCode);
break;
case KRLoginProgressStatus.kr_registerSetPsd:
break;
case KRLoginProgressStatus.kr_forgetPsdSendCode:
kr_checkVerificationCode(KRLoginProgressStatus.kr_forgetPsdSendCode);
break;
case KRLoginProgressStatus.kr_forgetPsdSetPsd:
break;
}
}
/// 验证验证码(仅支持邮箱)
void kr_checkVerificationCode(KRLoginProgressStatus status) async {
final either = await KRAuthApi().kr_checkVerificationCode(
accountController.text,
codeController.text,
kr_loginStatus.value == KRLoginProgressStatus.kr_registerSendCode
? 2 // 注册验证码类型为2
: 3); // 重置密码验证码类型为3
either.fold((l) {
KRCommonUtil.kr_showToast(l.msg);
}, (r) async {
if (status == KRLoginProgressStatus.kr_registerSendCode) {
kr_loginStatus.value = KRLoginProgressStatus.kr_registerSetPsd;
} else if (status == KRLoginProgressStatus.kr_forgetPsdSendCode) {
kr_loginStatus.value = KRLoginProgressStatus.kr_forgetPsdSetPsd;
}
});
}
/// 忘记密码-设置新密码(仅支持邮箱)
void kr_setNewPsdByForgetPsd() async {
if (psdController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.enterPassword);
return;
}
if (agPsdController.text.isEmpty) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.reenterPassword);
return;
}
if (psdController.text != agPsdController.text) {
KRCommonUtil.kr_showToast(AppTranslations.kr_login.passwordMismatch);
return;
}
final either = await KRAuthApi().kr_setNewPsdByForgetPsd(
accountController.text,
codeController.text,
psdController.text);
either.fold((l) {
KRCommonUtil.kr_showToast(l.msg);
}, (r) async {
codeController.clear();
psdController.clear();
kr_loginStatus.value = KRLoginProgressStatus.kr_forgetPsdSetPsd;
_saveLoginData(r);
});
}
/// 开始倒计时
void _startCountdown() {
kr_canSendCode.value = false;
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
if (_countdown > 0) {
_countdown -= 1;
kr_countdownText.value = "${_countdown}s";
} else {
kr_canSendCode.value = true;
kr_countdownText.value = AppTranslations.kr_login.sendCode;
_countdown = 60;
timer.cancel();
_onCountdownFinished();
}
});
}
/// 设置登录数据(仅支持邮箱)
void _saveLoginData(String token) {
KRAppRunData.getInstance().kr_saveUserInfo(
token,
accountController.text,
KRLoginType.kr_email,
null);
kr_loginStatus.value = KRLoginProgressStatus.kr_check;
// 登录/注册成功后,发送消息触发订阅服务刷新
// 延迟一小段时间确保登录状态已经完全保存
Future.delayed(Duration(milliseconds: 100), () {
KREventBus().kr_sendMessage(KRMessageType.kr_payment);
});
final controller = Get.find<HIUserInfoController>();
controller.loadDeviceList();
// 登录成功后返回到上一页
Get.back();
}
/// 根据输入内容匹配邮箱
List<String> kr_generateAndSortEmailList(String input) {
// 常用邮箱域名
List<String> _commonEmailDomains = [
"@gmail.com",
"@yahoo.com",
"@outlook.com",
"@hotmail.com",
"@icloud.com",
"@aol.com",
"@zoho.com",
"@protonmail.com",
"@qq.com",
"@163.com",
"@126.com",
"@sina.com",
"@sohu.com",
"@foxmail.com",
"@aliyun.com",
"@189.cn",
"@china.com",
];
// 判断是否是邮箱格式
bool isEmail(String input) {
final emailRegex =
RegExp(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$");
return emailRegex.hasMatch(input);
}
// 输入过短或者是邮箱格式,直接返回空数组
if (input.length < 2 || isEmail(input)) {
return [];
}
// 处理输入,确保只保留一个 '@' 后的内容
String sanitizedInput =
input.contains("@") ? input.substring(0, input.indexOf("@")) : input;
// 根据匹配度排序
List<String> emailList = _commonEmailDomains.map((domain) {
return "$sanitizedInput$domain";
}).toList();
// 根据用户输入的 @ 后部分对域名进行匹配和排序
String? userDomain = input.contains("@") ? input.split("@").last : null;
if (userDomain != null && userDomain.isNotEmpty) {
emailList.sort((a, b) {
String domainA = a.split("@")[1];
String domainB = b.split("@")[1];
int matchScoreA = domainA.startsWith(userDomain) ? 1 : 0;
int matchScoreB = domainB.startsWith(userDomain) ? 1 : 0;
// 先比较匹配度,再按照字母顺序排序
if (matchScoreA == matchScoreB) {
return domainA.compareTo(domainB);
}
return matchScoreB.compareTo(matchScoreA);
});
}
return emailList;
}
/// 返回
void kr_back() {
kr_removeOverlay();
switch (kr_loginStatus.value) {
case KRLoginProgressStatus.kr_check:
break;
case KRLoginProgressStatus.kr_loginByCode:
kr_loginStatus.value = KRLoginProgressStatus.kr_check;
_resetTimer();
break;
case KRLoginProgressStatus.kr_loginByPsd:
kr_loginStatus.value = KRLoginProgressStatus.kr_check;
break;
case KRLoginProgressStatus.kr_registerSendCode:
kr_loginStatus.value = KRLoginProgressStatus.kr_check;
_resetTimer();
break;
case KRLoginProgressStatus.kr_registerSetPsd:
kr_loginStatus.value = KRLoginProgressStatus.kr_registerSendCode;
psdController.clear();
agPsdController.clear();
break;
case KRLoginProgressStatus.kr_forgetPsdSendCode:
kr_loginStatus.value = KRLoginProgressStatus.kr_loginByPsd;
_resetTimer();
codeController.clear();
psdController.clear();
agPsdController.clear();
break;
case KRLoginProgressStatus.kr_forgetPsdSetPsd:
kr_loginStatus.value = KRLoginProgressStatus.kr_forgetPsdSendCode;
psdController.clear();
agPsdController.clear();
break;
}
}
/// 重置计时器
void _resetTimer() {
if (_timer.isActive) {
_timer.cancel();
}
_countdown = 60;
kr_canSendCode.value = true;
kr_countdownText.value = AppTranslations.kr_login.sendCode;
}
void _onCountdownFinished() {}
void toggleHeight() {
// if (animationController.status == AnimationStatus.completed) {
// animationController.reverse();
// } else {
// animationController.forward();
// }
}
@override
void onReady() {
super.onReady();
// 每次打开登录页面时,重置为登录状态(而不是注册状态)
// 这样确保点击"登录/注册"按钮时始终显示登录页面
kr_loginStatus.value = KRLoginProgressStatus.kr_check;
}
@override
void onClose() {
kr_removeOverlay();
if (_timer.isActive) {
_timer.cancel();
}
animationController.dispose();
inviteCodeController.dispose();
kr_accountFocusNode.dispose();
kr_passwordFocusNode.dispose();
kr_confirmPasswordFocusNode.dispose();
kr_codeFocusNode.dispose();
kr_inviteCodeFocusNode.dispose();
super.onClose();
}
// 添加点击输入框的方法
void kr_onInputTap() {
kr_accountFocusNode.requestFocus();
}
// 添加焦点管理
void kr_initFocus() {
kr_accountFocusNode.addListener(() {
if (kr_accountFocusNode.hasFocus) {
// 获得焦点时的处理
_updateInputState();
}
});
}
void _updateInputState() {
String input = accountController.text.trim();
// 始终保持邮箱类型
kr_loginType.value = KRLoginType.kr_email;
kr_emailList.value = kr_generateAndSortEmailList(input);
}
// 添加移除悬浮框的方法
void kr_removeOverlay() {
overlayEntry?.remove();
overlayEntry = null;
}
}