feat: 尚未购买的弹窗
This commit is contained in:
parent
adcde623c7
commit
55d7508807
@ -6,6 +6,7 @@ import 'package:get/get.dart';
|
||||
import 'package:kaer_with_panels/app/modules/hi_menu/controllers/hi_menu_controller.dart';
|
||||
import 'package:kaer_with_panels/app/routes/app_pages.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_subscription_expiry_text.dart';
|
||||
|
||||
/// 用户信息展示卡片 Widget
|
||||
///
|
||||
@ -67,51 +68,10 @@ class UserInfoCard extends StatelessWidget {
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
Obx(() {
|
||||
final currentSubscribe =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
String expiryText;
|
||||
|
||||
if (currentSubscribe == null) {
|
||||
expiryText = '尚未购买套餐';
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime =
|
||||
DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
expireDateTime = null;
|
||||
}
|
||||
|
||||
if (expireDateTime == null) {
|
||||
expiryText = '套餐信息无效';
|
||||
} else if (expireDateTime.isBefore(now)) {
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
expiryText = '已于 $formattedExpireDate 到期';
|
||||
} else {
|
||||
final year = expireDateTime.year;
|
||||
final month = expireDateTime.month.toString().padLeft(2, '0');
|
||||
final day = expireDateTime.day.toString().padLeft(2, '0');
|
||||
final hour = expireDateTime.hour.toString().padLeft(2, '0');
|
||||
final minute = expireDateTime.minute.toString().padLeft(2, '0');
|
||||
final second = expireDateTime.second.toString().padLeft(2, '0');
|
||||
|
||||
// 2. 拼接成最终的字符串
|
||||
final formattedDateTime = '$year/$month/$day $hour:$minute:$second';
|
||||
|
||||
expiryText = '到期时间:$formattedDateTime';
|
||||
}
|
||||
}
|
||||
return Text(
|
||||
expiryText,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
);
|
||||
}),
|
||||
KRSubscriptionExpiryText(
|
||||
expireTimeProvider: () => controller.kr_subscribeService
|
||||
.kr_currentSubscribe.value?.expireTime,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
@ -19,13 +19,14 @@ 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/widgets/dialogs/hi_dialog.dart';
|
||||
import 'package:kaer_with_panels/app/common/app_config.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_subscription_expiry_text.dart';
|
||||
|
||||
class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
const HIUserInfoView({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isDeviceLogin = KRAppRunData.getInstance().isDeviceLogin();
|
||||
final isDeviceLogin = KRAppRunData.getInstance().isDeviceLogin();
|
||||
return HIBaseScaffold(
|
||||
child: Stack(
|
||||
children: [
|
||||
@ -69,9 +70,14 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Obx(() {
|
||||
final account = KRAppRunData.getInstance().kr_account.value;
|
||||
final isDeviceLogin = account != null && account.startsWith('9000');
|
||||
final accountText = isDeviceLogin ? '待绑定' : 'ID: ${KRAppRunData.getInstance().kr_account.value.toString()}';
|
||||
final account = KRAppRunData.getInstance()
|
||||
.kr_account
|
||||
.value;
|
||||
final isDeviceLogin = account != null &&
|
||||
account.startsWith('9000');
|
||||
final accountText = isDeviceLogin
|
||||
? '待绑定'
|
||||
: 'ID: ${KRAppRunData.getInstance().kr_account.value.toString()}';
|
||||
return Text(
|
||||
accountText,
|
||||
style: TextStyle(
|
||||
@ -84,51 +90,13 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
final currentSubscribe =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
String expiryText;
|
||||
|
||||
if (currentSubscribe == null) {
|
||||
expiryText = '尚未购买套餐';
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime =
|
||||
DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
expireDateTime = null;
|
||||
}
|
||||
|
||||
if (expireDateTime == null) {
|
||||
expiryText = '套餐信息无效';
|
||||
} else if (expireDateTime.isBefore(now)) {
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
expiryText = '已于 $formattedExpireDate 到期';
|
||||
} else {
|
||||
final year = expireDateTime.year;
|
||||
final month = expireDateTime.month.toString().padLeft(2, '0');
|
||||
final day = expireDateTime.day.toString().padLeft(2, '0');
|
||||
final hour = expireDateTime.hour.toString().padLeft(2, '0');
|
||||
final minute = expireDateTime.minute.toString().padLeft(2, '0');
|
||||
final second = expireDateTime.second.toString().padLeft(2, '0');
|
||||
|
||||
// 2. 拼接成最终的字符串
|
||||
final formattedDateTime = '$year/$month/$day $hour:$minute:$second';
|
||||
|
||||
expiryText = '到期时间:$formattedDateTime';
|
||||
}
|
||||
}
|
||||
return Text(
|
||||
expiryText,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
);
|
||||
}),
|
||||
KRSubscriptionExpiryText(
|
||||
expireTimeProvider: () => controller
|
||||
.kr_subscribeService
|
||||
.kr_currentSubscribe
|
||||
.value
|
||||
?.expireTime,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -138,7 +106,8 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
SizedBox(height: 12.w),
|
||||
// 动态:如果已有账号,显示“修改密码”,否则显示“绑定邮箱”
|
||||
Obx(() {
|
||||
final isDeviceLogin = KRAppRunData.getInstance().isDeviceLogin();
|
||||
final isDeviceLogin =
|
||||
KRAppRunData.getInstance().isDeviceLogin();
|
||||
if (!isDeviceLogin) return SizedBox.shrink();
|
||||
return InkWell(
|
||||
onTap: () {
|
||||
@ -155,14 +124,18 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
margin: EdgeInsets.symmetric(horizontal: 0).copyWith(bottom: 10), // 在这里增加底部间距
|
||||
padding: EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
margin: EdgeInsets.symmetric(horizontal: 0)
|
||||
.copyWith(bottom: 10), // 在这里增加底部间距
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(22),
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
border:
|
||||
Border.all(color: Colors.white, width: 2),
|
||||
),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
isDeviceLogin ? '绑定邮箱' : '修改密码',
|
||||
@ -203,7 +176,8 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
// 2. 让 GridView 根据内容自动调整高度
|
||||
shrinkWrap: true,
|
||||
// 3. 设置网格的配置
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // 强制两列
|
||||
crossAxisSpacing: 10, // 水平间距
|
||||
mainAxisSpacing: 10, // 垂直间距
|
||||
@ -226,8 +200,10 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
child: Text(
|
||||
'请确认是否移除此设备?',
|
||||
style: KrAppTextStyle(
|
||||
color:
|
||||
Theme.of(context).textTheme.bodyMedium?.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@ -240,8 +216,7 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
},
|
||||
onCancel: () {
|
||||
controller.deleteDevice(id);
|
||||
}
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
} else {
|
||||
@ -261,9 +236,11 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
),
|
||||
// 👇 核心改动 3: 将固定在底部的按钮放在 Expanded 外部
|
||||
Obx(() {
|
||||
if((KRAppRunData.getInstance().kr_account.value != null &&
|
||||
KRAppRunData.getInstance().kr_account.value!.startsWith('9000')))
|
||||
return SizedBox.shrink();
|
||||
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(
|
||||
@ -278,7 +255,10 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
'注销账号后,所有此账号内的剩余套餐和账户数据将被清空,无法找回。', // 1. 修改为正确的提示信息
|
||||
textAlign: TextAlign.left, // 文本居中
|
||||
style: KrAppTextStyle(
|
||||
color: Theme.of(context).textTheme.bodyMedium?.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@ -292,8 +272,7 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
Get.toNamed(Routes.KR_DELETE_ACCOUNT);
|
||||
},
|
||||
// 4. onConfirm 对应“返回”按钮的点击事件
|
||||
onConfirm: () {
|
||||
},
|
||||
onConfirm: () {},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
@ -301,7 +280,8 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
padding: EdgeInsets.symmetric(vertical: 12.w),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(24.w),
|
||||
border: Border.all(color: const Color(0xFFFF2ED1), width: 2),
|
||||
border: Border.all(
|
||||
color: const Color(0xFFFF2ED1), width: 2),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
@ -324,7 +304,10 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
'确认要退出您的账号?', // 1. 修改为正确的提示信息
|
||||
textAlign: TextAlign.center, // 文本居中
|
||||
style: KrAppTextStyle(
|
||||
color: Theme.of(context).textTheme.bodyMedium?.color,
|
||||
color: Theme.of(context)
|
||||
.textTheme
|
||||
.bodyMedium
|
||||
?.color,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
@ -333,15 +316,14 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
cancelText: '确认',
|
||||
confirmText: '返回',
|
||||
onCancel: () async {
|
||||
final currentDevice = controller.devices.firstWhere(
|
||||
(device) => device['is_current'] == true,
|
||||
final currentDevice =
|
||||
controller.devices.firstWhere(
|
||||
(device) => device['is_current'] == true,
|
||||
);
|
||||
final deviceId = currentDevice['id'] as String;
|
||||
await controller.deleteDevice(deviceId);
|
||||
},
|
||||
onConfirm: () {
|
||||
|
||||
},
|
||||
onConfirm: () {},
|
||||
);
|
||||
},
|
||||
child: Container(
|
||||
@ -376,6 +358,7 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 构建“当前设备信息卡”的私有方法
|
||||
Widget _buildDeviceCard({
|
||||
required BuildContext context,
|
||||
@ -396,7 +379,8 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
final deviceType = deviceInfo['type'] as String;
|
||||
final iconName = deviceInfo['icon'] as String;
|
||||
|
||||
return Stack( // 使用 Stack 来放置删除按钮
|
||||
return Stack(
|
||||
// 使用 Stack 来放置删除按钮
|
||||
children: [
|
||||
// 主体内容容器
|
||||
Container(
|
||||
@ -486,31 +470,31 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
// 在这里处理点击“添加设备”的逻辑
|
||||
final device_limit = AppConfig.getInstance().device_limit;
|
||||
HIDialog.show(
|
||||
customMessageWidget: Padding(
|
||||
padding: EdgeInsets.only(top: 16.w, bottom: 16.w),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min, // 让 Column 高度包裹内容
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 2. 第一个 Text 组件
|
||||
Text(
|
||||
'请使用绑定邮箱登录新设备',
|
||||
style: KrAppTextStyle(
|
||||
color: Colors.black, // 可以使用稍浅
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
customMessageWidget: Padding(
|
||||
padding: EdgeInsets.only(top: 16.w, bottom: 16.w),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min, // 让 Column 高度包裹内容
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// 2. 第一个 Text 组件
|
||||
Text(
|
||||
'请使用绑定邮箱登录新设备',
|
||||
style: KrAppTextStyle(
|
||||
color: Colors.black, // 可以使用稍浅
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
SizedBox(height: 20.w),
|
||||
Text(
|
||||
"每个账号最多允许同时使用${device_limit}台设备同时在线",
|
||||
style: KrAppTextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
/*Obx(() {
|
||||
),
|
||||
SizedBox(height: 20.w),
|
||||
Text(
|
||||
"每个账号最多允许同时使用${device_limit}台设备同时在线",
|
||||
style: KrAppTextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
)
|
||||
/*Obx(() {
|
||||
// final current = controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
|
||||
// 如果 current 为 null,显示默认值 0
|
||||
@ -518,9 +502,9 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
|
||||
return
|
||||
}),*/
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
confirmText: KRAppRunData.getInstance().isDeviceLogin() ? '前往' : null,
|
||||
cancelText: '取消',
|
||||
onConfirm: () {
|
||||
@ -591,7 +575,7 @@ class HIUserInfoView extends GetView<HIUserInfoController> {
|
||||
final RegExp regExp = RegExp(r'\((.*?)\)');
|
||||
final Match? match = regExp.firstMatch(deviceName);
|
||||
|
||||
if (match != null && match.groupCount >= 1 ) {
|
||||
if (match != null && match.groupCount >= 1) {
|
||||
// 获取括号内内容
|
||||
final inside = match.group(1)!; // "Android; google Pixel 9; 15"
|
||||
|
||||
|
||||
@ -4,11 +4,11 @@ import 'package:get/get.dart';
|
||||
import 'package:kaer_with_panels/app/common/app_run_data.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/hi_base_scaffold.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_local_image.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_subscription_expiry_text.dart';
|
||||
import '../controllers/kr_delete_account_controller.dart';
|
||||
import 'package:kaer_with_panels/app/localization/app_translations.dart';
|
||||
import 'package:kaer_with_panels/app/widgets/kr_app_text_style.dart';
|
||||
|
||||
|
||||
class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
const KRDeleteAccountView({super.key});
|
||||
|
||||
@ -46,7 +46,8 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
padding: EdgeInsets.symmetric(vertical: 12.w),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(24.w),
|
||||
border: Border.all(color: const Color(0xFFFF2ED1), width: 2),
|
||||
border:
|
||||
Border.all(color: const Color(0xFFFF2ED1), width: 2),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
@ -87,7 +88,6 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _buildUserInfoSection() {
|
||||
return Row(
|
||||
children: [
|
||||
@ -129,12 +129,16 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
final _ = KRAppRunData.getInstance().kr_isLogin.value;
|
||||
final userId = (KRAppRunData.getInstance().kr_userId.value ?? '').toString();
|
||||
final deviceId = KRAppRunData.getInstance().deviceId ?? '';
|
||||
|
||||
final account = KRAppRunData.getInstance()
|
||||
.kr_account
|
||||
.value;
|
||||
final isDeviceLogin = account != null &&
|
||||
account.startsWith('9000');
|
||||
final accountText = isDeviceLogin
|
||||
? '待绑定'
|
||||
: 'ID: ${KRAppRunData.getInstance().kr_account.value.toString()}';
|
||||
return Text(
|
||||
'ID: ${userId.isNotEmpty ? userId : deviceId}',
|
||||
accountText,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.85),
|
||||
fontSize: 14.sp,
|
||||
@ -142,51 +146,14 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
),
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
final currentSubscribe =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
String expiryText;
|
||||
|
||||
if (currentSubscribe == null) {
|
||||
expiryText = '尚未购买套餐';
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime =
|
||||
DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
expireDateTime = null;
|
||||
}
|
||||
|
||||
if (expireDateTime == null) {
|
||||
expiryText = '套餐信息无效';
|
||||
} else if (expireDateTime.isBefore(now)) {
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
expiryText = '已于 $formattedExpireDate 到期';
|
||||
} else {
|
||||
expiryText = '到期时间:${expireDateTime}';final year = expireDateTime.year;
|
||||
final month = expireDateTime.month.toString().padLeft(2, '0');
|
||||
final day = expireDateTime.day.toString().padLeft(2, '0');
|
||||
final hour = expireDateTime.hour.toString().padLeft(2, '0');
|
||||
final minute = expireDateTime.minute.toString().padLeft(2, '0');
|
||||
final second = expireDateTime.second.toString().padLeft(2, '0');
|
||||
|
||||
// 2. 拼接成最终的字符串
|
||||
final formattedDateTime = '$year/$month/$day $hour:$minute:$second';
|
||||
|
||||
expiryText = '到期时间:$formattedDateTime';
|
||||
}
|
||||
}
|
||||
return Text(
|
||||
expiryText,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
);
|
||||
}),
|
||||
KRSubscriptionExpiryText(
|
||||
expireTimeProvider: () => controller
|
||||
.kr_subscribeService.kr_currentSubscribe.value?.expireTime,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -213,7 +180,8 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
color: const Color(0xFFA6A6A6),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(25.w),
|
||||
borderSide: BorderSide(color: Colors.white, width: 2),
|
||||
@ -233,14 +201,15 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
suffixIcon: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w),
|
||||
child: Obx(() {
|
||||
|
||||
return GestureDetector(
|
||||
onTap: controller.kr_canSendCode.value ? controller.kr_sendCode : null,
|
||||
onTap: controller.kr_canSendCode.value
|
||||
? controller.kr_sendCode
|
||||
: null,
|
||||
child: Container(
|
||||
width: 100.w,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: controller.kr_canSendCode.value
|
||||
color: controller.kr_canSendCode.value
|
||||
? Theme.of(Get.context!).primaryColor
|
||||
: const Color(0xFFD5D5D5),
|
||||
borderRadius: BorderRadius.circular(100.r), // 药丸状
|
||||
@ -254,7 +223,7 @@ class KRDeleteAccountView extends GetView<KRDeleteAccountController> {
|
||||
fontWeight: FontWeight.w600,
|
||||
color: controller.kr_canSendCode.value
|
||||
? Colors.black
|
||||
: const Color(0xFF464655) ,
|
||||
: const Color(0xFF464655),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@ -86,8 +86,17 @@ class HIAnimatedConnectButton extends GetView<KRHomeController> {
|
||||
print('🔵 Switch UI 正在更新,切换中点击了按钮: status=${status.runtimeType}, isConnected=$isConnected, isSwitching=$isSwitching');
|
||||
return;
|
||||
}
|
||||
final hasValidSubscription =
|
||||
controller.kr_subscribeService.kr_availableSubscribes.isNotEmpty;
|
||||
final current = controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
bool hasValidSubscription = false;
|
||||
if (current != null) {
|
||||
DateTime? expire;
|
||||
try {
|
||||
expire = DateTime.parse(current.expireTime);
|
||||
} catch (_) {
|
||||
expire = null;
|
||||
}
|
||||
hasValidSubscription = expire != null && expire.isAfter(DateTime.now());
|
||||
}
|
||||
if (hasValidSubscription) {
|
||||
controller.kr_toggleSwitch(!controller.kr_isConnected.value);
|
||||
} else {
|
||||
@ -291,4 +300,3 @@ class _ContinuousRippleEffectState extends State<ContinuousRippleEffect>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -18,7 +18,6 @@ import 'kr_home_subscription_view.dart';
|
||||
import './hi_animated_connect_button.dart';
|
||||
import 'package:kaer_with_panels/app/services/global_overlay_service.dart';
|
||||
|
||||
|
||||
class KRHomeView extends StatefulWidget {
|
||||
const KRHomeView({super.key});
|
||||
|
||||
@ -35,8 +34,6 @@ class _KRHomeViewState extends State<KRHomeView> {
|
||||
controller = Get.find<KRHomeController>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
@ -50,174 +47,186 @@ class _KRHomeViewState extends State<KRHomeView> {
|
||||
children: [
|
||||
HIBaseScaffold(
|
||||
showMenuButton: true,
|
||||
topContentAreaHeight: 80,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child:
|
||||
SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(40.w, 8.w, 0, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Hi快VPN-网在我在,网快我快',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
// 订阅信息
|
||||
Obx(() {
|
||||
// 1. 先获取订阅信息
|
||||
final currentSubscribe =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
|
||||
// 2. 准备一个 Widget 变量,用于存放最终要显示的内容
|
||||
Widget content;
|
||||
|
||||
// --- 定义统一的文本样式,并设置行高 ---
|
||||
final textStyle = TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.2, // 您可以微调这个值来达到想要的视觉效果
|
||||
);
|
||||
|
||||
// 3. 开始条件判断
|
||||
if (currentSubscribe == null) {
|
||||
// --- 情况1: 没有任何订阅信息 ---
|
||||
content = Text(
|
||||
'尚未购买套餐',
|
||||
style: textStyle,
|
||||
);
|
||||
} else {
|
||||
// --- 情况2: 有订阅信息,需要判断是否过期 ---
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime = DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
// 日期格式解析失败
|
||||
}
|
||||
|
||||
if (expireDateTime != null && expireDateTime.isBefore(now)) {
|
||||
// --- 情况2.1: 订阅已过期 ---
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
// 使用换行符 \n 合并为单个 Text 组件
|
||||
content = Text(
|
||||
'您的套餐已于 $formattedExpireDate 到期\n请前往购买新套餐',
|
||||
style: textStyle,
|
||||
);
|
||||
} else {
|
||||
// --- 情况2.2: 订阅有效 ---
|
||||
final difference = expireDateTime?.difference(now);
|
||||
final remainingDaysText = (difference?.inDays ?? 0) > 0
|
||||
? '${difference!.inDays} 天'
|
||||
: '不足一天';
|
||||
// 使用换行符 \n 合并为单个 Text 组件
|
||||
content = Text(
|
||||
'套餐剩余:$remainingDaysText\n${controller.kr_isConnected.value ? '当前线路:${controller.kr_getRealConnectedNodeCountry()}' : '未连接'}',
|
||||
style: textStyle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 返回包裹在公共 Container 中的最终内容
|
||||
return Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: EdgeInsets.only(top: 8.h),
|
||||
child: content,
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 8.h), // 添加一些垂直间距
|
||||
|
||||
// --- 自定义“闪连”Checkbox ---
|
||||
Obx(() {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min, // 让 Row 的宽度包裹其内容
|
||||
children: [
|
||||
// --- 可点击的 Checkbox 区域 ---
|
||||
GestureDetector(
|
||||
// 点击方框和文字都可以切换状态
|
||||
onTap: () => controller.toggleQuickConnect(!controller.isQuickConnectEnabled.value),
|
||||
child: AbsorbPointer(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 1. 自定义 Checkbox 的方框外观
|
||||
Container(
|
||||
width: 20.w,
|
||||
height: 20.w,
|
||||
decoration: BoxDecoration(
|
||||
color: controller.isQuickConnectEnabled.value
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.transparent,
|
||||
border: Border.all(
|
||||
color: Theme.of(context).primaryColor,
|
||||
width: 1.5,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(4.r),
|
||||
),
|
||||
child: controller.isQuickConnectEnabled.value
|
||||
? Icon(
|
||||
Icons.check,
|
||||
size: 14.w,
|
||||
color: Colors.black,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
// 2. “闪连”标签
|
||||
Text(
|
||||
'闪连',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
topContentAreaHeight: 80,
|
||||
child: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: SafeArea(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.fromLTRB(40.w, 8.w, 0, 0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
'Hi快VPN-网在我在,网快我快',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
// --- 问号图标和点击弹窗区域 ---
|
||||
SizedBox(width: 6.w), // 文字和问号图标之间的间距
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
HIDialog.show(
|
||||
title: '*闪连功能',
|
||||
message: '开启后,每次打开软件默认自动连接,无需点击连接按钮\n在后台关闭软件后,软件将自动断开',
|
||||
),
|
||||
// 订阅信息
|
||||
Obx(() {
|
||||
// 1. 先获取订阅信息
|
||||
final currentSubscribe = controller
|
||||
.kr_subscribeService.kr_currentSubscribe.value;
|
||||
|
||||
// 2. 准备一个 Widget 变量,用于存放最终要显示的内容
|
||||
Widget content;
|
||||
|
||||
// --- 定义统一的文本样式,并设置行高 ---
|
||||
final normalStyle = TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
height: 1.2,
|
||||
);
|
||||
final highlightStyle = normalStyle.copyWith(
|
||||
color: const Color(0xFFFF00B7),
|
||||
);
|
||||
|
||||
// 3. 开始条件判断
|
||||
if (currentSubscribe == null) {
|
||||
// --- 情况1: 没有任何订阅信息 ---
|
||||
content = Text(
|
||||
'尚未购买套餐',
|
||||
style: highlightStyle,
|
||||
);
|
||||
} else {
|
||||
// --- 情况2: 有订阅信息,需要判断是否过期 ---
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime =
|
||||
DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
// 日期格式解析失败
|
||||
}
|
||||
|
||||
if (expireDateTime != null &&
|
||||
expireDateTime.isBefore(now)) {
|
||||
// --- 情况2.1: 订阅已过期 ---
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
// 使用换行符 \n 合并为单个 Text 组件
|
||||
content = Text(
|
||||
'您的套餐已于 $formattedExpireDate 到期\n请前往购买新套餐',
|
||||
style: highlightStyle,
|
||||
);
|
||||
},
|
||||
child: KrLocalImage(
|
||||
imageName: 'question-icon', // 图片名称
|
||||
imageType: ImageType.svg, // 图片类型
|
||||
width: 24.w,
|
||||
height: 24.w,
|
||||
color: Colors.white, // 让图标颜色与边框协调
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
} else {
|
||||
// --- 情况2.2: 订阅有效 ---
|
||||
final difference =
|
||||
expireDateTime?.difference(now);
|
||||
final remainingDaysText =
|
||||
(difference?.inDays ?? 0) > 0
|
||||
? '${difference!.inDays} 天'
|
||||
: '不足一天';
|
||||
// 使用换行符 \n 合并为单个 Text 组件
|
||||
content = Text(
|
||||
'套餐剩余:$remainingDaysText\n${controller.kr_isConnected.value ? '当前线路:${controller.kr_getRealConnectedNodeCountry()}' : '未连接'}',
|
||||
style: normalStyle,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 返回包裹在公共 Container 中的最终内容
|
||||
return Container(
|
||||
alignment: Alignment.centerLeft,
|
||||
padding: EdgeInsets.only(top: 8.h),
|
||||
child: content,
|
||||
);
|
||||
}),
|
||||
SizedBox(height: 8.h), // 添加一些垂直间距
|
||||
|
||||
// --- 自定义“闪连”Checkbox ---
|
||||
Obx(() {
|
||||
return Row(
|
||||
mainAxisSize: MainAxisSize.min, // 让 Row 的宽度包裹其内容
|
||||
children: [
|
||||
// --- 可点击的 Checkbox 区域 ---
|
||||
GestureDetector(
|
||||
// 点击方框和文字都可以切换状态
|
||||
onTap: () => controller.toggleQuickConnect(
|
||||
!controller.isQuickConnectEnabled.value),
|
||||
child: AbsorbPointer(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
// 1. 自定义 Checkbox 的方框外观
|
||||
Container(
|
||||
width: 20.w,
|
||||
height: 20.w,
|
||||
decoration: BoxDecoration(
|
||||
color: controller
|
||||
.isQuickConnectEnabled.value
|
||||
? Theme.of(context).primaryColor
|
||||
: Colors.transparent,
|
||||
border: Border.all(
|
||||
color:
|
||||
Theme.of(context).primaryColor,
|
||||
width: 1.5,
|
||||
),
|
||||
borderRadius:
|
||||
BorderRadius.circular(4.r),
|
||||
),
|
||||
child: controller
|
||||
.isQuickConnectEnabled.value
|
||||
? Icon(
|
||||
Icons.check,
|
||||
size: 14.w,
|
||||
color: Colors.black,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
SizedBox(width: 8.w),
|
||||
// 2. “闪连”标签
|
||||
Text(
|
||||
'闪连',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20.sp,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// --- 问号图标和点击弹窗区域 ---
|
||||
SizedBox(width: 6.w), // 文字和问号图标之间的间距
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
HIDialog.show(
|
||||
title: '*闪连功能',
|
||||
message:
|
||||
'开启后,每次打开软件默认自动连接,无需点击连接按钮\n在后台关闭软件后,软件将自动断开',
|
||||
);
|
||||
},
|
||||
child: KrLocalImage(
|
||||
imageName: 'question-icon', // 图片名称
|
||||
imageType: ImageType.svg, // 图片类型
|
||||
width: 24.w,
|
||||
height: 24.w,
|
||||
color: Colors.white, // 让图标颜色与边框协调
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// 将 HIAnimatedConnectButton 移到 HIBaseScaffold 外部,避免 SafeArea 约束
|
||||
HIAnimatedConnectButton(),
|
||||
],
|
||||
);
|
||||
),
|
||||
// 将 HIAnimatedConnectButton 移到 HIBaseScaffold 外部,避免 SafeArea 约束
|
||||
HIAnimatedConnectButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -12,6 +12,7 @@ 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';
|
||||
|
||||
class KRLoginView extends GetView<KRLoginController> {
|
||||
const KRLoginView({super.key});
|
||||
@ -19,7 +20,8 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final isKeyboardVisible = MediaQuery.of(context).viewInsets.bottom > 0;
|
||||
final isHideBack = (Get.arguments as Map<String, dynamic>?)?['is-back'] ?? false;
|
||||
final isHideBack =
|
||||
(Get.arguments as Map<String, dynamic>?)?['is-back'] ?? false;
|
||||
return HIBaseScaffold(
|
||||
showBack: !isHideBack,
|
||||
resizeToAvoidBottomInset: true,
|
||||
@ -27,7 +29,9 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 40.w,),
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: 40.w,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
// Text(
|
||||
@ -43,8 +47,7 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
),
|
||||
),
|
||||
),
|
||||
if (!isKeyboardVisible)
|
||||
const HIHelpEntrance(),
|
||||
if (!isKeyboardVisible) const HIHelpEntrance(),
|
||||
],
|
||||
),
|
||||
);
|
||||
@ -76,30 +79,17 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Obx(() {
|
||||
final account = KRAppRunData.getInstance().kr_account.value;
|
||||
final isDeviceLogin = account != null && account.startsWith('9000');
|
||||
|
||||
if (isDeviceLogin) return const SizedBox();
|
||||
final account = KRAppRunData.getInstance()
|
||||
.kr_account
|
||||
.value;
|
||||
final isDeviceLogin = account != null &&
|
||||
account.startsWith('9000');
|
||||
final accountText = isDeviceLogin
|
||||
? '待绑定'
|
||||
: 'ID: ${KRAppRunData.getInstance().kr_account.value.toString()}';
|
||||
|
||||
return Text(
|
||||
account ?? '',
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 20.sp,
|
||||
fontWeight: FontWeight.bold,
|
||||
height: 0.9,
|
||||
),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
final _ = KRAppRunData.getInstance().kr_isLogin.value;
|
||||
final userId = (KRAppRunData.getInstance().kr_userId.value ?? '').toString();
|
||||
final deviceId = KRAppRunData.getInstance().deviceId ?? '';
|
||||
|
||||
return Text(
|
||||
'ID: ${userId.isNotEmpty ? userId : deviceId}',
|
||||
accountText,
|
||||
style: TextStyle(
|
||||
color: Colors.white.withOpacity(0.85),
|
||||
fontSize: 14.sp,
|
||||
@ -107,51 +97,14 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
),
|
||||
);
|
||||
}),
|
||||
Obx(() {
|
||||
final currentSubscribe =
|
||||
controller.kr_subscribeService.kr_currentSubscribe.value;
|
||||
String expiryText;
|
||||
|
||||
if (currentSubscribe == null) {
|
||||
expiryText = '尚未购买套餐';
|
||||
} else {
|
||||
final now = DateTime.now();
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime =
|
||||
DateTime.parse(currentSubscribe.expireTime);
|
||||
} catch (e) {
|
||||
expireDateTime = null;
|
||||
}
|
||||
|
||||
if (expireDateTime == null) {
|
||||
expiryText = '套餐信息无效';
|
||||
} else if (expireDateTime.isBefore(now)) {
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
expiryText = '已于 $formattedExpireDate 到期';
|
||||
} else {
|
||||
expiryText = '到期时间:${expireDateTime}';final year = expireDateTime.year;
|
||||
final month = expireDateTime.month.toString().padLeft(2, '0');
|
||||
final day = expireDateTime.day.toString().padLeft(2, '0');
|
||||
final hour = expireDateTime.hour.toString().padLeft(2, '0');
|
||||
final minute = expireDateTime.minute.toString().padLeft(2, '0');
|
||||
final second = expireDateTime.second.toString().padLeft(2, '0');
|
||||
|
||||
// 2. 拼接成最终的字符串
|
||||
final formattedDateTime = '$year/$month/$day $hour:$minute:$second';
|
||||
|
||||
expiryText = '到期时间:$formattedDateTime';
|
||||
}
|
||||
}
|
||||
return Text(
|
||||
expiryText,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
);
|
||||
}),
|
||||
KRSubscriptionExpiryText(
|
||||
expireTimeProvider: () => controller
|
||||
.kr_subscribeService.kr_currentSubscribe.value?.expireTime,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12.sp,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -283,7 +236,8 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
color: const Color(0xFFA6A6A6),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(25.w), // 调整为更圆的角
|
||||
borderSide: BorderSide(color: Colors.white, width: 2),
|
||||
@ -327,7 +281,8 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
color: const Color(0xFFA6A6A6),
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
contentPadding:
|
||||
EdgeInsets.symmetric(horizontal: 16.w, vertical: 10.w),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(25.w),
|
||||
borderSide: BorderSide(color: Colors.white, width: 2),
|
||||
@ -347,14 +302,15 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
suffixIcon: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 5.w, vertical: 5.w),
|
||||
child: Obx(() {
|
||||
|
||||
return GestureDetector(
|
||||
onTap: controller.kr_canSendCode.value ? () => controller.kr_sendCode() : null,
|
||||
onTap: controller.kr_canSendCode.value
|
||||
? () => controller.kr_sendCode()
|
||||
: null,
|
||||
child: Container(
|
||||
width: 100.w,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: controller.kr_canSendCode.value
|
||||
color: controller.kr_canSendCode.value
|
||||
? Theme.of(Get.context!).primaryColor
|
||||
: const Color(0xFFD5D5D5),
|
||||
borderRadius: BorderRadius.circular(100.r), // 药丸状
|
||||
@ -366,7 +322,7 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
fontWeight: FontWeight.w600,
|
||||
color: controller.kr_canSendCode.value
|
||||
? Colors.black
|
||||
: const Color(0xFF464655) ,
|
||||
: const Color(0xFF464655),
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -378,7 +334,6 @@ class KRLoginView extends GetView<KRLoginController> {
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Widget _buildSaveButton() {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
|
||||
67
lib/app/widgets/kr_subscription_expiry_text.dart
Normal file
67
lib/app/widgets/kr_subscription_expiry_text.dart
Normal file
@ -0,0 +1,67 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class KRSubscriptionExpiryText extends StatelessWidget {
|
||||
final String? Function() expireTimeProvider;
|
||||
final TextStyle? style;
|
||||
|
||||
const KRSubscriptionExpiryText({
|
||||
Key? key,
|
||||
required this.expireTimeProvider,
|
||||
this.style,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Obx(() {
|
||||
final expireTimeStr = expireTimeProvider();
|
||||
String expiryText;
|
||||
bool highlight = false;
|
||||
|
||||
if (expireTimeStr == null || expireTimeStr.isEmpty) {
|
||||
expiryText = '尚未购买套餐';
|
||||
highlight = true;
|
||||
} else {
|
||||
DateTime? expireDateTime;
|
||||
try {
|
||||
expireDateTime = DateTime.parse(expireTimeStr);
|
||||
} catch (_) {
|
||||
expireDateTime = null;
|
||||
}
|
||||
|
||||
if (expireDateTime == null) {
|
||||
expiryText = '套餐信息无效';
|
||||
} else if (expireDateTime.isBefore(DateTime.now())) {
|
||||
final formattedExpireDate =
|
||||
'${expireDateTime.year}/${expireDateTime.month.toString().padLeft(2, '0')}/${expireDateTime.day.toString().padLeft(2, '0')}';
|
||||
expiryText = '已于 $formattedExpireDate 到期';
|
||||
highlight = true;
|
||||
} else {
|
||||
final year = expireDateTime.year;
|
||||
final month = expireDateTime.month.toString().padLeft(2, '0');
|
||||
final day = expireDateTime.day.toString().padLeft(2, '0');
|
||||
final hour = expireDateTime.hour.toString().padLeft(2, '0');
|
||||
final minute = expireDateTime.minute.toString().padLeft(2, '0');
|
||||
final second = expireDateTime.second.toString().padLeft(2, '0');
|
||||
|
||||
final formattedDateTime = '$year/$month/$day $hour:$minute:$second';
|
||||
expiryText = '到期时间:$formattedDateTime';
|
||||
}
|
||||
}
|
||||
|
||||
final baseStyle = style ??
|
||||
const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 12,
|
||||
);
|
||||
final appliedStyle = highlight
|
||||
? baseStyle.copyWith(color: const Color(0xFFFF00B7))
|
||||
: baseStyle;
|
||||
|
||||
return Text(
|
||||
expiryText,
|
||||
style: appliedStyle,
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user