155 lines
5.5 KiB
Dart
155 lines
5.5 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:get/get.dart';
|
|
import 'package:hgdj/hj_utils/screen.dart';
|
|
import 'package:hgdj/tools_base/widget/net_image_widget.dart';
|
|
import 'package:hgdj/tools_base/widget/sheet_handle_bar.dart';
|
|
|
|
import '../../hj_page/mine/mine_vip/pay_order_source.dart';
|
|
import '../../hj_page/mine/mine_vip/vip_support_model.dart';
|
|
import '../../hj_page/mine/widgets/gradient_text.dart';
|
|
import 'guide_common.dart';
|
|
import 'guide_config.dart';
|
|
import 'guide_manager.dart';
|
|
|
|
/// 吸底型付费引导弹窗(通用壳):横条 + 标题 + [badge] + 主图 + 副文案 + 开通按钮,
|
|
/// 首页/播放页各自传 title/subtitle/buttonText 组装
|
|
class GuideBottomSheet extends StatelessWidget {
|
|
final VipProductModel card;
|
|
final Widget title; // 各场景自定义
|
|
final Widget? badge; // 标题下方的小标签(免费次数场景用),不传不占位
|
|
final Widget subtitle; // 主图下方文案
|
|
final String buttonText;
|
|
final PaySourcePage sourcePage;
|
|
final String cover; // 场景下发的主图,相对路径由 ImageCacheManager 拼域名
|
|
const GuideBottomSheet({
|
|
super.key,
|
|
required this.card,
|
|
required this.title,
|
|
this.badge,
|
|
required this.subtitle,
|
|
required this.buttonText,
|
|
required this.sourcePage,
|
|
required this.cover,
|
|
});
|
|
|
|
/// [scene] 决定主图/卡/下单来源,调用方须先用开关判过能弹
|
|
/// 返回 true = 点了开通并已跳会员页(调用方据此别恢复播放)
|
|
static Future<bool> show({
|
|
required GuideScene scene,
|
|
required Widget title,
|
|
required Widget subtitle,
|
|
Widget? badge,
|
|
String? buttonText,
|
|
}) async {
|
|
final card = await loadGuideCard(scene);
|
|
if (card == null) return false; // 配置有误不弹
|
|
final goVip = await Get.bottomSheet<bool>(
|
|
GuideBottomSheet(
|
|
card: card,
|
|
title: title,
|
|
badge: badge,
|
|
subtitle: subtitle,
|
|
buttonText: buttonText ?? '立即开通 · 仅需¥${card.discountedPriceUI}',
|
|
sourcePage: guideSourcePage(scene),
|
|
cover: GuideManager().configOf(scene)?.cover ?? '', //已校验非空
|
|
),
|
|
isScrollControlled: true,
|
|
backgroundColor: Colors.transparent,
|
|
);
|
|
return goVip ?? false;
|
|
}
|
|
|
|
/// 播放页引导(长短视频共用文案):文案优先用下发的,没配走默认。
|
|
/// [buttonText] 短视频传无价文案,长视频走默认带价文案
|
|
static Future<bool> showVideo({String? buttonText}) {
|
|
final config = GuideManager().configOf(GuideScene.videoPreviewEnd);
|
|
return show(
|
|
scene: GuideScene.videoPreviewEnd,
|
|
title: Text(
|
|
config?.title?.isNotEmpty == true
|
|
? config!.title!
|
|
: '该视频为VIP内容\n只能观看试看内容哦~',
|
|
textAlign: TextAlign.center,
|
|
style: const TextStyle(
|
|
color: Colors.white, fontSize: 17, fontWeight: FontWeight.w600),
|
|
),
|
|
subtitle: GradientText(
|
|
config?.description?.isNotEmpty == true
|
|
? config!.description!
|
|
: '想要查看完整内容,需要开通会员',
|
|
gradient:
|
|
const LinearGradient(colors: [Colors.white, Color(0xffEFD394)]),
|
|
style: const TextStyle(
|
|
color: Colors.white, fontSize: 15, fontWeight: FontWeight.w500),
|
|
),
|
|
buttonText: buttonText,
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Material(
|
|
color: Colors.transparent,
|
|
child: Container(
|
|
width: double.infinity,
|
|
padding: EdgeInsets.fromLTRB(16, 18, 16, 18 + screen.paddingBottom),
|
|
decoration: const BoxDecoration(
|
|
gradient: LinearGradient(
|
|
begin: Alignment.topCenter,
|
|
end: Alignment.bottomCenter,
|
|
colors: [Color(0xff0F0F0F), Colors.black]),
|
|
border: Border(
|
|
top: BorderSide(
|
|
color: Color(0x4DE4BB6D))), // rgba(228,187,109,0.3)
|
|
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
|
|
),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
const SheetHandleBar(),
|
|
18.sizeBoxH,
|
|
title,
|
|
if (badge != null) ...[18.sizeBoxH, badge!],
|
|
18.sizeBoxH,
|
|
// 主图(场景下发)
|
|
SizedBox(
|
|
width: 270,
|
|
height: 122,
|
|
child: NetworkImageLoader(
|
|
imageUrl: cover, fit: BoxFit.fill, borderRadius: 8),
|
|
),
|
|
18.sizeBoxH,
|
|
subtitle,
|
|
18.sizeBoxH,
|
|
// 开通按钮
|
|
GestureDetector(
|
|
onTap: () => goVipDetail(card, sourcePage: sourcePage),
|
|
child: Container(
|
|
width: double.infinity,
|
|
height: 52,
|
|
alignment: Alignment.center,
|
|
decoration: BoxDecoration(
|
|
gradient: const LinearGradient(
|
|
colors: [Color(0xffFFB03F), Color(0xffF2680C)]),
|
|
borderRadius: BorderRadius.circular(26),
|
|
boxShadow: [
|
|
BoxShadow(
|
|
color: const Color(0x73F2680C),
|
|
blurRadius: 18,
|
|
offset: const Offset(0, 6))
|
|
], // rgba(242,104,12,0.45)
|
|
),
|
|
child: Text(buttonText,
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 17,
|
|
fontWeight: FontWeight.w700)),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|