初始化提交

This commit is contained in:
2025-09-23 16:23:15 +08:00
commit 877b18a70f
590 changed files with 53617 additions and 0 deletions
@@ -0,0 +1,506 @@
import 'package:get/get.dart';
import 'package:kaer_with_panels/app/services/api_service/kr_subscribe_api.dart';
import 'package:kaer_with_panels/app/model/response/kr_package_list.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_log_util.dart';
import '../../../common/app_run_data.dart';
import '../../../model/response/kr_already_subscribe.dart';
import '../../../model/response/kr_payment_methods.dart';
import '../../../routes/app_pages.dart';
import '../../../services/api_service/kr_api.user.dart';
import '../../../utils/kr_event_bus.dart';
/// 会员购买控制器
/// 负责处理会员套餐选择、支付方式选择和订阅流程
class KRPurchaseMembershipController extends GetxController {
// 注入的服务
final KRSubscribeApi _kr_subscribeApi = KRSubscribeApi();
// 事件监听器
Worker? _kr_eventWorker;
// UI 状态
final RxBool kr_isLoading = false.obs;
final RxString kr_errorMessage = ''.obs;
final RxString kr_userEmail = ''.obs;
final RxBool kr_showPlanSelector = false.obs; // 是否显示套餐选择器
// 数据状态
final RxList<KRPackageListItem> kr_plans = <KRPackageListItem>[].obs;
final RxList<KRPaymentMethod> kr_paymentMethods = <KRPaymentMethod>[].obs;
final RxInt kr_selectedPlanIndex = 0.obs;
final RxInt kr_selectedPaymentMethodIndex = (-1).obs;
final RxInt kr_selectedDiscountIndex = (-1).obs;
// 已订阅套餐列表
var _kr_alreadySubscribe = <KRAlreadySubscribe>[];
/// 描述是否展开
final kr_isDescriptionExpanded = false.obs;
/// 当前余额
var _kr_balance = 0;
@override
void onInit() {
super.onInit();
kr_initializeData();
}
@override
void onClose() {
_kr_eventWorker?.dispose();
super.onClose();
}
/// 初始化数据
Future<void> kr_initializeData() async {
kr_userEmail.value = KRAppRunData.getInstance().kr_account.toString();
await kr_getPackageList();
// 监听所有支付相关消息
_kr_eventWorker = KREventBus().kr_listenMessages(
[KRMessageType.kr_payment, KRMessageType.kr_subscribe_update],
_kr_handleMessage,
);
}
/// 处理消息
Future<void> _kr_handleMessage(KRMessageData message) async {
switch (message.kr_type) {
case KRMessageType.kr_payment:
await _iniUserInfo();
// 只更新支付方式显示,因为支付方式标题中包含余额信息
if (kr_paymentMethods.isNotEmpty) {
final balanceMethodIndex = kr_paymentMethods
.indexWhere((method) => method.platform == 'balance');
if (balanceMethodIndex != -1) {
// 触发支付方式列表更新
kr_paymentMethods.refresh();
}
}
break;
case KRMessageType.kr_subscribe_update:
break;
default:
break;
}
}
/// 获取套餐列表和支付方式
Future<void> kr_getPackageList() async {
kr_isLoading.value = true;
kr_selectedPlanIndex.value = 0; // 重置套餐选择
kr_selectedDiscountIndex.value = -1; // 重置折扣选择
kr_selectedPaymentMethodIndex.value = -1; // 重置支付方式选择
await _iniUserInfo();
await kr_getAlreadySubscribe();
await kr_fetchPackages();
await kr_fetchPaymentMethods();
// 根据套餐数量决定是否显示套餐选择器
kr_showPlanSelector.value = kr_plans.length > 1;
kr_isLoading.value = false;
}
/// 初始化用户信息
Future<void> _iniUserInfo() async {
final either0 = await KRUserApi().kr_getUserInfo();
either0.fold(
(error) {
KRLogUtil.kr_e(error.msg, tag: 'AppRunData');
},
(userInfo) async {
_kr_balance = userInfo.balance;
},
);
}
/// 获取用户已订阅套餐
Future<void> kr_getAlreadySubscribe() async {
final either = await _kr_subscribeApi.kr_getAlreadySubscribe();
either.fold(
(error) => KRCommonUtil.kr_showToast(error.msg),
(alreadySubscribe) {
_kr_alreadySubscribe = alreadySubscribe;
KRLogUtil.kr_i(
'已订阅套餐: ${_kr_alreadySubscribe.map((e) => e.subscribeId).toList()}',
tag: 'PurchaseMembershipController');
},
);
}
/// 获取套餐列表
Future<void> kr_fetchPackages() async {
final either = await _kr_subscribeApi.kr_getPackageListList();
either.fold(
(error) => KRCommonUtil.kr_showToast(error.msg),
(packageList) {
kr_plans.value = packageList.kr_list;
// 默认选择第一个套餐
if (kr_plans.isNotEmpty) {
kr_selectedPlanIndex.value = 0;
kr_initializeSelection(kr_plans.first);
}
},
);
}
/// 获取支付方式列表
Future<void> kr_fetchPaymentMethods() async {
final either = await _kr_subscribeApi.kr_getPaymentMethods();
either.fold(
(error) => KRCommonUtil.kr_showToast(error.msg),
(paymentMethods) {
kr_paymentMethods.value = paymentMethods;
// 检查当前选择的套餐价格是否小于等于余额
if (kr_plans.isNotEmpty) {
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
final selectedPrice = kr_getPlanPrice(selectedPlan,
discountIndex: kr_selectedDiscountIndex.value);
// 查找余额支付方式的索引
final balanceMethodIndex = paymentMethods
.indexWhere((method) => method.platform == 'balance');
// 如果找到余额支付方式且余额足够,默认选择余额支付
if (balanceMethodIndex != -1 && selectedPrice <= _kr_balance / 100) {
kr_selectPaymentMethod(balanceMethodIndex);
} else {
// 查找第一个非余额支付方式
final nonBalanceMethodIndex = paymentMethods
.indexWhere((method) => method.platform != 'balance');
if (nonBalanceMethodIndex != -1) {
kr_selectPaymentMethod(nonBalanceMethodIndex);
}
}
}
},
);
}
/// 获取支付方式显示标题
String kr_getPaymentMethodTitle(KRPaymentMethod method) {
if (method.platform == 'balance') {
return '${method.name}${(_kr_balance / 100).toStringAsFixed(2)})';
}
return method.name;
}
/// 选择套餐
void kr_selectPlan(int planIndex, {int? discountIndex}) {
if (planIndex >= 0 && planIndex < kr_plans.length) {
kr_selectedPlanIndex.value = planIndex;
// 确保折扣索引有效
if (discountIndex != null) {
final plan = kr_plans[planIndex];
if (discountIndex >= 0 && discountIndex < plan.kr_discount.length) {
kr_selectedDiscountIndex.value = discountIndex;
} else {
// 如果传入的折扣索引无效,但有折扣选项,则默认选择第一个
if (plan.kr_discount.isNotEmpty) {
kr_selectedDiscountIndex.value = 0;
} else {
kr_selectedDiscountIndex.value = -1;
}
}
} else {
// 如果没有传入折扣索引,但有折扣选项,则默认选择第一个
final plan = kr_plans[planIndex];
if (plan.kr_discount.isNotEmpty) {
kr_selectedDiscountIndex.value = 0;
} else {
kr_selectedDiscountIndex.value = -1;
}
}
// 重置支付方式选择
kr_selectedPaymentMethodIndex.value = -1;
// 重新判断应该选择的支付方式
_kr_updatePaymentMethodSelection();
// 更新UI状态
update();
}
}
/// 更新支付方式选择
void _kr_updatePaymentMethodSelection() {
if (kr_plans.isEmpty || kr_paymentMethods.isEmpty) return;
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
final selectedPrice = kr_getPlanPrice(selectedPlan,
discountIndex: kr_selectedDiscountIndex.value);
// 查找余额支付方式的索引
final balanceMethodIndex =
kr_paymentMethods.indexWhere((method) => method.platform == 'balance');
// 如果找到余额支付方式且余额足够,选择余额支付
if (balanceMethodIndex != -1 && selectedPrice <= _kr_balance / 100) {
kr_selectPaymentMethod(balanceMethodIndex);
} else {
// 查找第一个非余额支付方式
final nonBalanceMethodIndex = kr_paymentMethods
.indexWhere((method) => method.platform != 'balance');
if (nonBalanceMethodIndex != -1) {
kr_selectPaymentMethod(nonBalanceMethodIndex);
}
}
}
/// 选择支付方式
void kr_selectPaymentMethod(int index) {
if (index >= 0 && index < kr_paymentMethods.length) {
kr_selectedPaymentMethodIndex.value = index;
}
}
/// 获取当前选中的数量
int kr_getSelectedQuantity() {
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
if (kr_selectedDiscountIndex.value >= 0 &&
kr_selectedDiscountIndex.value < selectedPlan.kr_discount.length) {
return selectedPlan
.kr_discount[kr_selectedDiscountIndex.value].kr_quantity;
}
return 1; // 默认数量为1
}
/// 开始订阅流程
Future<void> kr_startSubscription() async {
if (!kr_validateSubscriptionData()) return;
kr_errorMessage.value = '';
try {
await kr_processPurchaseAndCheckout();
} catch (e) {
kr_errorMessage.value = '订阅失败: ${e.toString()}';
}
}
/// 验证订阅数据
bool kr_validateSubscriptionData() {
if (kr_plans.isEmpty) {
KRCommonUtil.kr_showToast('没有可用的套餐');
return false;
}
if (kr_selectedPaymentMethodIndex.value < 0 ||
kr_selectedPaymentMethodIndex.value >= kr_paymentMethods.length) {
KRCommonUtil.kr_showToast('请选择支付方式');
return false;
}
return true;
}
/// 处理购买和结账流程
Future<void> kr_processPurchaseAndCheckout() async {
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
final selectedPaymentMethod =
kr_paymentMethods[kr_selectedPaymentMethodIndex.value];
// 获取选中的数量
final quantity = kr_getSelectedQuantity();
// 判断是续订还是新购
final isRenewal = _kr_alreadySubscribe
.any((subscribe) => subscribe.subscribeId == selectedPlan.kr_id);
final subscribeId = isRenewal
? _kr_alreadySubscribe
.firstWhere(
(subscribe) => subscribe.subscribeId == selectedPlan.kr_id)
.userSubscribeId
: 0;
// 根据判断结果调用不同的接口
final purchaseEither = isRenewal
? await _kr_subscribeApi.kr_renewal(
subscribeId,
quantity,
selectedPaymentMethod.id,
'',
)
: await _kr_subscribeApi.kr_purchase(
selectedPlan.kr_id,
quantity,
selectedPaymentMethod.id,
'',
);
purchaseEither.fold(
(error) => KRCommonUtil.kr_showToast(error.msg),
(order) async {
// 所有支付方式都需要调用 checkout 接口
final checkoutEither = await _kr_subscribeApi.kr_checkout(order);
checkoutEither.fold(
(error) => KRCommonUtil.kr_showToast(error.msg),
(uri) => Get.toNamed(
Routes.KR_ORDER_STATUS,
arguments: {
'url': uri,
'order': order,
'payment_type': selectedPaymentMethod.platform,
},
),
);
},
);
}
/// 获取套餐价格
double kr_getPlanPrice(KRPackageListItem plan, {int? discountIndex}) {
if (discountIndex != null &&
discountIndex >= 0 &&
discountIndex < plan.kr_discount.length) {
// 计算折扣价格
final discount = plan.kr_discount[discountIndex];
return (plan.kr_unitPrice / 100) *
discount.kr_quantity *
(discount.kr_discount / 100);
}
return plan.kr_unitPrice / 100;
}
/// 获取时间字符串
String kr_getTimeStr(KRPackageListItem plan, {int? discountIndex}) {
final quantity = discountIndex != null &&
discountIndex >= 0 &&
discountIndex < plan.kr_discount.length
? plan.kr_discount[discountIndex].kr_quantity
: 1;
if (plan.kr_unitTime == 'Month') {
return AppTranslations.kr_purchaseMembership.month(quantity);
} else if (plan.kr_unitTime == 'Year') {
return AppTranslations.kr_purchaseMembership.year(quantity);
} else if (plan.kr_unitTime == 'Day') {
return AppTranslations.kr_purchaseMembership.day(quantity);
}
return '';
}
/// 获取折扣文本
String kr_getDiscountText(KRPackageListItem plan, int discountIndex) {
if (discountIndex >= 0 && discountIndex < plan.kr_discount.length) {
final discount = plan.kr_discount[discountIndex];
// 折扣值为 100 表示原价,不需要显示折扣
if (discount.kr_discount == 100) {
return '';
}
// 计算折扣百分比(例如:95% 显示为 -5%)
final discountPercent = 100 - discount.kr_discount;
return '-${discountPercent}%';
}
return '';
}
/// 获取套餐总选项数
int kr_getTotalOptionsCount(KRPackageListItem plan) {
// 确保折扣列表不为空
if (plan.kr_discount.isEmpty) {
return 1; // 如果没有折扣选项,至少返回1个选项
}
return plan.kr_discount.length;
}
/// 初始化选择
void kr_initializeSelection(KRPackageListItem plan) {
if (plan.kr_discount.isNotEmpty) {
// 默认选择第一个选项
kr_selectedDiscountIndex.value = 0;
} else {
// 如果没有选项,设置为 -1
kr_selectedDiscountIndex.value = -1;
}
}
/// 获取当前选中套餐的描述
String kr_getSelectedPlanDescription() {
if (kr_selectedPlanIndex.value >= kr_plans.length) return '';
final plan = kr_plans[kr_selectedPlanIndex.value];
return plan.kr_description.kr_features
.map((feature) => feature.kr_label)
.join('');
}
/// 获取当前选中套餐的特性标题列表
List<String> kr_getSelectedPlanFeatureLabels() {
if (kr_selectedPlanIndex.value >= kr_plans.length) return [];
final plan = kr_plans[kr_selectedPlanIndex.value];
return plan.kr_description.kr_features
.map((feature) => feature.kr_label)
.toList();
}
/// 获取当前选中套餐的详细信息
List<KRFeature> kr_getSelectedPlanFeatures() {
if (kr_selectedPlanIndex.value >= kr_plans.length) return [];
final plan = kr_plans[kr_selectedPlanIndex.value];
return plan.kr_description.kr_features;
}
/// 判断当前选中的套餐是否是续订
bool kr_isRenewal() {
if (kr_plans.isEmpty || _kr_alreadySubscribe.isEmpty) return false;
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
return _kr_alreadySubscribe
.any((subscribe) => subscribe.subscribeId == selectedPlan.kr_id);
}
/// 获取当前选中套餐的订阅按钮文字
String kr_getSubscribeButtonText() {
if (kr_plans.isEmpty) return '';
final selectedPlan = kr_plans[kr_selectedPlanIndex.value];
final isRenewal = _kr_alreadySubscribe
.any((subscribe) => subscribe.subscribeId == selectedPlan.kr_id);
return isRenewal
? AppTranslations.kr_purchaseMembership.renewNow
: AppTranslations.kr_purchaseMembership.startSubscription;
}
/// 切换描述展开状态
void kr_toggleDescriptionExpanded() {
kr_isDescriptionExpanded.value = !kr_isDescriptionExpanded.value;
}
/// 获取流量限制显示文本
String kr_getTrafficLimitText(KRPackageListItem plan) {
KRLogUtil.kr_i('原始流量值: ${plan.kr_traffic}', tag: 'TrafficLimit');
if (plan.kr_traffic == 0) {
return AppTranslations.kr_purchaseMembership.unlimitedTraffic;
}
// 将字节转换为GB
final trafficInGB = plan.kr_traffic / (1024 * 1024 * 1024);
KRLogUtil.kr_i('转换为GB后的值: $trafficInGB', tag: 'TrafficLimit');
if (trafficInGB < 1) {
return '${(trafficInGB * 1024).toStringAsFixed(0)}MB';
} else if (trafficInGB < 1024) {
return '${trafficInGB.toStringAsFixed(0)}GB';
} else {
return '${(trafficInGB / 1024).toStringAsFixed(1)}TB';
}
}
/// 获取设备限制显示文本
String kr_getDeviceLimitText(KRPackageListItem plan) {
if (plan.kr_deviceLimit == 0) {
return AppTranslations.kr_purchaseMembership.unlimitedDevices;
}
return AppTranslations.kr_purchaseMembership
.devices(plan.kr_deviceLimit.toString());
}
}