|
|
|
@ -29,7 +29,7 @@ class GoodsvipView extends GetView<GoodsvipController> { |
|
|
|
onPressed: () => Get.back(), |
|
|
|
), |
|
|
|
title: Text( |
|
|
|
'aiRecharge'.tr, |
|
|
|
_pageTitle, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 18.sp, |
|
|
|
fontWeight: FontWeight.w600, |
|
|
|
@ -48,29 +48,34 @@ class GoodsvipView extends GetView<GoodsvipController> { |
|
|
|
} else if (controller.error.isNotEmpty) { |
|
|
|
content = Center(child: Text(controller.error.value)); |
|
|
|
} else { |
|
|
|
final focused = _tier != null; |
|
|
|
final source = focused |
|
|
|
? controller.items.where(_matchesTier).toList() |
|
|
|
: controller.items.toList(); |
|
|
|
final Map<UsageType, List<DBGoods>> grouped = {}; |
|
|
|
for (final g in controller.items) { |
|
|
|
for (final g in source) { |
|
|
|
grouped.putIfAbsent(g.usagetype, () => []).add(g); |
|
|
|
} |
|
|
|
// VIP 时长在前、算力包在后;两者都没有商品时页面只剩权益说明 |
|
|
|
final order = [UsageType.Vip, UsageType.Compute]; |
|
|
|
// 从「我的」点某一档进来时只留会员服务和这一档;其它入口仍是完整充值页。 |
|
|
|
final order = |
|
|
|
focused ? [UsageType.Vip] : [UsageType.Vip, UsageType.Compute]; |
|
|
|
final children = <Widget>[]; |
|
|
|
// 到期 / 算力不足提示条:阈值由后台配(0 = 关掉该提示),判定在 controller 里 |
|
|
|
if (controller.vipExpiringSoon) { |
|
|
|
children.add(_buildWarnBanner( |
|
|
|
isDarkMode, |
|
|
|
'vipExpiringSoon'.trParams({'days': '${controller.vipDaysLeft}'}), |
|
|
|
)); |
|
|
|
children.add(SizedBox(height: 12.h)); |
|
|
|
} |
|
|
|
if (controller.computeLow) { |
|
|
|
children.add(_buildWarnBanner(isDarkMode, 'computeLow'.tr)); |
|
|
|
children.add(SizedBox(height: 12.h)); |
|
|
|
if (!focused) { |
|
|
|
if (controller.vipExpiringSoon) { |
|
|
|
children.add(_buildWarnBanner( |
|
|
|
isDarkMode, |
|
|
|
'vipExpiringSoon' |
|
|
|
.trParams({'days': '${controller.vipDaysLeft}'}), |
|
|
|
)); |
|
|
|
children.add(SizedBox(height: 12.h)); |
|
|
|
} |
|
|
|
if (controller.computeLow) { |
|
|
|
children.add(_buildWarnBanner(isDarkMode, 'computeLow'.tr)); |
|
|
|
children.add(SizedBox(height: 12.h)); |
|
|
|
} |
|
|
|
children.add(_buildFeaturesSection(isDarkMode)); |
|
|
|
children.add(SizedBox(height: 16.h)); |
|
|
|
} |
|
|
|
children.add(_buildFeaturesSection(isDarkMode)); |
|
|
|
children.add(SizedBox(height: 16.h)); |
|
|
|
// children.add(_buildScenesSection(isDarkMode)); |
|
|
|
// children.add(SizedBox(height: 16.h)); |
|
|
|
for (int i = 0; i < order.length; i++) { |
|
|
|
final t = order[i]; |
|
|
|
final list = grouped[t]; |
|
|
|
@ -84,7 +89,9 @@ class GoodsvipView extends GetView<GoodsvipController> { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
children.add(GoodsFooterSection(isDarkMode: isDarkMode)); |
|
|
|
if (!focused) { |
|
|
|
children.add(GoodsFooterSection(isDarkMode: isDarkMode)); |
|
|
|
} |
|
|
|
content = ListView( |
|
|
|
key: ValueKey(userTick), |
|
|
|
padding: EdgeInsets.all(16.w), |
|
|
|
@ -113,6 +120,49 @@ class GoodsvipView extends GetView<GoodsvipController> { |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
/// 进页时记下的档位。不要改回读 Get.arguments。 |
|
|
|
String? get _tier => controller.vipTier; |
|
|
|
|
|
|
|
String get _pageTitle { |
|
|
|
switch (_tier) { |
|
|
|
case 'month': |
|
|
|
return 'vipMonth'.tr; |
|
|
|
case 'quarter': |
|
|
|
return 'vipQuarter'.tr; |
|
|
|
case 'lifetime': |
|
|
|
return 'vipLifetime'.tr; |
|
|
|
default: |
|
|
|
return 'aiRecharge'.tr; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 月度约 30 天、季度约 90 天、终生按一年以上。天数对不上时再看商品名。 |
|
|
|
bool _matchesTier(DBGoods g) { |
|
|
|
if (g.usagetype != UsageType.Vip) return false; |
|
|
|
final tier = _tier; |
|
|
|
if (g.viptime > 0) { |
|
|
|
switch (tier) { |
|
|
|
case 'month': |
|
|
|
return g.viptime >= 28 && g.viptime <= 31; |
|
|
|
case 'quarter': |
|
|
|
return g.viptime >= 80 && g.viptime <= 100; |
|
|
|
case 'lifetime': |
|
|
|
return g.viptime >= 365; |
|
|
|
} |
|
|
|
} |
|
|
|
final blob = '${g.id} ${g.name} ${g.localname}'.toLowerCase(); |
|
|
|
switch (tier) { |
|
|
|
case 'month': |
|
|
|
return blob.contains('month') || blob.contains('月度'); |
|
|
|
case 'quarter': |
|
|
|
return blob.contains('quarter') || blob.contains('季'); |
|
|
|
case 'lifetime': |
|
|
|
return blob.contains('life') || blob.contains('终'); |
|
|
|
default: |
|
|
|
return false; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/// 到期 / 算力不足的提示条。刻意做成温和的黄色而不是红色错误样式—— |
|
|
|
/// 这是「该续费了」的提醒,不是故障;下面就是购买入口,不需要再额外引导。 |
|
|
|
Widget _buildWarnBanner(bool isDarkMode, String text) { |
|
|
|
@ -486,10 +536,10 @@ class GoodsvipView extends GetView<GoodsvipController> { |
|
|
|
shrinkWrap: true, |
|
|
|
physics: const NeverScrollableScrollPhysics(), |
|
|
|
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( |
|
|
|
crossAxisCount: 2, |
|
|
|
crossAxisCount: _tier != null ? 1 : 2, |
|
|
|
mainAxisSpacing: 8.h, |
|
|
|
crossAxisSpacing: 12.w, |
|
|
|
childAspectRatio: 1.3, |
|
|
|
childAspectRatio: _tier != null ? 2.8 : 1.3, |
|
|
|
), |
|
|
|
itemCount: list.length, |
|
|
|
itemBuilder: (_, i) => _buildGridItemCard(list[i], type, isDarkMode), |
|
|
|
|