// +---------------------------------------------------------------------- declare (strict_types = 1); namespace addon\wxchat\controller\member; use addon\wxchat\model\WxchatRoom; use addon\wxchat\model\WxchatRoomMember; use addon\wxchat\model\WxchatRoomMic; use think\facade\Db; use think\facade\Request; use ywxapp\controller\FrontendBase; /** * 语音 / 视频房:创建 / 加入 / 麦位管理 / 弹幕开关 * 房间公屏聊天复用 group 消息通道(session_id = room_id) */ class Room extends FrontendBase { /** * 房间列表(直播中按热度) */ public function lists() { $type = (int) Request::get('type', 0); $query = WxchatRoom::where('status', 1); if ($type) { $query->where('type', $type); } $list = $query->order('hot', 'desc')->order('create_at', 'desc') ->paginate(20, false, ['page' => (int) Request::get('page', 1)]); $this->success([ 'list' => $list->items(), 'total' => $list->total(), 'pages' => $list->lastPage(), ]); } /** * 创建房间(自动初始化麦位 + 房主上 0 号麦) */ public function create() { $uid = $this->auth->uid; $title = trim((string) Request::post('title', '')); $type = (int) Request::post('type', 1); $cover = trim((string) Request::post('cover', '')); $notice = trim((string) Request::post('notice', '')); $micCount = max(2, min(20, (int) Request::post('mic_count', 8))); if (! $title) { $this->error('请填写房间标题'); } $room = new WxchatRoom(); $room->title = $title; $room->type = $type; $room->owner_uid = $uid; $room->cover = $cover; $room->notice = $notice; $room->mic_count = $micCount; $room->danmaku_on = 1; $room->status = 1; $room->create_at = time(); $room->save(); // 初始化麦位 $mics = []; for ($i = 0; $i < $micCount; $i++) { $mics[] = [ 'room_id' => $room->id, 'mic_index' => $i, 'uid' => $i == 0 ? $uid : 0, 'status' => $i == 0 ? 1 : 0, 'create_at' => time(), ]; } (new WxchatRoomMic())->saveAll($mics); // 房主进入 $member = new WxchatRoomMember(); $member->room_id = $room->id; $member->uid = $uid; $member->role = 1; // 主播 $member->join_at = time(); $member->save(); $this->success(['room_id' => $room->id], '开播成功'); } /** * 进入房间(观众) */ public function join() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); $room = WxchatRoom::where('id', $roomId)->where('status', 1)->find(); if (! $room) { $this->error('房间不存在或已关闭'); } if (! WxchatRoomMember::where('room_id', $roomId)->where('uid', $uid)->find()) { $member = new WxchatRoomMember(); $member->room_id = $roomId; $member->uid = $uid; $member->role = 0; $member->join_at = time(); $member->save(); $room->where('id', $roomId)->inc('hot')->update(); } $mics = WxchatRoomMic::where('room_id', $roomId)->order('mic_index')->select(); $this->success([ 'room' => $room, 'mics' => $mics, ]); } /** * 离开房间 */ public function leave() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); WxchatRoomMember::where('room_id', $roomId)->where('uid', $uid)->delete(); // 释放麦位 WxchatRoomMic::where('room_id', $roomId)->where('uid', $uid)->update(['uid' => 0, 'status' => 0]); $room = WxchatRoom::find($roomId); if ($room && $room->owner_uid == $uid) { $room->status = 0; $room->save(); } $this->success([], '已离开'); } /** * 上麦 */ public function micUp() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); $micIdx = (int) Request::post('mic_index', 0); $mic = WxchatRoomMic::where('room_id', $roomId)->where('mic_index', $micIdx)->find(); if (! $mic) { $this->error('麦位不存在'); } if ($mic->status == 2) { $this->error('该麦位已锁定'); } if ($mic->status == 1 && $mic->uid != $uid) { $this->error('麦位已被占用'); } $mic->uid = $uid; $mic->status = 1; $mic->save(); $this->success([], '上麦成功'); } /** * 下麦 */ public function micDown() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); $micIdx = (int) Request::post('mic_index', 0); $mic = WxchatRoomMic::where('room_id', $roomId)->where('mic_index', $micIdx)->where('uid', $uid)->find(); if (! $mic) { $this->error('你不在该麦位'); } $mic->uid = 0; $mic->status = 0; $mic->save(); $this->success([], '下麦成功'); } /** * 锁定 / 解锁 / 禁麦(房主) */ public function micManage() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); $micIdx = (int) Request::post('mic_index', 0); $op = (int) Request::post('op', 2); // 2锁定 0解锁 3禁麦 $room = WxchatRoom::find($roomId); if (! $room || $room->owner_uid != $uid) { $this->error('仅房主可操作'); } WxchatRoomMic::where('room_id', $roomId)->where('mic_index', $micIdx) ->update(['status' => $op, 'uid' => $op == 0 ? 0 : Db::raw('uid')]); $this->success([], '操作成功'); } /** * 弹幕开关(房主房间级 / 或用户快捷关闭) */ public function danmaku() { $uid = $this->auth->uid; $roomId = (int) Request::post('room_id', 0); $on = (int) Request::post('on', 1); $room = WxchatRoom::find($roomId); if (! $room) { $this->error('房间不存在'); } // 房主可切换房间弹幕总开关;普通用户仅对自己快捷关闭(落到个人设置) if ($room->owner_uid == $uid) { $room->danmaku_on = $on ? 1 : 0; $room->save(); $this->success(['danmaku_on' => $room->danmaku_on], '房间弹幕已' . ($on ? '开启' : '关闭')); } // 非房主:更新个人弹幕总开关(设置-互动-弹幕管理) $pc = \ywxapp\model\MemberProfile::where('uid', $uid)->value('privacy_config'); $pc = $pc ? json_decode($pc, true) : []; $pc = is_array($pc) ? $pc : []; $pc['danmaku_global'] = $on ? 1 : 0; \ywxapp\model\MemberProfile::where('uid', $uid) ->update(['privacy_config' => json_encode($pc, JSON_UNESCAPED_UNICODE)]); $this->success(['danmaku_global' => $on], '个人弹幕已' . ($on ? '开启' : '关闭')); } }