flutter_kinetra/lib/kt_widgets/kt_store_widget.dart
2025-09-23 15:09:18 +08:00

365 lines
14 KiB
Dart

import 'package:flutter/material.dart';
import 'package:flutter_kinetra/kt_model/kt_goods_bean.dart';
import 'package:flutter_kinetra/kt_utils/kt_string_extend.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../kt_model/kt_store_bean.dart';
class KtStoreWidget extends StatefulWidget {
final KtStoreBean store;
final bool onlyCoins;
final bool isStoreDialog;
final void Function(KtGoodsBean goods)? onItemTap; // 新增回调
const KtStoreWidget({
super.key,
required this.store,
this.onItemTap,
this.isStoreDialog = false,
this.onlyCoins = false,
});
@override
State<KtStoreWidget> createState() => _KtStoreWidgetState();
}
class _KtStoreWidgetState extends State<KtStoreWidget> {
int selVip = -1;
int selCoin = -1;
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: initWidget(),
);
}
Widget descView() {
return Text('''
1. Coins are virtual items and cannot be refunded. Use it for this product. \n
2. Gold coins will never expire, the reward coins will expire 24 hours a day.\n
3. Coins will be used first when unlocking episodes. If the amount is insufficient, reward coins will automatically be used. \n
4. The purchase has not been credited, click <Restore> to refresh. \n
5. For other questions, contact us via Profile>Help &feedback.\n
''', style: TextStyle(fontSize: 12.sp, color: Color(0xFF848484),height: 0.95));
}
List<Widget> initWidget() {
// if (widget.onlyCoins) return [coinList()];
List<Widget> widgets = [SizedBox(height: 10.w)];
//
// int coinsIndex = widget.store.sort?.indexOf('list_coins') ?? 0;
// int vipIndex = widget.store.sort?.indexOf('list_sub_vip') ?? 0;
// if (coinsIndex < vipIndex) {
// widgets.addAll([coinList(), SizedBox(height: 15.w), vipList()]);
// } else {
// widgets.addAll([vipList(), SizedBox(height: 15.w), coinList()]);
// }
widgets.addAll([coinList()]);
widgets.addAll([
if (widget.store.payMode == 0 && widget.store.showType == 0)
SizedBox(height: 15.w),
descView(),
]);
return widgets;
}
List<KtGoodsBean> get smallList =>
widget.store.listCoins!.where((item) => item.size == 'small').toList();
List<KtGoodsBean> get bigList =>
widget.store.listCoins!.where((item) => item.size == 'big').toList();
Widget coinList() {
if (widget.store.listCoins?.isEmpty ?? true) return Container();
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
if (!widget.onlyCoins)
Row(
children: [
Text(
'Go Coins',
style: TextStyle(
fontSize: 14.sp,
color:widget.isStoreDialog? Color(0xFF1E1E20):Colors.white,
fontWeight: FontWeight.w600,
),
),
Text(
' | Limited-time coin packs',
style: TextStyle(
fontSize: 14.sp,
color:widget.isStoreDialog? Color(0xFF1E1E20):Colors.white,
fontWeight: FontWeight.w200,
),
),
],
),
SizedBox(height: 10.w),
// big
// if (!onlyNewSubCoins)
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
...bigList.map((item) {
return GestureDetector(
onTap: () {
selCoin = item.id ?? -1;
setState(() {});
widget.onItemTap?.call(item); // 回调
},
child: Stack(
children: [
Container(
width: 167.w,
padding: EdgeInsets.fromLTRB(4.w, 17.w, 5.w, 3.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('coin_big_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'ic_coin.png'.ktIcon,
width: 22.4.w,
),
Text(
'${item.coins ?? 0}',
style: TextStyle(
fontSize: 20.sp,
color: Color(0xFF1E1E20),
fontWeight: FontWeight.w500,
),
),
SizedBox(width: 4.w),
if ((item.sendCoins ?? 0) > 0)
Text(
'+${item.sendCoins}',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Color(0xFFAD8502),
),
),
],
),
SizedBox(height: 6.w),
Container(
width: 160.w,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 6.w),
decoration: BoxDecoration(
color: Color(0xFF1E1E20),
borderRadius: BorderRadius.circular(8.w),
),
child: Text(
'${item.productDetails?.price ?? 0}',
style: TextStyle(
fontSize: 13.sp,
color: Color(0xFFFFD321),
fontWeight: FontWeight.w700,
fontStyle: FontStyle.italic,
),
),
),
],
),
),
if (!item.cornerMarker.isNullString)
Positioned(
top: 4.w,
left: 4.w,
child: Image.asset(
'ic_fire.png'.ktIcon,
width: 16.w,
),
),
if ((item.sendCoins ?? 0) > 0)
Positioned(
right: 0,
top: 0,
child: Container(
width: 42.w,
height: 16.w,
padding: EdgeInsets.symmetric(horizontal: 3.w),
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(0.50, 0.00),
end: Alignment(0.50, 1.00),
colors: [
const Color(0xFFFD9A68),
const Color(0xFFFF538D),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.w),
topRight: Radius.circular(8.w),
bottomLeft: Radius.circular(8.w),
),
),
child: Text(
'+${((item.sendCoins ?? 0) / (item.coins ?? 1) * 100).toInt()}%',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
);
}),
],
),
SizedBox(height: 10.w),
// if (!widget.onlyCoins) subCoinList(),
// small
// if (!onlyNewSubCoins)
GridView.builder(
shrinkWrap: true,
padding: EdgeInsets.zero,
physics: const NeverScrollableScrollPhysics(),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 3,
mainAxisSpacing: 10.w,
crossAxisSpacing: 10.w,
childAspectRatio: 108 / 90,
),
itemBuilder: (_, index) {
var item = smallList[index];
return GestureDetector(
onTap: () {
selCoin = item.id ?? -1;
setState(() {});
widget.onItemTap?.call(item); // 回调
},
child: Stack(
children: [
Container(
width: 108.w,
padding: EdgeInsets.fromLTRB(5.w, 14.w, 5.w, 4.w),
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('coin_small_bg.png'.ktIcon),
fit: BoxFit.fill,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'ic_coin.png'.ktIcon,
width: 22.4.w,
),
Text(
'${item.coins ?? 0}',
style: TextStyle(
fontSize: 20.sp,
color: Color(0xFF1E1E20),
fontWeight: FontWeight.w500,
height: 0.8,
),
),
],
),
if ((item.sendCoins ?? 0) > 0)
Text(
'+${item.sendCoins}',
style: TextStyle(
fontSize: 12.sp,
fontWeight: FontWeight.w500,
color: Color(0xFF499C00),
),
),
],
),
const Spacer(),
Container(
alignment: Alignment.center,
padding: EdgeInsets.symmetric(vertical: 4.w),
decoration: BoxDecoration(
color: Color(0xFF1E1E20),
borderRadius: BorderRadius.circular(8.w),
),
child: Text(
'${item.productDetails?.price ?? 0}',
style: TextStyle(
fontSize: 13.sp,
color: Color(0xFF80FF00),
fontWeight: FontWeight.w700,
fontStyle: FontStyle.italic,
),
),
),
],
),
),
if (!item.cornerMarker.isNullString)
Positioned(
top: 4.w,
left: 4.w,
child: Image.asset('ic_fire.png'.ktIcon, width: 16.w),
),
if ((item.sendCoins ?? 0) > 0)
Positioned(
right: 0,
top: 0,
child: Container(
width: 42.w,
height: 16.w,
padding: EdgeInsets.symmetric(horizontal: 3.w),
alignment: Alignment.center,
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment(0.50, 0.00),
end: Alignment(0.50, 1.00),
colors: [
const Color(0xFFFD9A68),
const Color(0xFFFF538D),
],
),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(8.w),
topRight: Radius.circular(8.w),
bottomLeft: Radius.circular(8.w),
),
),
child: Text(
'+${((item.sendCoins ?? 0) / (item.coins ?? 1) * 100).toInt()}%',
style: TextStyle(
fontSize: 10.sp,
color: Colors.white,
fontWeight: FontWeight.w500,
),
),
),
),
],
),
);
},
itemCount: smallList.length,
),
],
);
}
}