Browse Source

feat(live): 添加直播间被踢出功能和优化RTC连接处理

- 在LiveEndPage中添加isKickedOut和operatorName参数用于显示被踢出信息
- 优化live_room_anchor_showcase中RTC连接逻辑,添加channelId验证
- 添加被踢出用户的小窗口关闭功能,使用OverlayController管理
- 修改踢人逻辑,被踢出用户跳转到结束直播页面并显示相应提示
- 优化踢人API调用和消息发送流程,修复参数传递问题
- 添加连麦卡片获取的日志输出优化
master
Jolie 3 months ago
parent
commit
0dbc7e9f17
3 changed files with 46 additions and 21 deletions
  1. 42
      lib/controller/discover/room_controller.dart
  2. 13
      lib/pages/discover/live_end_page.dart
  3. 12
      lib/widget/live/live_room_anchor_showcase.dart

42
lib/controller/discover/room_controller.dart

@ -2,6 +2,7 @@ import 'dart:convert';
import 'package:agora_rtc_engine/agora_rtc_engine.dart';
import 'package:dating_touchme_app/controller/global.dart';
import 'package:dating_touchme_app/controller/overlay_controller.dart';
import 'package:dating_touchme_app/model/live/gift_product_model.dart';
import 'package:dating_touchme_app/model/rtc/link_mic_card_model.dart';
import 'package:dating_touchme_app/model/rtc/rtc_channel_data.dart';
@ -16,8 +17,8 @@ import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import '../../model/live/live_chat_message.dart';
import '../../pages/discover/live_end_page.dart';
import '../../pages/mine/real_name_page.dart';
import '../../pages/setting/match_league_page.dart';
import '../../pages/setting/match_spread_page.dart';
import 'svga_player_manager.dart';
@ -556,14 +557,26 @@ class RoomController extends GetxController with WidgetsBindingObserver {
final operatorName = message['operatorName']?.toString() ?? '主持人';
print('✅ 收到踢人消息: 被踢用户ID $kickingUId');
//
if (rtcChannel.value?.uid == kickingUId) {
//
if (Get.isRegistered<OverlayController>()) {
try {
final overlayController = Get.find<OverlayController>();
overlayController.hide(); //
} catch (e) {
print('关闭小窗口失败: $e');
}
}
//
SmartDialog.showToast('您已被$operatorName踢出房间');
await leaveChannel();
//
Get.back();
//
Get.off(
() => LiveEndPage(isKickedOut: true, operatorName: operatorName),
);
} else {
//
final channelName = RTCManager.instance.currentChannelId;
@ -596,10 +609,7 @@ class RoomController extends GetxController with WidgetsBindingObserver {
required int kickingUId,
}) async {
try {
final requestData = {
'channelId': channelId,
'kickingUId': kickingUId,
};
final requestData = {'channelId': channelId, 'kickingUId': kickingUId};
final response = await _networkService.rtcApi.kickingRtcChannelUser(
requestData,
@ -607,7 +617,7 @@ class RoomController extends GetxController with WidgetsBindingObserver {
if (response.data.isSuccess) {
SmartDialog.showToast('已踢出用户');
// RTM
final channelName = RTCManager.instance.currentChannelId;
if (channelName != null && channelName.isNotEmpty) {
@ -617,19 +627,19 @@ class RoomController extends GetxController with WidgetsBindingObserver {
'operatorId': GlobalData().userData?.id ?? '',
'operatorName': GlobalData().userData?.nickName ?? '',
};
await RTMManager.instance.publishChannelMessage(
channelName: channelName,
message: json.encode(messageData),
);
print('✅ 踢人消息已发送: 踢出用户ID $kickingUId');
//
await fetchRtcChannelDetail(channelName);
}
} else {
final message = response.data.message.isNotEmpty
? response.data.message
final message = response.data.message.isNotEmpty
? response.data.message
: '踢出用户失败';
SmartDialog.showToast(message);
}
@ -646,7 +656,9 @@ class RoomController extends GetxController with WidgetsBindingObserver {
final base = response.data;
if (base.isSuccess && base.data != null) {
linkMicCard.value = base.data;
print('✅ 获取连麦卡片成功: type=${base.data!.type}, num=${base.data!.num}, unitSellingPrice=${base.data!.unitSellingPrice}');
print(
'✅ 获取连麦卡片成功: type=${base.data!.type}, num=${base.data!.num}, unitSellingPrice=${base.data!.unitSellingPrice}',
);
} else {
linkMicCard.value = null;
print('❌ 获取连麦卡片失败: ${base.message}');

13
lib/pages/discover/live_end_page.dart

@ -8,7 +8,14 @@ import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
class LiveEndPage extends StatelessWidget {
const LiveEndPage({super.key});
final bool isKickedOut; //
final String? operatorName; //
const LiveEndPage({
super.key,
this.isKickedOut = false,
this.operatorName,
});
@override
Widget build(BuildContext context) {
@ -127,7 +134,9 @@ class LiveEndPage extends StatelessWidget {
Padding(
padding: EdgeInsets.symmetric(horizontal: 16.w),
child: Text(
'当前相亲已结束',
isKickedOut
? '您已被${operatorName ?? '主持人'}踢出直播间'
: '当前相亲已结束',
style: TextStyle(
fontSize: 14.w,
color: Colors.white,

12
lib/widget/live/live_room_anchor_showcase.dart

@ -156,8 +156,11 @@ class _LiveRoomAnchorShowcaseState extends State<LiveRoomAnchorShowcase> {
Widget _buildAnchorVideo(bool joined, int? remoteUid) {
final engine = _rtcManager.engine;
final currentChannelId = _rtcManager.currentChannelId;
if (_roomController.rtcChannelDetail.value?.anchorInfo == null ||
engine == null) {
engine == null ||
currentChannelId == null ||
currentChannelId.isEmpty) {
return _buildWaitingPlaceholder();
}
return ClipRRect(
@ -180,7 +183,7 @@ class _LiveRoomAnchorShowcaseState extends State<LiveRoomAnchorShowcase> {
_roomController.rtcChannelDetail.value?.anchorInfo?.uid,
),
connection: RtcConnection(
channelId: _rtcManager.currentChannelId!,
channelId: currentChannelId,
),
),
),
@ -232,7 +235,8 @@ class _LiveRoomAnchorShowcaseState extends State<LiveRoomAnchorShowcase> {
userInfo != null &&
userInfo.uid != null &&
joined &&
engine != null
engine != null &&
(_rtcManager.currentChannelId != null && _rtcManager.currentChannelId!.isNotEmpty)
? Stack(
children: [
AgoraVideoView(
@ -245,7 +249,7 @@ class _LiveRoomAnchorShowcaseState extends State<LiveRoomAnchorShowcase> {
rtcEngine: engine,
canvas: VideoCanvas(uid: userInfo.uid!),
connection: RtcConnection(
channelId: _rtcManager.currentChannelId ?? '',
channelId: _rtcManager.currentChannelId!,
),
),
),

Loading…
Cancel
Save