初始化

This commit is contained in:
谢宇宁
2026-09-15 15:44:13 +07:00
commit a23ba685e9
1065 changed files with 101122 additions and 0 deletions
@@ -0,0 +1,81 @@
import 'package:flutter/material.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/hj_model/mine/exchange/recharge_type_list_model.dart';
import 'package:hgdj/hj_utils/screen.dart';
// 金币充值档位卡片
class CoinItem extends StatelessWidget {
final RechargeTypeModel model;
final bool isSelected; // 是否选中
final VoidCallback? onTap;
const CoinItem(this.model, {super.key, this.onTap, this.isSelected = false});
@override
Widget build(BuildContext context) {
final couponDesc = model.couponDesc;
return GestureDetector(
onTap: onTap,
child: Stack(
children: [
Container(
width: double.infinity,
margin: const EdgeInsets.only(top: 10),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: .1),
borderRadius: BorderRadius.circular(8),
border: isSelected
? Border.all(width: 1, color: const Color(0xffF9C142))
: null,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('coin_icon.webp'.mineImgPath, width: 36),
4.sizeBoxH,
Text(
"${model.amount}金币",
style: const TextStyle(color: Colors.white, fontSize: 14),
),
4.sizeBoxH,
Text(
'¥${model.moneyYuan}',
style: const TextStyle(
color: Color(0xffF9C142), fontWeight: FontWeight.w500),
),
4.sizeBoxH,
],
),
),
// 左上角优惠角标
if (couponDesc?.isNotEmpty == true)
Positioned(
top: 0,
left: 0,
child: Container(
height: 20,
padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 5),
decoration: const BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
bottomRight: Radius.circular(12)),
color: Color(0xffFFD460),
),
child: Text(
couponDesc!,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
color: Color(0xff292929),
fontWeight: FontWeight.w500,
height: 1,
fontSize: 10.0,
),
),
),
),
],
),
);
}
}
@@ -0,0 +1,266 @@
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:hgdj/assets_tool/app_colors.dart';
import 'package:hgdj/assets_tool/images.dart';
import 'package:hgdj/hj_utils/screen.dart';
import 'package:hgdj/hj_utils/widget_util.dart';
import 'package:hgdj/routers/jump_router.dart';
import 'package:hgdj/tools_base/global_store/store.dart';
import 'package:hgdj/tools_base/loading/loading_center_widget.dart';
import 'package:provider/provider.dart';
import 'package:hgdj/tools_base/widget/sheet_handle_bar.dart';
import '../../make_money/mine_withdrawal_record_page.dart';
import '../mine_charge_coin_logic.dart';
import '../pay_order_source.dart';
import 'coin_item.dart';
/// 金币支付底部弹窗(按设计稿:余额卡片 + 档位网格 + 立即支付)
class CoinPayBottomSheet extends StatelessWidget {
/// 下单来源,默认播放页底部弹窗——本弹窗只在播放页(购买弹窗/解锁蒙层)用
final PaySourcePage sourcePage;
/// 下单埋点上下文(短剧付费墙充金币要带剧/集/付费墙上下文)
final PayOrderTrackInfo? orderTrack;
const CoinPayBottomSheet(
{super.key,
this.sourcePage = PaySourcePage.videoBottomSheet,
this.orderTrack});
/// 弹窗展示中,防连点叠多个 bottomSheet
static bool _isShowing = false;
static Future<T?> show<T>({
PaySourcePage sourcePage = PaySourcePage.videoBottomSheet,
PayOrderTrackInfo? orderTrack,
}) async {
if (_isShowing) return null;
_isShowing = true;
try {
return await Get.bottomSheet<T>(
CoinPayBottomSheet(sourcePage: sourcePage, orderTrack: orderTrack),
isScrollControlled: true,
backgroundColor: Colors.transparent,
);
} finally {
_isShowing = false;
}
}
@override
Widget build(BuildContext context) {
return GetBuilder<MineChargeCoinLogic>(
init: MineChargeCoinLogic(sourcePage: sourcePage, orderTrack: orderTrack),
global: false,
builder: (logic) {
// Material 填深色底:圆角抗锯齿对着 #040018,避免透明底导致左右上角异色
return Material(
color: const Color(0xff040018),
borderRadius: const BorderRadius.vertical(top: Radius.circular(18)),
clipBehavior: Clip.antiAlias,
child: Container(
constraints: BoxConstraints(maxHeight: Get.height * 0.85),
decoration: const BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topCenter,
end: Alignment.bottomCenter,
colors: [Color(0xff040018), Color(0xff060606)],
),
),
child: Stack(
children: [
// 顶部径向黄光:#FACC15 16% → 0%
const Positioned.fill(
child: DecoratedBox(
decoration: BoxDecoration(
gradient: RadialGradient(
center: Alignment.topCenter,
radius: 1.2,
colors: [
Color(0x29FACC15), // #FACC15 @ 16%
Color(0x00FACC15), // #FACC15 @ 0%
],
),
),
),
),
SafeArea(
top: false,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
12.sizeBoxH,
const SheetHandleBar(),
16.sizeBoxH,
const Text(
'金币支付',
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.w600,
),
),
16.sizeBoxH,
Flexible(child: _buildBody(logic)),
_buildBottomBar(logic),
],
),
),
],
),
),
);
},
);
}
Widget _buildBody(MineChargeCoinLogic logic) {
if (logic.isInitLoading) {
return const SizedBox(height: 220, child: LoadingCenterWidget());
}
if (logic.model?.list?.isEmpty != false) {
return SizedBox(
height: 220,
child: CErrorWidget(retryOnTap: () => logic.loadData()),
);
}
return SingleChildScrollView(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
children: [
_buildWallet(),
16.sizeBoxH,
GridView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 12,
crossAxisSpacing: 6,
childAspectRatio: 111 / 138,
),
itemCount: logic.model!.list!.length,
itemBuilder: (context, index) {
final model = logic.model!.list![index];
final isSelected = logic.selectedCoin?.id == model.id;
return CoinItem(
model,
isSelected: isSelected,
onTap: () => logic.onSelectCoin(index),
);
},
),
18.sizeBoxH,
],
),
);
}
/// 我的金币余额卡片
Widget _buildWallet() {
return Container(
alignment: Alignment.centerLeft,
padding: const EdgeInsets.fromLTRB(16, 14, 16, 14),
decoration: BoxDecoration(
color: Colors.white.withValues(alpha: 0.1),
borderRadius: BorderRadius.circular(8),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'我的金币余额',
style: TextStyle(
color: Colors.white, fontSize: 14, fontWeight: FontWeight.w500),
),
8.sizeBoxH,
Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Image.asset('coin_icon.webp'.mineImgPath, width: 36),
4.sizeBoxW,
Consumer<GlobalStore>(
builder: (_, store, __) {
final wallet = store.wallet;
final total = (wallet?.amount ?? 0) + (wallet?.income ?? 0);
return Text(
'$total',
style: const TextStyle(
color: Color(0xffFFD460),
fontSize: 32,
fontWeight: FontWeight.w600,
),
);
},
),
const Spacer(),
InkWell(
enableFeedback: false,
onTap: () =>
Get.to(RecordsPage(RecordType.bill), opaque: false),
child: Container(
alignment: Alignment.center,
height: 30,
width: 90,
decoration: BoxDecoration(
color: const Color(0xffFFD460),
borderRadius: BorderRadius.circular(999),
),
child: const Text(
'余额明细',
style: TextStyle(color: Color(0xff3D3D3D), fontSize: 14),
),
),
),
],
),
],
),
);
}
/// 立即支付 + 在线客服
Widget _buildBottomBar(MineChargeCoinLogic logic) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
GestureDetector(
onTap: () => logic.onGotoPay(),
child: Container(
height: 44,
margin: const EdgeInsets.symmetric(horizontal: 16),
decoration: BoxDecoration(
color: AppColors.actionRed,
borderRadius: BorderRadius.circular(6),
),
alignment: Alignment.center,
child: Text(
'¥${logic.selectedCoin?.moneyYuan ?? 0}/立即支付',
style: const TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.w500,
),
),
),
),
12.sizeBoxH,
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text('支付问题反馈,点击联系 ',
style: textStyle(12, const Color(0xffBFBFC1), FontWeight.w400)),
GestureDetector(
onTap: pushToCustomService,
child: Text('在线客服',
style:
textStyle(12, const Color(0xffFFD460), FontWeight.w400)),
),
],
),
16.sizeBoxH,
],
);
}
}