import 'package:dating_touchme_app/controller/discover/room_controller.dart'; import 'package:dating_touchme_app/controller/global.dart'; import 'package:dating_touchme_app/controller/overlay_controller.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/generated/assets.dart'; import 'package:dating_touchme_app/model/live/live_chat_message.dart'; import 'package:dating_touchme_app/model/rtc/rtc_channel_detail.dart'; import 'package:dating_touchme_app/network/user_api.dart'; import 'package:dating_touchme_app/pages/discover/live_end_page.dart'; import 'package:dating_touchme_app/pages/discover/settlement_page.dart'; import 'package:dating_touchme_app/widget/live/disconnect_mic_dialog.dart'; import 'package:dating_touchme_app/widget/live/kick_list.dart'; import 'package:dating_touchme_app/widget/live/live_gift_popup.dart'; import 'package:dating_touchme_app/widget/live/live_room_user_profile_dialog.dart'; import 'package:easy_refresh/easy_refresh.dart'; import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:flutter_smart_dialog/flutter_smart_dialog.dart'; import 'package:get/get.dart'; import 'package:tdesign_flutter/tdesign_flutter.dart'; /// 直播间顶部用户信息与操作区域 class LiveRoomUserHeader extends StatelessWidget { const LiveRoomUserHeader({ super.key, required this.userName, required this.popularityText, this.avatarAsset = Assets.imagesUserAvatar, this.fireIconAsset = Assets.imagesFireIcon, this.closeIconAsset = Assets.imagesCloseArrow, this.onFollowTap, this.onCloseTap, }); final String userName; final String popularityText; final String avatarAsset; final String fireIconAsset; final String closeIconAsset; final VoidCallback? onFollowTap; final VoidCallback? onCloseTap; void _showGiftPopupForUser(RtcSeatUserInfo? userInfo, int type) async { // 获取 RoomController 判断当前用户角色 final _roomController = Get.find(); if (userInfo == null) { return; } // 获取目标用户ID(优先使用userId,如果没有则使用miId) final targetUserId = userInfo.uid; if (targetUserId == null) { SmartDialog.showToast('用户ID不存在'); return; } // 刷新玫瑰数量 await _roomController.getVirtualAccount(); // 创建必要的 ValueNotifier final activeGift = ValueNotifier(null); final giftNum = ValueNotifier(1); _roomController.setDialogDismiss(true); SmartDialog.show( alignment: Alignment.bottomCenter, maskColor: Colors.black.withOpacity(0.5), onDismiss: (){ _roomController.setDialogDismiss(false); }, builder: (context) { return Obx(() { // 获取礼物列表 final giftProducts = _roomController.giftProducts; final giftList = giftProducts.toList(); return LiveGiftPopup( activeGift: activeGift, giftNum: giftNum, giftList: giftList, changeActive: (index) { activeGift.value = index; }, type: type, showHeader: false, // 不显示头部 targetUserId: targetUserId, // 设置目标用户ID ); }); }, ); } @override Widget build(BuildContext context) { // 获取 RoomController 判断当前用户角色 final roomController = Get.find(); final overlayController = Get.find(); final isHost = roomController.currentRole == CurrentRole.broadcaster; return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( height: 40.w, padding: EdgeInsets.symmetric(horizontal: 3.w), margin: EdgeInsets.only(left: 10.w), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(40.w)), color: const Color.fromRGBO(0, 0, 0, .25), ), child: Row( children: [ // 支持网络图片和本地资源 ClipOval( child: Image.network( avatarAsset, width: 34.w, height: 34.w, fit: BoxFit.cover, errorBuilder: (context, error, stackTrace) { return Image.asset( Assets.imagesUserAvatar, width: 34.w, height: 34.w, ); }, ), ).onTap(() async { // 检查是否是当前用户自己的消息 final currentUserId = GlobalData().userId ?? GlobalData().userData?.id; if (currentUserId != null && currentUserId == roomController.rtcChannelDetail .value?.anchorInfo?.userId) { // 是自己的头像,不显示弹框 return; } try { final _userApi = Get.find(); final response = await _userApi.getDongwoMarriageInformationDetail(miId: roomController.rtcChannelDetail .value?.anchorInfo?.miId ?? ""); if (response.data.isSuccess && response.data.data != null) { // 不是自己的消息,显示用户资料对话框 showUserProfileDialog( context, LiveChatMessage( userId: roomController.rtcChannelDetail .value?.anchorInfo?.userId ?? "", uid: roomController.rtcChannelDetail .value?.anchorInfo?.uid, userName: roomController.rtcChannelDetail .value?.anchorInfo?.nickName ?? "", avatar: roomController.rtcChannelDetail .value?.anchorInfo?.profilePhoto, miId: roomController.rtcChannelDetail .value?.anchorInfo?.miId, content: "", timestamp: 0 ), (int type) => _showGiftPopupForUser(roomController.rtcChannelDetail .value?.anchorInfo, type), response.data.data! ); } else { // 响应失败,设置错误信息 final errorMsg = response.data.message ?? '获取数据失败'; SmartDialog.showToast(errorMsg); } } catch(e, stackTrace){ print('获取用户信息失败: $e'); print('堆栈跟踪: $stackTrace'); SmartDialog.showToast('获取用户信息失败,请稍后重试'); // 不再 rethrow,避免导致闪退 } }), SizedBox(width: 7.w), Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.center, children: [ Text( userName, style: TextStyle(fontSize: 13.w, color: Colors.white), ), ], ), ], ), ), Row( children: [ // 只有主持人才显示直播设置按钮 if (false && isHost) GestureDetector( onTap: () { roomController.setDialogDismiss(true); SmartDialog.showAttach( targetContext: context, onDismiss: (){ roomController.setDialogDismiss(false); }, builder: (context) { // 判断是否有嘉宾在连麦 final hasGuests = roomController.rtcChannelDetail.value?.maleInfo != null || roomController.rtcChannelDetail.value?.femaleInfo != null; return Container( width: 110.w, margin: EdgeInsets.only(left: 160.w), padding: EdgeInsets.symmetric(horizontal: 10.w), decoration: BoxDecoration( color: Colors.black.withAlpha(80), borderRadius: BorderRadius.all(Radius.circular(10.w)), ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ SizedBox(height: 15.w), // 只有当有嘉宾在连麦时才显示"解除连麦"选项 GestureDetector( onTap: () async { roomController.audienceList.clear(); await roomController.getAudienceList(null); // 隐藏键盘 FocusScope.of(context).unfocus(); // 隐藏 overlay SmartDialog.dismiss(); roomController.setDialogDismiss(true); SmartDialog.show( alignment: Alignment.bottomCenter, maskColor: TDTheme.of(context).fontGyColor2, onDismiss: (){ roomController.setDialogDismiss(false); }, builder: (_) { return KickList(); }, ); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Image.asset( Assets.imagesGetOutIcon, width: 15.w, ), SizedBox(width: 5.w), Text( '踢出直播间', style: TextStyle( color: Colors.white, fontSize: 13.sp, ), ), ], ), ), SizedBox(height: 15.w), if (hasGuests) GestureDetector( onTap: () { // 关闭设置弹窗 SmartDialog.dismiss(); // 弹出解除连麦对话框 roomController.setDialogDismiss(true); SmartDialog.show( onDismiss: (){ roomController.setDialogDismiss(false); }, builder: (context) { return DisconnectMicDialog(); }, ); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Image.asset( Assets.imagesMicOff, width: 15.w, ), SizedBox(width: 5.w), Text( '解除连麦', style: TextStyle( color: Colors.white, fontSize: 13.sp, ), ), ], ), ), if (hasGuests) SizedBox(height: 15.w), GestureDetector( onTap: () async { await roomController.getDurationMins(); // 隐藏 overlay SmartDialog.dismiss(); SmartDialog.show( onDismiss: (){ roomController.setDialogDismiss(false); }, builder: (context) { return ClipRRect( borderRadius: BorderRadius.all(Radius.circular(16.w)), child: Material( color: Colors.white, child: Container( width: 311.w, height: 189.w, padding: EdgeInsets.symmetric( vertical: 20.w, horizontal: 27.w ), child: Column( children: [ Text( "您当前正在视频相亲中\n" "确定要退出吗?", textAlign: TextAlign.center, style: TextStyle( fontSize: 18.w ), ), Container( margin: EdgeInsets.only(top: 9.w, bottom: 18.w), height: 23.w, decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.centerLeft, // 90deg = 从左到右 end: Alignment.centerRight, colors: [ Color.fromRGBO(117, 98, 249, 0), Color.fromRGBO(117, 98, 249, 0.2), Color.fromRGBO(117, 98, 249, 0.2), Color.fromRGBO(117, 98, 249, 0.2), Color.fromRGBO(117, 98, 249, 0), ], stops: [ 0.0, 0.2931, 0.5389, 0.7708, 1.0, ], ), ), child: Center( child: Text( "本场有效露脸开播时长${roomController.durationMins.value}分钟", style: TextStyle( fontSize: 12.w, color: const Color.fromRGBO(117, 98, 249, 1) ), ), ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Container( width: 128.w, height: 40.w, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12.w)), color: const Color.fromRGBO(237, 237, 237, 1) ), child: Center( child: Text( "取消", style: TextStyle( fontSize: 15.w, fontWeight: FontWeight.w400 ), ), ), ).onTap(() { SmartDialog.dismiss(); }), Container( width: 128.w, height: 40.w, decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(12.w)), color: const Color.fromRGBO(117, 98, 249, 1) ), child: Center( child: Text( "确认", style: TextStyle( color: Colors.white, fontSize: 15.w, fontWeight: FontWeight.w400 ), ), ), ).onTap(() async { // 退出房间时清空RTM消息 await roomController.leaveChannel(); await roomController.getLiveData(); await roomController.getLiveIncome(); SmartDialog.dismiss(); if (Get.isRegistered()) { final roomController = Get.find(); roomController.chatMessages.clear(); } // 如果还没有执行 pop,手动调用 Get.back() Get.off(() => SettlementPage()); // 等待页面关闭后再显示小窗口,确保小窗口能正确显示 Future.delayed(const Duration(milliseconds: 200), () { overlayController.hide(); }); }), ], ) ], ), ), ), ); }, ); }, child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Image.asset( Assets.imagesExitRoom, width: 15.w, ), SizedBox(width: 5.w), Text( '结束直播', style: TextStyle( color: Colors.white, fontSize: 13.sp, ), ), ], ), ), SizedBox(height: 15.w), ], ), ); }, ); }, child: Container( height: 30.w, padding: EdgeInsets.symmetric(horizontal: 5.w), margin: EdgeInsets.only(right: 15.w), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30.w)), color: const Color.fromRGBO(0, 0, 0, .3), border: Border.all( color: const Color.fromRGBO(255, 255, 255, .3), width: 1.w, ), ), child: Row( children: [ Icon( Icons.settings_rounded, color: Colors.white, size: 18.w, ), Text( '直播设置', style: TextStyle(color: Colors.white, fontSize: 13.sp), ), Icon( Icons.keyboard_arrow_down_sharp, color: Colors.white, size: 18.w, ), ], ), ), ), GestureDetector( onTap: onCloseTap, child: Container( width: 30.w, height: 30.w, margin: EdgeInsets.only(right: 15.w), decoration: BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(30.w)), color: const Color.fromRGBO(0, 0, 0, .3), ), child: Center( child: Image.asset(closeIconAsset, width: 14.w, height: 14.w), ), ), ), ], ), ], ); } }