diff --git a/assets/images/live_error_icon.png b/assets/images/live_error_icon.png new file mode 100644 index 0000000..d23bb52 Binary files /dev/null and b/assets/images/live_error_icon.png differ diff --git a/lib/controller/discover/room_controller.dart b/lib/controller/discover/room_controller.dart index d5da128..d026211 100644 --- a/lib/controller/discover/room_controller.dart +++ b/lib/controller/discover/room_controller.dart @@ -1,8 +1,10 @@ +import 'dart:async'; import 'dart:convert'; import 'package:agora_rtc_engine/agora_rtc_engine.dart'; import 'package:dating_touchme_app/config/env_config.dart'; import 'package:dating_touchme_app/controller/global.dart'; +import 'package:dating_touchme_app/controller/message/conversation_controller.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'; @@ -17,6 +19,7 @@ import 'package:dating_touchme_app/model/rtc/rtc_channel_data.dart'; import 'package:dating_touchme_app/model/rtc/rtc_channel_detail.dart'; import 'package:dating_touchme_app/network/network_service.dart'; import 'package:dating_touchme_app/pages/mine/edit_info_page.dart'; +import 'package:dating_touchme_app/pages/mine/login_page.dart'; import 'package:dating_touchme_app/pages/setting/match_league_page.dart'; import 'package:dating_touchme_app/rtc/rtc_manager.dart'; import 'package:dating_touchme_app/rtc/rtm_manager.dart'; @@ -479,6 +482,47 @@ class RoomController extends GetxController with WidgetsBindingObserver { final sseClient = SSEClient(); + logout() async { + // 退出直播间 + if (Get.isRegistered()) { + try { + final roomController = Get.find(); + await roomController.leaveChannel(); + } catch (e) { + print('退出直播间失败: $e'); + } + } + + // 取消小窗口 + if (Get.isRegistered()) { + try { + final overlayController = Get.find(); + overlayController.hide(); // 隐藏直播房间小窗 + overlayController.hideVideoCall(); // 隐藏视频通话小窗 + } catch (e) { + print('取消小窗口失败: $e'); + } + } + + // 先退出 IM 登录 + if(IMManager.instance.isInitialized){ + await IMManager.instance.logout(); + } + // 清除会话列表和用户信息缓存 + if (Get.isRegistered()) { + final conversationController = Get.find(); + conversationController.clearConversations(); + } + // App清除本地存储,有待处理, + // storage.erase(); + GetStorage().remove('userId'); + GetStorage().remove('token'); + // storage.write('hasAgreedUserAgreement', true); + // 清除全局数据 + GlobalData().logout(); + } + + final count = 3.obs; /// 调用接口创建 RTC 频道 Future createRtcChannel() async { if (isLive.value) { @@ -524,7 +568,206 @@ class RoomController extends GetxController with WidgetsBindingObserver { final Stream stream = sseClient.connect("connectionId", request); stream.listen( (SSEResponse response) { - print("Received event: ${response.event}, data: ${response.data}"); + print("sseData: ${response.rawResponse}"); + String raw = response.rawResponse; + if (raw.startsWith("data:")) { + String result = raw.substring(5); + print(result); + Map data = jsonDecode(result); + print(data["data"]["illegalLabel"]); + if(data["data"]["illegalHandle"] == 1){ + RTCManager.instance.publishAudio(); + + + // 隐藏 overlay + if(!isDialogShowing.value){ + SmartDialog.dismiss(); + setDialogDismiss(true); + + + + SmartDialog.show( + onDismiss: (){ + setDialogDismiss(false); + }, + builder: (context) { + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(16.w)), + child: Material( + color: Colors.white, + child: Container( + width: 311.w, + height: 275.w, + padding: EdgeInsets.only( + top: 25.w, + right: 25.w, + left: 25.w + ), + child: Column( + children: [ + Image.asset( + Assets.imagesLiveErrorIcon, + width: 102.w, + height: 102.w, + ), + SizedBox(height: 5.w,), + Text( + "系统提醒", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18.w, + fontWeight: FontWeight.w700 + ), + ), + SizedBox(height: 7.w,), + Text( + "你的行为涉嫌违反平台社区规范,请注意规范言行。多次违规将会受到限制功能、封禁账号等处罚,请文明交友,理性互动。", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.w + ), + ), + SizedBox(height: 14.w,), + Container( + width: 188.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( + fontSize: 14.w, + color: Colors.white + ), + ), + ), + ).onTap(() { + + // 隐藏 overlay + SmartDialog.dismiss(); + setDialogDismiss(false); + }) + ], + ), + ), + ), + ); + }, + ); + } + } else if(data["data"]["illegalHandle"] == 2){ + SmartDialog.dismiss(); + setDialogDismiss(true); + + Future.delayed(Duration(seconds: 3), () async { + + SmartDialog.dismiss(); + + final isNotBroadcaster = currentRole != CurrentRole.broadcaster; + if (isNotBroadcaster) { + await leaveChannel(); + // 调用 LiveChatMessageService 处理结束直播消息 + LiveChatMessageService.instance.handleEndLiveMessage(); + logout(); + Get.offAll(() => LoginPage()); + } else { + if(isClose.value) return; + isClose.value = true; + await leaveChannel(); + SmartDialog.dismiss(); + if (Get.isRegistered()) { + final roomController = Get.find(); + roomController.chatMessages.clear(); + } + // 如果还没有执行 pop,手动调用 Get.back() + + final OverlayController _overlayController = Get.find(); + // 等待页面关闭后再显示小窗口,确保小窗口能正确显示 + Future.delayed(const Duration(milliseconds: 200), () { + _overlayController.hide(); + isClose.value = false; + }); + + logout(); + Get.offAll(() => LoginPage()); + + } + }); + Timer? _timer; + _timer = Timer.periodic(Duration(seconds: 1), (timer) { + count.value --; + update(); + // 👇 你的终止条件 + if (count.value == 0) { + print("满足条件,停止执行"); + timer.cancel(); // 停止 + } + }); + + SmartDialog.show( + onDismiss: (){ + setDialogDismiss(false); + _timer?.cancel(); + }, + builder: (context) { + return ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(16.w)), + child: Material( + color: Colors.white, + child: Container( + width: 311.w, + height: 275.w, + padding: EdgeInsets.only( + top: 25.w, + right: 25.w, + left: 25.w + ), + child: Column( + children: [ + Image.asset( + Assets.imagesLiveErrorIcon, + width: 102.w, + height: 102.w, + ), + SizedBox(height: 5.w,), + Text( + "账户封禁", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18.w, + fontWeight: FontWeight.w700 + ), + ), + SizedBox(height: 7.w,), + Text( + "你的账号因 涉嫌违规,已被封禁。", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.w + ), + ), + SizedBox(height: 14.w,), + Obx((){ + return Text( + "${count.value}秒后返回到登录界面", + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 14.w + ), + ); + }), + ], + ), + ), + ), + ); + }, + ); + } + } }, onError: (error) => print("SSE Error: $error"), onDone: () => print("SSE Connection Closed"), diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index 030d8da..1d8f134 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -142,6 +142,7 @@ class Assets { static const String imagesLikeActive = 'assets/images/like_active.png'; static const String imagesLikeIcon = 'assets/images/like_icon.png'; static const String imagesLimitTime = 'assets/images/limit_time.png'; + static const String imagesLiveErrorIcon = 'assets/images/live_error_icon.png'; static const String imagesLiveIcon = 'assets/images/live_icon.png'; static const String imagesLocationIcon = 'assets/images/location_icon.png'; static const String imagesLoginBg = 'assets/images/login_bg.png'; diff --git a/lib/widget/live/draggable_overlay_widget.dart b/lib/widget/live/draggable_overlay_widget.dart index 062a41f..d29b493 100644 --- a/lib/widget/live/draggable_overlay_widget.dart +++ b/lib/widget/live/draggable_overlay_widget.dart @@ -3,8 +3,11 @@ import 'package:dating_touchme_app/controller/discover/room_controller.dart'; import 'package:dating_touchme_app/controller/overlay_controller.dart'; import 'package:dating_touchme_app/extension/ex_widget.dart'; import 'package:dating_touchme_app/pages/discover/live_room_page.dart'; +import 'package:dating_touchme_app/pages/discover/settlement_page.dart'; +import 'package:dating_touchme_app/service/live_chat_message_service.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:dating_touchme_app/rtc/rtc_manager.dart'; @@ -172,8 +175,36 @@ class _DraggableOverlayWidgetState extends State { right: 2.w, child: GestureDetector( onTap: () async { - await _roomController.leaveChannel(); - widget.onClose?.call(); + try { + final isNotBroadcaster = _roomController.currentRole != CurrentRole.broadcaster; + if (isNotBroadcaster) { + await _roomController.leaveChannel(); + // 调用 LiveChatMessageService 处理结束直播消息 + LiveChatMessageService.instance.handleEndLiveMessage(); + } else { + if(_roomController.isClose.value) return; + _roomController.isClose.value = true; + widget.onClose?.call(); + 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.to(() => SettlementPage()); + // 等待页面关闭后再显示小窗口,确保小窗口能正确显示 + Future.delayed(const Duration(milliseconds: 200), () { + _overlayController.hide(); + _roomController.isClose.value = false; + }); + } + + } catch (e){ + _roomController.isClose.value = false; + } }, child: Container( width: 20.w,