Files
hi-client/lib/app/modules/kr_login/views/kr_login_view.dart
T
2025-12-08 23:12:51 -08:00

415 lines
14 KiB
Dart
Executable File

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
import '../controllers/kr_login_controller.dart';
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
import 'package:kaer_with_panels/app/localization/app_translations.dart';
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
import 'package:kaer_with_panels/app/widgets/hi_base_scaffold.dart';
import 'package:kaer_with_panels/app/widgets/hi_help_entrance.dart';
import 'package:kaer_with_panels/app/common/app_run_data.dart';
import 'package:kaer_with_panels/app/modules/kr_home/controllers/kr_home_controller.dart';
import 'package:kaer_with_panels/app/services/kr_site_config_service.dart';
import 'package:flutter/foundation.dart';
import 'package:kaer_with_panels/app/widgets/kr_subscription_expiry_text.dart';
import 'package:flutter/services.dart';
class KRLoginView extends GetView<KRLoginController> {
const KRLoginView({super.key});
@override
Widget build(BuildContext context) {
final isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0;
final isHideBack =
(Get.arguments as Map<String, dynamic>?)?['is-back'] ?? false;
return HIBaseScaffold(
showBack: !isHideBack,
resizeToAvoidBottomInset: true,
child: Stack(
children: [
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
FocusScope.of(context).unfocus();
},
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.symmetric(
horizontal: 40.w,
),
child: Column(
children: [
// Text(
// '${controller.kr_loginStatus.value}',
// style: TextStyle(color: Colors.white), // 使用 TextStyle()
// ),
SizedBox(height: 20.w),
_buildUserInfoSection(),
SizedBox(height: 12.w),
_buildBindEmailLayout(),
SizedBox(height: 100.w), // 为底部帮助按钮留出空间
],
),
),
),
),
if (!isKeyboardVisible) const HIHelpEntrance(),
],
),
);
}
Widget _buildUserInfoSection() {
return Row(
children: [
Container(
width: 60.w,
height: 60.w,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(18.r),
),
alignment: Alignment.center,
child: KrLocalImage(
imageName: 'hi-home-logo',
imageType: ImageType.svg,
width: 30.w,
height: 30.w,
color: Colors.black,
),
),
SizedBox(width: 12.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Obx(() {
final account = KRAppRunData.getInstance().kr_account.value;
final isDeviceLogin =
account != null && account.startsWith('9000');
final accountText = (account ==null || isDeviceLogin)
? '待绑定'
: '${KRAppRunData.getInstance().kr_account.value.toString()}';
return Text(
accountText,
style: TextStyle(
color: Colors.white.withOpacity(0.85),
fontSize: 14.sp,
fontWeight: FontWeight.w500,
),
);
}),
KRSubscriptionExpiryText(
expireTimeProvider: () => controller
.kr_subscribeService.kr_currentSubscribe.value?.expireTime,
style: TextStyle(
color: Colors.white,
fontSize: 12.sp,
),
),
],
),
),
],
);
}
Widget _buildContentByEntry() {
final entry = (Get.arguments as Map<String, dynamic>?)?['entry'];
if (entry == 'forget_psd') {
return _buildForgetPasswordLayout();
} else if (entry == 'bind_email') {
return _buildBindEmailLayout();
} else if (entry == 'login') {
return _buildLoginEmailLayout();
}
return _buildForgetPasswordLayout(); // 默认显示修改密码
}
Widget _buildForgetPasswordLayout() {
return Column(
children: [
Container(
constraints: BoxConstraints(minHeight: 300.w),
child: Column(
children: [
_buildStandardInputField(
controller: controller.psdController,
hintText: '新密码',
isPassword: true,
),
SizedBox(height: 10.w),
_buildStandardInputField(
controller: controller.agPsdController,
hintText: '确认密码',
isPassword: true,
),
],
),
),
SizedBox(height: 30.h),
_buildSaveButton(),
],
);
}
Widget _buildBindEmailLayout() {
return Column(
children: [
Container(
constraints: BoxConstraints(minHeight: 300.w),
child: Column(
children: [
_buildStandardInputField(
controller: controller.accountController,
hintText: 'Email',
),
// SizedBox(height: 10.w),
// _buildStandardInputField(
// controller: controller.psdController,
// hintText: '新密码',
// isPassword: true,
// ),
// SizedBox(height: 10.w),
// _buildStandardInputField(
// controller: controller.agPsdController,
// hintText: '确认密码',
// isPassword: true,
// ),
SizedBox(height: 10),
// 👇 核心改动:使用新的验证码输入框
_buildVerificationCodeField(),
],
),
),
SizedBox(height: 30.h),
_buildSaveButton(),
],
);
}
Widget _buildLoginEmailLayout() {
return Column(
children: [
Container(
constraints: BoxConstraints(minHeight: 300.w),
child: Column(
children: [
_buildStandardInputField(
controller: controller.accountController,
hintText: 'Email',
),
SizedBox(height: 10),
_buildStandardInputField(
controller: controller.psdController,
hintText: '密码',
isPassword: true,
),
SizedBox(height: 10.w),
],
),
),
SizedBox(height: 30.h),
_buildSaveButton(),
],
);
}
/// 构建标准输入框
Widget _buildStandardInputField({
required TextEditingController controller,
required String hintText,
bool isPassword = false,
}) {
return SizedBox(
// height: 50, // 固定高度
child: TextField(
controller: controller,
obscureText: isPassword,
style: KrAppTextStyle(
fontSize: 16,
color: Colors.white,
),
decoration: InputDecoration(
hintText: hintText,
hintStyle: KrAppTextStyle(
fontSize: 16,
color: const Color(0xFFA6A6A6),
fontWeight: FontWeight.w600,
),
contentPadding:
EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w), // 调整为更圆的角
borderSide: BorderSide(color: Colors.white, width: 2),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w),
borderSide: BorderSide(color: Colors.white, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w),
borderSide: BorderSide(color: Colors.white, width: 2),
),
),
),
);
}
/// 构建注册页面的验证码输入框(包含间距)
Widget _buildVerificationCodeField() {
// 从站点配置服务获取验证配置(站点配置不是响应式的,不需要 Obx)
// final siteConfig = KRSiteConfigService();
// final needVerification = siteConfig.isEmailVerificationEnabled() ||
// siteConfig.isRegisterVerificationEnabled();
//
// // 如果不需要验证码,返回空容器
// if (!needVerification) {
// return SizedBox.shrink();
// }
return SizedBox(
height: 50, // 固定高度
child: TextField(
controller: controller.codeController,
keyboardType: TextInputType.number,
textInputAction: TextInputAction.done,
autofillHints: const [AutofillHints.oneTimeCode],
enableSuggestions: false,
autocorrect: false,
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
onChanged: (value) {
var v = value.replaceAll(RegExp("\\s+"), "");
if (v.length % 2 == 0 && v.isNotEmpty) {
final half = v.length ~/ 2;
final first = v.substring(0, half);
final second = v.substring(half);
if (first == second) {
v = first;
}
}
const maxLen = 6;
if (v.length > maxLen) {
v = v.substring(0, maxLen);
}
if (controller.codeController.text != v) {
controller.codeController.value =
controller.codeController.value.copyWith(
text: v,
selection: TextSelection.collapsed(offset: v.length),
composing: TextRange.empty,
);
}
if (v.isNotEmpty && (v.length >= 6)) {
FocusScope.of(Get.context!).unfocus();
}
},
onSubmitted: (_) {
FocusScope.of(Get.context!).unfocus();
},
style: KrAppTextStyle(
fontSize: 16,
color: Colors.white,
),
decoration: InputDecoration(
hintText: '验证码',
hintStyle: KrAppTextStyle(
fontSize: 16,
color: const Color(0xFFA6A6A6),
fontWeight: FontWeight.w600,
),
contentPadding:
EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w),
borderSide: BorderSide(color: Colors.white, width: 2),
),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w),
borderSide: BorderSide(color: Colors.white, width: 2),
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(25.w),
borderSide: BorderSide(color: Colors.white, width: 2),
),
isDense: true,
suffixIconConstraints: BoxConstraints(
maxHeight: 50.w, // 限制最大高度
),
suffixIcon: Padding(
padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w),
child: Obx(() {
return GestureDetector(
onTap: controller.kr_canSendCode.value
? () => controller.kr_sendCode()
: null,
child: Container(
width: 100.w,
alignment: Alignment.center,
decoration: BoxDecoration(
color: controller.kr_canSendCode.value
? Theme.of(Get.context!).primaryColor
: const Color(0xFFD5D5D5),
borderRadius: BorderRadius.circular(100.r), // 药丸状
),
child: Text(
controller.kr_countdownText.value,
style: KrAppTextStyle(
fontSize: 14,
fontWeight: FontWeight.w600,
color: controller.kr_canSendCode.value
? Colors.black
: const Color(0xFF464655),
),
),
),
);
}),
),
),
),
);
}
Widget _buildSaveButton() {
return GestureDetector(
onTap: () {
_handleSave();
},
child: Container(
width: double.infinity,
height: 50,
decoration: BoxDecoration(
color: Theme.of(Get.context!).primaryColor,
borderRadius: BorderRadius.circular(100.r),
),
child: Center(
child: Text(
controller.kr_getNextBtnText(),
style: KrAppTextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Colors.black,
),
),
),
),
);
}
void _handleSave() {
final entry = (Get.arguments as Map<String, dynamic>?)?['entry'];
if (entry == 'forget_psd') {
controller.kr_setNewPsdByForgetPsd();
} else if (entry == 'bind_email') {
controller.kr_register();
} else if (entry == 'login') {
controller.kr_check();
}
}
}