aslan-flutter/lib/chatvibe_ui/widgets/room/room_task_page.dart
2026-07-01 18:25:58 +08:00

819 lines
30 KiB
Dart

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_smart_dialog/flutter_smart_dialog.dart';
import 'package:aslan/chatvibe_core/constants/at_global_config.dart';
import 'package:aslan/chatvibe_data/sources/repositories/room_repository_imp.dart';
import 'package:marquee/marquee.dart';
import 'package:aslan/app_localizations.dart';
import 'package:aslan/chatvibe_data/sources/local/user_manager.dart';
import 'package:aslan/chatvibe_ui/widgets/room_reward_countdown_timer.dart';
import '../../../chatvibe_data/models/enum/at_task_code_type.dart';
import '../../../chatvibe_data/models/enum/at_vip_type.dart';
import '../../../chatvibe_domain/models/res/at_room_task_list_res.dart';
import '../../components/at_compontent.dart';
import '../../components/at_debounce_widget.dart';
import '../../components/at_tts.dart';
import '../../components/text/at_text.dart';
class RoomTaskPage extends StatefulWidget {
const RoomTaskPage({super.key});
@override
_RoomTaskPageState createState() => _RoomTaskPageState();
}
class _RoomTaskPageState extends State<RoomTaskPage> {
int type = 0;
int taskCategory = 1;
ATRoomTaskListRes? roomTaskListRes;
bool isLoding = true;
//折扣
double disCount = 1.0;
@override
void initState() {
super.initState();
if (AccountStorage().getVIP()?.name == ATVIPType.VISCOUNT.name) {
// disCount = 1.05;
} else if (AccountStorage().getVIP()?.name == ATVIPType.EARL.name) {
// disCount = 1.07;
} else if (AccountStorage().getVIP()?.name == ATVIPType.MARQUIS.name) {
disCount = 1.10;
} else if (AccountStorage().getVIP()?.name == ATVIPType.DUKE.name) {
disCount = 1.15;
} else if (AccountStorage().getVIP()?.name == ATVIPType.KING.name) {
disCount = 1.20;
} else if (AccountStorage().getVIP()?.name == ATVIPType.EMPEROR.name) {
disCount = 1.25;
}
_loadData();
}
@override
Widget build(BuildContext context) {
return SafeArea(
child: Stack(
alignment: Alignment.bottomCenter,
children: [
Container(
height: ScreenUtil().screenHeight * 0.85,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage("atu_images/room/at_icon_room_task_bg.png"),
fit: BoxFit.fill,
),
),
child: Column(
children: [
SizedBox(height: 125.w),
Row(
children: [
Spacer(),
GestureDetector(
child: Image.asset(
"atu_images/room/at_icon_room_reward_help.png",
height: 23.w,
width: 23.w,
),
onTap: () {
SmartDialog.show(
tag: "showRoomTaskRuleDialog",
alignment: Alignment.center,
animationType: SmartAnimationType.fade,
builder: (_) {
return Container(
height: 340.w,
padding: EdgeInsets.symmetric(horizontal: 28.w),
width: ScreenUtil().screenWidth * 0.9,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/room/at_icon_room_task_rule_bg.png",
),
fit: BoxFit.fill,
),
),
child: Column(
children: [
SizedBox(height: 56.w),
text(
ATAppLocalizations.of(
context,
)!.dailyCoinBonanzaRules,
fontSize: 15.sp,
fontWeight: FontWeight.w600,
textColor: Colors.white,
),
SizedBox(height: 35.w),
Expanded(
child: SingleChildScrollView(
child: text(
maxLines: 25,
ATAppLocalizations.of(
context,
)!.dailyCoinBonanzaRulesDetail,
textColor: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w600,
),
),
),
SizedBox(height: 25.w),
],
),
);
},
);
},
),
SizedBox(width: 30.w),
],
),
SizedBox(height: 15.w),
Directionality(
textDirection: TextDirection.ltr,
child: RoomRewardCountdownTimer(
key: UniqueKey(),
targetDate: DateTime.fromMillisecondsSinceEpoch(
roomTaskListRes?.countdown ?? 0,
),
),
),
SizedBox(height: 15.w),
_buildTaskTabs(),
SizedBox(height: 15.w),
Expanded(
child: ListView.separated(
itemCount: roomTaskListRes?.tasks?.length ?? 0, // 列表项数量
padding: EdgeInsets.only(
bottom: 15.w,
left: 20.w,
right: 20.w,
),
itemBuilder: (context, index) {
return _buildTaskItem(
index,
roomTaskListRes?.tasks?[index],
);
},
separatorBuilder: (BuildContext context, int index) {
return SizedBox(height: 10.w);
},
),
),
],
),
),
isLoding
? Container(
color: Colors.transparent,
child: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.black26,
borderRadius: BorderRadius.circular(8),
),
width: 55.w,
height: 55.w,
child: CupertinoActivityIndicator(),
),
),
)
: Container(),
],
),
);
}
void _loadData() {
setState(() {
isLoding = true;
});
ChatRoomRepository()
.roomTaskList(taskCategory)
.then((res) {
roomTaskListRes = res;
isLoding = false;
setState(() {});
})
.catchError((e) {
setState(() {
isLoding = true;
});
});
}
Widget _buildTaskTabs() {
return Padding(
padding: EdgeInsets.symmetric(horizontal: 22.w),
child: Directionality(
textDirection: TextDirection.ltr,
child: Container(
height: 58.w,
decoration: BoxDecoration(
color: Color(0xFF1B1A22),
borderRadius: BorderRadius.circular(4.w),
border: Border.all(color: Color(0xFF9A6A34), width: 1.w),
boxShadow: [
BoxShadow(
color: Colors.black.withValues(alpha: 0.22),
blurRadius: 10.w,
offset: Offset(0, 4.w),
),
],
),
child: ClipRRect(
borderRadius: BorderRadius.circular(3.w),
child: LayoutBuilder(
builder: (context, constraints) {
final double selectedWidth = constraints.maxWidth * 0.56;
return Stack(
children: [
Positioned.fill(
child: IgnorePointer(
child:
type == 0
? Align(
alignment: Alignment.centerLeft,
child: SizedBox(
width: selectedWidth,
child: ClipPath(
clipper: _RoomTaskSelectedTabClipper(
isLeft: true,
),
child: _buildSelectedTaskTabBackground(),
),
),
)
: Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: selectedWidth,
child: ClipPath(
clipper: _RoomTaskSelectedTabClipper(
isLeft: false,
),
child: _buildSelectedTaskTabBackground(),
),
),
),
),
),
Row(
children: [
Expanded(
child: _buildTaskTabItem(
label:
ATAppLocalizations.of(context)!.personalTasks,
selected: type == 0,
onTap: () => _changeTaskTab(0),
margin: EdgeInsets.only(right: 5.w),
textAlign: TextAlign.center,
),
),
Expanded(
child: _buildTaskTabItem(
label:
ATAppLocalizations.of(context)!.roomOwnerTasks,
selected: type == 1,
onTap: () => _changeTaskTab(1),
margin: EdgeInsets.only(left: 5.w),
textAlign: TextAlign.center,
),
),
],
),
],
);
},
),
),
),
),
);
}
Widget _buildSelectedTaskTabBackground() {
return Container(
decoration: const BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFFF3D6AE), Color(0xFFBE8A55)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
);
}
Widget _buildTaskTabItem({
required String label,
required bool selected,
required VoidCallback onTap,
required EdgeInsets margin,
required TextAlign textAlign,
}) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: onTap,
child: Container(
margin: margin,
alignment: Alignment.center,
padding: EdgeInsets.symmetric(horizontal: 10.w),
child: text(
label,
maxLines: 1,
textAlign: textAlign,
fontStyle: FontStyle.italic,
fontSize: 14.sp,
letterSpacing: 0.5,
fontWeight: FontWeight.w700,
textColor: selected ? Color(0xFF2E1C10) : Color(0xFFE9C48B),
),
),
);
}
void _changeTaskTab(int nextType) {
if (type == nextType) {
return;
}
setState(() {
type = nextType;
});
taskCategory = nextType == 0 ? 1 : 2;
_loadData();
}
Widget _buildTaskItem(int index, Tasks? task) {
return Container(
height: 105.w,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/room/at_icon_room_task_list_item_bg.png",
),
fit: BoxFit.fill,
),
),
child: Row(
children: [
SizedBox(width: 18.w),
netImage(url: task?.iconUrl ?? "", height: 35.w, width: 35.w),
SizedBox(width: 3.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(height: 20.w),
Container(
constraints: BoxConstraints(maxWidth: 180.w),
height: 17.w,
child:
"${_getTaskName(task?.taskCode ?? "")}".length > 25
? Marquee(
text: _getTaskName(task?.taskCode ?? ""),
style: TextStyle(
fontSize: 12.sp,
height: 1.11,
color: Colors.white,
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
scrollAxis: Axis.horizontal,
crossAxisAlignment: CrossAxisAlignment.start,
blankSpace: 40.0,
velocity: 40.0,
pauseAfterRound: Duration(seconds: 1),
accelerationDuration: Duration(seconds: 1),
accelerationCurve: Curves.easeOut,
decelerationDuration: Duration(milliseconds: 550),
decelerationCurve: Curves.easeOut,
)
: Text(
_getTaskName(task?.taskCode ?? ""),
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: TextStyle(
fontSize: 12.sp,
color: Colors.white,
fontWeight: FontWeight.w400,
decoration: TextDecoration.none,
),
),
),
SizedBox(height: 8.w),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Container(
padding: EdgeInsetsDirectional.only(end: 18.w),
child: Stack(
children: [
Container(
margin: EdgeInsets.only(top: 3.w),
decoration: BoxDecoration(
color: Colors.white24,
borderRadius: BorderRadius.circular(8.w),
),
height: 8.w,
width: _getProgressWidth(task),
),
Container(
margin: EdgeInsets.only(top: 3.w),
height: 8.w,
width: _getCurrenProgress(task),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xffDD8000), Color(0xffFFFFFF)],
begin: Alignment.centerLeft,
end: Alignment.centerRight,
),
borderRadius: BorderRadius.circular(8.w),
),
),
Container(
margin: EdgeInsetsDirectional.only(start: 3.w),
width: _getProgressWidth(task),
child: Row(
children:
task?.tiers
?.map(
(e) => Expanded(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.end,
children: [
Image.asset(
"atu_images/general/at_icon_jb.png",
width: 15.w,
height: 15.w,
),
Transform.translate(
offset: Offset(
ATGlobalConfig.lang == "ar"
? -10.w
: 10.w,
0,
),
child: text(
"${_getTargetValue(e.targetValue ?? 0)} ${_getTargetUnit(task.taskCode ?? "")}",
fontSize: 9.sp,
textColor: Colors.white,
),
),
Transform.translate(
offset: Offset(
ATGlobalConfig.lang == "ar"
? -(_translateRewardValue(
"+${e.rewardValue}"
.length,
))
: _translateRewardValue(
"+${e.rewardValue}"
.length,
),
0,
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment:
CrossAxisAlignment.end,
children: [
disCount > 1
? text(
"+${e.rewardValue}",
fontSize: 9.sp,
textColor: Color(
0xffFFB627,
),
decoration:
TextDecoration
.lineThrough,
lineHeight: 0.95,
)
: Container(),
text(
"+${((e.rewardValue ?? 0) * disCount + 1e-9).floor()}",
fontSize: 9.sp,
lineHeight: 0.95,
textColor: Color(
0xffFFB627,
),
),
],
),
),
],
),
),
)
.toList() ??
[],
),
),
],
),
),
),
],
),
),
SizedBox(width: 8.w),
Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: 10.w),
_buildReciverTaskBtn(task),
text(
"(${task?.currentValue ?? 0}/${task?.tiers?.last.targetValue ?? 0})",
fontSize: 12.sp,
fontWeight: FontWeight.w600,
textColor: Colors.white,
),
],
),
SizedBox(width: 12.w),
],
),
);
}
_buildReciverTaskBtn(Tasks? task) {
/// 0 go,1 claim,2 completed
int state = 0;
if (task?.currentValue == task?.tiers?.last.targetValue) {
///进度条跑完了
for (int index = 0; index < (task?.tiers ?? []).length; index++) {
Tiers? tier = task?.tiers?[index];
if ((tier?.isCompleted ?? false) && !(tier?.isClaimed ?? false)) {
///已经完成没有领取
state = 1;
break;
} else {
state = 2;
}
}
} else {
for (int index = 0; index < (task?.tiers ?? []).length; index++) {
Tiers? tier = task?.tiers?[index];
if ((tier?.isCompleted ?? false) && !(tier?.isClaimed ?? false)) {
///已经完成没有领取
state = 1;
break;
} else {
state = 0;
}
}
}
if (state == 0) {
return Container(
width: 72.w,
height: 28.w,
alignment: Alignment.center,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/room/at_icon_room_task_list_item_go_btn.png",
),
fit: BoxFit.fill,
),
),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
text(
ATAppLocalizations.of(context)!.go,
textColor: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w600,
),
Icon(
ATGlobalConfig.lang == "ar"
? Icons.keyboard_arrow_left
: Icons.keyboard_arrow_right,
size: 16.w,
color: Colors.white,
),
],
),
);
} else if (state == 1) {
return ATDebounceWidget(
child: Container(
width: 72.w,
height: 28.w,
alignment: Alignment.center,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/room/at_icon_room_task_list_item_act_btn.png",
),
fit: BoxFit.fill,
),
),
child: text(
ATAppLocalizations.of(context)!.claim,
textColor: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w600,
),
),
onTap: () {
_claim(task);
},
);
} else if (state == 2) {
return Container(
width: 72.w,
height: 28.w,
alignment: Alignment.center,
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
"atu_images/room/at_icon_room_task_list_item_complete_btn.png",
),
fit: BoxFit.fill,
),
),
child: text(
ATAppLocalizations.of(context)!.complete,
textColor: Colors.white,
fontSize: 13.sp,
fontWeight: FontWeight.w600,
),
);
}
}
_translateRewardValue(int lenght) {
double ws = 0;
if (lenght == 3) {
ws = 1.w;
} else if (lenght == 4) {
ws = 4.w;
} else if (lenght == 5) {
ws = 5.w;
} else if (lenght == 6) {
ws = 8.w;
} else if (lenght == 7) {
ws = 10.w;
}else if (lenght == 8) {
ws = 12.w;
}
return ws;
}
_getTargetValue(int targetValue) {
if (targetValue >= 1000000) {
return _formatCompactTargetValue(targetValue / 1000000, 'M');
} else if (targetValue >= 1000) {
return _formatCompactTargetValue(targetValue / 1000, 'K');
}
return targetValue.toString();
}
String _formatCompactTargetValue(double value, String suffix) {
final bool hasDecimal = value.truncateToDouble() != value;
final String formatted = value.toStringAsFixed(hasDecimal ? 1 : 0);
return '$formatted$suffix';
}
_getTaskName(String taskCode) {
if (taskCode == ATTaskCodeType.PERSONAL_GAME_CONSUME.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalGameConsume;
} else if (taskCode == ATTaskCodeType.PERSONAL_MIC_IN_ROOM.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalMicInRoom;
} else if (taskCode == ATTaskCodeType.PERSONAL_ACTIVE_IN_ROOM.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalActiveInRoom;
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_MIC_TIME.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOwnerMicTime;
} else if (taskCode == ATTaskCodeType.PERSONAL_LUCKY_GIFT_GOLD.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalLuckyGiftGold;
} else if (taskCode == ATTaskCodeType.PERSONAL_MAGIC_GIFT_GOLD.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalMagicGiftGold;
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_SEND_GIFT_GOLD.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOwnerSendGiftGold;
} else if (taskCode == ATTaskCodeType.ROOM_USER_SEND_GIFT_GOLD.name) {
return ATAppLocalizations.of(context)!.taskNameRoomUserSendGiftGold;
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_INVITE_MIC.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOwnerInviteMic;
} else if (taskCode == ATTaskCodeType.ROOM_ONLINE_USER_COUNT.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOnlineUserCount;
} else if (taskCode == ATTaskCodeType.PERSONAL_SEND_GIFT.name) {
return ATAppLocalizations.of(context)!.taskNamePersonalSendGift;
} else if (taskCode == ATTaskCodeType.ROOM_MIC_USER_30MIN.name) {
return ATAppLocalizations.of(context)!.taskNameRoomMicUser30Min;
} else if (taskCode == ATTaskCodeType.ROOM_MIC_USER_60MIN.name) {
return ATAppLocalizations.of(context)!.taskNameRoomMicUser60Min;
} else if (taskCode == ATTaskCodeType.ROOM_MIC_USER_120MIN.name) {
return ATAppLocalizations.of(context)!.taskNameRoomMicUser120Min;
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_SEND_GIFT_USER.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOwnerSendGiftUser;
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_SEND_RED_PACKET.name) {
return ATAppLocalizations.of(context)!.taskNameRoomOwnerSendRedPacket;
} else if (taskCode == ATTaskCodeType.ROOM_NEW_MEMBER.name) {
return ATAppLocalizations.of(context)!.taskNameRoomNewMember;
}
}
_getTargetUnit(String taskCode) {
if (taskCode == ATTaskCodeType.PERSONAL_GAME_CONSUME.name ||
taskCode == ATTaskCodeType.PERSONAL_LUCKY_GIFT_GOLD.name ||
taskCode == ATTaskCodeType.PERSONAL_MAGIC_GIFT_GOLD.name ||
taskCode == ATTaskCodeType.ROOM_OWNER_SEND_GIFT_GOLD.name ||
taskCode == ATTaskCodeType.ROOM_USER_SEND_GIFT_GOLD.name) {
return "Coins";
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_MIC_TIME.name ||
taskCode == ATTaskCodeType.PERSONAL_MIC_IN_ROOM.name ||
taskCode == ATTaskCodeType.PERSONAL_ACTIVE_IN_ROOM.name) {
return "Min";
} else if (taskCode == ATTaskCodeType.ROOM_OWNER_INVITE_MIC.name ||
taskCode == ATTaskCodeType.ROOM_ONLINE_USER_COUNT.name ||
taskCode == ATTaskCodeType.PERSONAL_SEND_GIFT.name ||
taskCode == ATTaskCodeType.ROOM_MIC_USER_30MIN.name ||
taskCode == ATTaskCodeType.ROOM_MIC_USER_60MIN.name ||
taskCode == ATTaskCodeType.ROOM_MIC_USER_120MIN.name ||
taskCode == ATTaskCodeType.ROOM_OWNER_SEND_GIFT_USER.name ||
taskCode == ATTaskCodeType.ROOM_OWNER_SEND_RED_PACKET.name ||
taskCode == ATTaskCodeType.ROOM_NEW_MEMBER.name) {
return "Member";
}
return "";
}
_getProgressWidth(Tasks? task) {
if ((task?.tiers?.length ?? 0) < 4) {
return ScreenUtil().screenWidth * 0.50;
} else {
return ScreenUtil().screenWidth * 0.50 / 3 * (task?.tiers?.length ?? 0);
}
}
void _claim(Tasks? task) {
ChatRoomRepository()
.roomTaskClaim(task?.taskCode ?? "")
.then((res) {
ATTts.show(ATAppLocalizations.of(context)!.receiveSucc);
_loadData();
})
.catchError((e) {
_loadData();
});
}
_getCurrenProgress(Tasks? task) {
int currentValue = task?.currentValue ?? 0;
var tiers = task?.tiers ?? [];
if (tiers.isEmpty) return 0.0;
// 假设 tiers 已按 targetValue 升序排列
int completedCount = 0;
for (var tier in tiers) {
if (currentValue >= (tier.targetValue ?? 0)) {
completedCount++;
} else {
break;
}
}
// 计算进度:完成的层级数 / 总层级数 * 总宽度
num w = _getProgressWidth(task);
return (w / tiers.length) * completedCount;
}
}
class _RoomTaskSelectedTabClipper extends CustomClipper<Path> {
final bool isLeft;
_RoomTaskSelectedTabClipper({required this.isLeft});
@override
Path getClip(Size size) {
final double cutWidth = 40.w;
final Path path = Path();
if (isLeft) {
path.moveTo(0, 0);
path.lineTo(size.width - cutWidth, 0);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
} else {
path.moveTo(cutWidth, 0);
path.lineTo(size.width, 0);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
}
path.close();
return path;
}
@override
bool shouldReclip(covariant _RoomTaskSelectedTabClipper oldClipper) {
return oldClipper.isLeft != isLeft;
}
}