Files
huangguo_android/lib/alert/video/video_buy_bottom_sheet.dart
2026-09-15 15:44:13 +07:00

269 lines
9.1 KiB
Dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/app_colors.dart';
import 'package:hgdj/extension/extensions.dart';
import 'package:hgdj/hj_model/video_model.dart';
import 'package:hgdj/hj_page/mine/mine_vip/widgets/coin_pay_bottom_sheet.dart';
import 'package:hgdj/hj_page/mine/widgets/gradient_text.dart';
import 'package:hgdj/hj_utils/pay/pay_manager.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/routers/jump_router.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:hgdj/tools_base/widget/sheet_handle_bar.dart';
import 'package:provider/provider.dart';
///金币购买作品面板
class VideoBuyBottomSheet extends StatefulWidget {
final VideoModel video;
const VideoBuyBottomSheet({super.key, required this.video});
@override
State<VideoBuyBottomSheet> createState() => _VideoBuyBottomSheetState();
}
class _VideoBuyBottomSheetState extends State<VideoBuyBottomSheet> {
VideoModel get _video => widget.video;
bool get _isCartoon => _video.videoType == 1;
bool get _isSeedLink => _video.newsType == 'SEED_LINK';
//图集和黄游金币解锁,没有vip折扣
bool get _noDiscount => _video.newsType == "PIC" || _isSeedLink;
//实际售价:无折扣品类按原价,其余按折后价
String get _priceText =>
'${(_noDiscount ? _video.originCoins : _video.coins) ?? 0} 金币';
@override
void initState() {
super.initState();
globalStore.updateUserInfo();
globalStore.refreshWallet();
}
@override
Widget build(BuildContext context) {
return Consumer<GlobalStore>(
builder: (_, store, __) {
final enough = (store.wallet?.amount ?? 0) >= (_video.realCoins ?? 0);
return Container(
width: double.infinity,
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 18),
decoration: const BoxDecoration(
color: AppColors.primaryColor,
borderRadius: BorderRadius.vertical(top: Radius.circular(20)),
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
const SheetHandleBar(),
18.sizeBoxH,
const Text(
'购买作品',
style: TextStyle(
color: Color(0xE5ffffff),
fontSize: 20,
fontWeight: FontWeight.w500),
),
18.sizeBoxH,
//作品解锁价
Row(
children: [
const Text('作品解锁',
style: TextStyle(color: Color(0xE5ffffff), fontSize: 14)),
const Spacer(),
GestureDetector(
onTap: () => CoinPayBottomSheet.show(),
child: Text(
_priceText,
style: const TextStyle(
color: Color(0xffFF9000),
fontSize: 14,
fontWeight: FontWeight.w500),
),
),
],
),
18.sizeBoxH,
//图集和黄游金币解锁,没有vip折扣,不展示原价和折扣说明
if (!_noDiscount) ..._discountRows(store),
Divider(height: 0.5, color: Colors.white.withValues(alpha: .05)),
18.sizeBoxH,
//我的金币余额 + 充值入口
Row(
children: [
const Text('我的金币',
style: TextStyle(color: Color(0xE5ffffff), fontSize: 14)),
const Spacer(),
Text(
'${store.wallet?.amount?.toDouble().fixed(2) ?? 0}',
style: const TextStyle(
color: Color(0xE5ffffff),
fontSize: 14,
fontWeight: FontWeight.w500),
),
12.sizeBoxW,
InkWell(
enableFeedback: false,
onTap: () => CoinPayBottomSheet.show(),
child: const Text(
'充值',
style: TextStyle(
color: Color(0xffA4634D),
fontSize: 14,
fontWeight: FontWeight.w400,
decoration: TextDecoration.underline,
decorationColor: Color(0xffA4634D),
),
),
),
],
),
18.sizeBoxH,
//底部两个按钮:立即支付 / 开通会员
Row(
children: [
Expanded(
child: _button(
enough ? '$_priceText/立即支付' : '余额不足,前往充值',
textColor: const Color(0xff7B0000),
decoration: BoxDecoration(
gradient: const LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [Color(0xfff8f3ae), Color(0xffddac44)],
),
borderRadius: BorderRadius.circular(3),
),
onTap: () => _onPay(enough),
),
),
12.sizeBoxW,
Expanded(
child: _button(
'开通会员免费看',
textColor: Colors.white,
decoration: BoxDecoration(
color: const Color(0xfff68804),
borderRadius: BorderRadius.circular(3),
),
onTap: () => pushToWalletPage(),
),
),
],
),
],
),
);
},
);
}
//原价 + 折扣说明(有 vip 折扣的品类才展示)
List<Widget> _discountRows(GlobalStore store) {
final isNormalUser = store.meInfo == null || store.meInfo?.vipLevel == 0;
final isVip = store.isVIP;
final String discountText;
if ((_video.coins ?? 0) < (_video.originCoins ?? 0) && isVip) {
discountText = '您当前享受${store.meInfo?.payVidDiscount}折优惠';
} else if (isVip) {
discountText = '您当前不享受免费观看';
} else {
discountText = '您当前不享受折扣优惠';
}
return [
Row(
children: [
const Text('作品原价',
style: TextStyle(color: Color(0xE5FFFFFF), fontSize: 14)),
const Spacer(),
Text(
'${_video.originCoins ?? 0} 金币',
style: TextStyle(
color: const Color(0x8CFFFFFF),
fontSize: 14,
decoration: isNormalUser ? null : TextDecoration.lineThrough,
decorationColor: const Color(0x8CFFFFFF),
),
),
],
),
18.sizeBoxH,
Row(
children: [
GradientText(
discountText,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400),
gradient: const LinearGradient(
colors: [Color(0xffAC7E6E), Color(0xffA4634D)]),
),
const Spacer(),
GestureDetector(
onTap: () => pushToWalletPage(),
child: GradientText(
isVip ? '升级会员免费看' : '购买VIP免费看',
gradient: const LinearGradient(
colors: [Color(0xffAC7E6E), Color(0xffA4634D)]),
style: const TextStyle(
fontSize: 14,
fontWeight: FontWeight.w500,
decoration: TextDecoration.underline,
decorationColor: Color(0xffA4634D),
),
),
),
],
),
18.sizeBoxH,
];
}
Widget _button(String text,
{required Color textColor,
required BoxDecoration decoration,
required VoidCallback onTap}) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: onTap,
child: Container(
height: 44,
alignment: Alignment.center,
decoration: decoration,
child: Text(
text,
style: TextStyle(
color: textColor, fontSize: 16, fontWeight: FontWeight.w500),
),
),
);
}
void _onPay(bool enough) async {
if (!enough) {
await CoinPayBottomSheet.show();
return;
}
//黄游(SEED_LINK)和普通视频都按单片算,动漫按整部算
final type =
(!_isSeedLink && _isCartoon) ? ProductType.mediaAll : ProductType.media;
await PayManager().buy(
_video.id,
type,
source: 'video_buy',
goldVideoCouponNum: 0,
jumpWalletOnInsufficient: false,
onSuccess: (data) {
_video.vidStatus?.hasPaid = true;
Get.back(result: true);
},
onFailure: (data) {
if (data?.code == 8000) {
CoinPayBottomSheet.show();
}
},
);
}
}