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 { 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 { 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; } }