hi-client/lib/app/modules/kr_login/views/kr_login_view.dart

415 lines
14 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 '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.w),
// 👇 核心改动:使用新的验证码输入框
_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.w),
_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.w, // 固定高度
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.w, // 固定高度
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.w,
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();
}
}
}