feat: 完成代码
Some checks failed
Build Android APK / 编译 libcore.aar (push) Has been cancelled
Build Android APK / 编译 Android APK (release) (push) Has been cancelled
Build Android APK / 创建 GitHub Release (push) Has been cancelled
Build Multi-Platform / 编译 libcore (iOS/tvOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Android) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Windows) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (macOS) (push) Has been cancelled
Build Multi-Platform / 编译 libcore (Linux) (push) Has been cancelled
Build Multi-Platform / 构建 Android APK (push) Has been cancelled
Build Multi-Platform / 构建 Windows (push) Has been cancelled
Build Multi-Platform / 构建 macOS (push) Has been cancelled
Build Multi-Platform / 构建 Linux (push) Has been cancelled
Build Multi-Platform / 构建 iOS (push) Has been cancelled
Build Multi-Platform / 创建 Release (push) Has been cancelled
Build Windows / 编译 libcore (Windows) (push) Has been cancelled
Build Windows / build (push) Has been cancelled

This commit is contained in:
speakeloudest 2025-10-31 04:00:26 -07:00
parent 74df08144f
commit 445b1e0352
11 changed files with 502 additions and 334 deletions

View File

@ -265,7 +265,7 @@ class KRAppRunData {
//
await KRDeviceInfoService().initialize();
KRLogUtil.kr_i('🔐 开始执行设备登录', tag: 'SplashController');
KRLogUtil.kr_i('🔐 开始执行设备登录', tag: 'AppRunData');
//
final authApi = KRAuthApi();

View File

@ -1,4 +1,5 @@
import 'package:kaer_with_panels/app/model/response/kr_is_register.dart';
import 'package:kaer_with_panels/app/model/response/kr_check_subscription.dart';
import 'package:kaer_with_panels/app/model/response/kr_login_data.dart';
import 'package:kaer_with_panels/app/model/response/kr_node_list.dart';
import 'package:kaer_with_panels/app/model/response/kr_package_list.dart';
@ -23,6 +24,8 @@ abstract class EntityFromJsonUtil {
switch (T.toString()) {
case "KRIsRegister":
return KRIsRegister.fromJson(json) as T;
case "KRCheckSubscription":
return KRCheckSubscription.fromJson(json) as T;
case "KRLoginData":
return KRLoginData.fromJson(json) as T;
case "KRPackageList":

View File

@ -0,0 +1,30 @@
///
class KRCheckSubscription {
///
final bool deviceSubscribed;
///
final bool emailSubscribed;
/// false
KRCheckSubscription({
this.deviceSubscribed = false,
this.emailSubscribed = false,
});
/// JSON
KRCheckSubscription.fromJson(Map<String, dynamic>? json)
: deviceSubscribed = (json?['device_status'] == true || json?['deviceStatus'] == "true") ? true : false,
emailSubscribed = (json?['email_status'] == true || json?['emailStatus'] == "true") ? true : false;
/// JSON
Map<String, dynamic> toJson() {
return {
'deviceStatus': deviceSubscribed,
'emailStatus': emailSubscribed,
};
}
///
bool get isFullySubscribed => deviceSubscribed && emailSubscribed;
}

View File

@ -267,7 +267,11 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
),
),
// 👇 3: Expanded
Padding(
Obx(() {
if((KRAppRunData.getInstance().kr_account.value != null &&
KRAppRunData.getInstance().kr_account.value!.startsWith('9000')))
return SizedBox.shrink();
return Padding(
padding: EdgeInsets.symmetric(horizontal: 40.w),
child: Column(
children: [
@ -318,10 +322,6 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
),
),
SizedBox(height: 10.w),
Obx(() {
return !(KRAppRunData.getInstance().kr_account.value != null &&
KRAppRunData.getInstance().kr_account.value!.startsWith('9000'))
?
GestureDetector(
onTap: () {
HIDialog.show(
@ -369,11 +369,10 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
),
),
)
: SizedBox.shrink();
})
],
),
),
);
}),
// HIHelpEntrance
SizedBox(height: 100.h),
],
@ -393,6 +392,17 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
final identifier = device['identifier'] ?? '';
final isCurrentDevice = device['is_current'] ?? false;
final id = device['id'] ?? '';
final userAgent = device['device_name'] ?? '未知设备';
final ip = device['ip'] ?? '';
final lastLoginRaw = device['last_login'];
final String lastLogin = lastLoginRaw?.toString() ?? '';
//
final deviceInfo = controller.getDeviceTypeInfo(userAgent);
final deviceType = deviceInfo['type'] as String;
final iconName = deviceInfo['icon'] as String;
return Stack( // 使 Stack
children: [
//
@ -408,14 +418,14 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
children: [
Row(
children: [
Icon(Icons.smartphone, color: Colors.white, size: 18.w),
Icon(_getIconData(iconName), color: Colors.white, size: 18.w),
SizedBox(width: 6.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
_extractDeviceModel(device['device_name']),
'设备:${_extractDeviceModel(userAgent)}',
style: TextStyle(
color: Colors.white,
fontSize: 10.sp, //
@ -423,7 +433,7 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
),
SizedBox(height: 4.h),
Text(
'ID$identifier',
'ID: ${identifier.substring(0, identifier.length > 4 ? 4 : identifier.length)}$id',
style: TextStyle(
color: Colors.white.withOpacity(0.9),
fontSize: 10.sp,
@ -576,18 +586,45 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
}
String _extractDeviceModel(String deviceName) {
// 2. 使
//
final RegExp regExp = RegExp(r'\((.*?)\)');
// 3.
final Match? match = regExp.firstMatch(deviceName);
// 4.
if (match != null && match.groupCount >= 1) {
// group(1)
return match.group(1) ?? deviceName;
//
final inside = match.group(1)!; // "Android; google Pixel 9; 15"
//
final parts = inside.split(';').map((s) => s.trim()).toList();
if (parts.length >= 2) {
//
return parts[1];
} else {
//
//
return inside;
}
} else {
//
return deviceName;
}
}
///
IconData _getIconData(String iconName) {
switch (iconName) {
case 'phone_android':
return Icons.phone_android;
case 'phone_iphone':
return Icons.phone_iphone;
case 'tablet':
return Icons.tablet_mac;
case 'desktop_mac':
return Icons.desktop_mac;
case 'computer':
return Icons.computer;
default:
return Icons.devices;
}
}
}

View File

@ -89,6 +89,7 @@ class KRDeleteAccountController extends GetxController {
// API code
final result = await _authApi.kr_deleteAccount(
KRAppRunData.getInstance().kr_account.value!,
kr_codeController.text,
);

View File

@ -169,7 +169,6 @@ class _KRHomeViewState extends State<KRHomeView> {
? Icon(
Icons.check,
size: 14.w,
fontWeight: FontWeight.w900,
color: Colors.black,
)
: null,

View File

@ -10,6 +10,7 @@ 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';
@ -366,18 +367,43 @@ class KRLoginController extends GetxController
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 {
inviteCode: inviteCodeController.text.isEmpty ? null : inviteCodeController.text,
);
either.fold(
(l) => KRCommonUtil.kr_showToast(l.msg),
(r) async {
_saveLoginData(r);
// KRCommonUtil.kr_showToast(AppTranslations.kr_login.registerSuccess);
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() {

View File

@ -61,6 +61,7 @@ class BaseResponse<T> {
}
if (retCode == 40004 || retCode == 40005 || retCode == 40002 || retCode == 40003) {
KRAppRunData().kr_loginOut();
return;
}
if (retCode != 200) {

View File

@ -2,6 +2,8 @@
abstract class Api {
///
static const String kr_isRegister = "/v1/app/auth/check";
///
static const String kr_checkSubscription = "/v1/public/user/subscribe_status";
///
// static const String kr_register = "/v1/auth/register";
@ -21,7 +23,7 @@ abstract class Api {
static const String kr_deviceLogin = "/v1/auth/login/device";
///
static const String kr_deleteAccount = "/v1/app/user/account";
static const String kr_deleteAccount = "/v1/public/user/delete_account";
/// -
static const String kr_setNewPsdByForgetPsd = "/v1/app/auth/reset_password";

View File

@ -8,6 +8,7 @@ import 'package:kaer_with_panels/app/mixins/kr_app_bar_opacity_mixin.dart';
import 'package:kaer_with_panels/app/services/api_service/api.dart';
import 'package:kaer_with_panels/app/model/enum/kr_request_type.dart';
import 'package:kaer_with_panels/app/model/response/kr_is_register.dart';
import 'package:kaer_with_panels/app/model/response/kr_check_subscription.dart';
import 'package:kaer_with_panels/app/model/response/kr_login_data.dart';
import 'package:kaer_with_panels/app/network/base_response.dart';
import 'package:kaer_with_panels/app/network/http_error.dart';
@ -43,6 +44,36 @@ class KRAuthApi {
return right(baseResponse.model.kr_isRegister);
}
/// true
Future<Either<HttpError, bool>> kr_checkSubscription(String email) async {
final Map<String, dynamic> data = <String, dynamic>{};
data['email'] = email;
// ID
final deviceId = KRDeviceInfoService().deviceId ?? 'unknown';
KRLogUtil.kr_i('设备ID: $deviceId', tag: 'KRAuthApi');
data["identifier"] = deviceId;
//
BaseResponse<KRCheckSubscription> baseResponse = await HttpUtil.getInstance()
.request<KRCheckSubscription>(
Api.kr_checkSubscription,
data,
method: HttpMethod.POST,
isShowLoading: true,
);
//
if (!baseResponse.isSuccess) {
return left(HttpError(msg: baseResponse.retMsg, code: baseResponse.retCode));
}
final subscription = baseResponse.model;
// true
return right(subscription.isFullySubscribed);
}
/// +
Future<Either<HttpError, String>> kr_register(
String email,
@ -139,8 +170,9 @@ class KRAuthApi {
}
///
Future<Either<HttpError, String>> kr_deleteAccount(String code) async {
Future<Either<HttpError, String>> kr_deleteAccount(String email, String code) async {
final Map<String, dynamic> data = <String, dynamic>{};
data['email'] = email;
data['code'] = code;
BaseResponse<dynamic> baseResponse = await HttpUtil.getInstance()

File diff suppressed because it is too large Load Diff