#include "MainPanel.h" #include #include #include #include #include #include #include #include #include #include "widgets/bubbletip.h" #include "widgets/chatView/chatwindow.h" #include "widgets/maskoverlay.h" #include "widgets/userprofilewidget.h" #include "AvPlayer2/PlayWidget.h" #include "api/roomapi.h" #include "appevent.h" #include "ui/av_recorder.h" MainPanel::MainPanel(QWidget *parent) : QWidget(parent) , userProfile(nullptr) , chatView(nullptr) { // 初始化防抖定时器 m_debounceTimer = new QTimer(this); m_debounceTimer->setSingleShot(true); m_debounceTimer->setInterval(500); // 500ms防抖延迟 connect(m_debounceTimer, &QTimer::timeout, this, &MainPanel::handleDebouncedPlay); // setupUI userProfile = new UserProfileWidget(this); webSocketClient = new WebSocketClient(this); chatView = new ChatWindow(webSocketClient); chatView->setMinimumWidth(400); QWidget *rightWidget = new QWidget; QVBoxLayout *vbox = new QVBoxLayout(rightWidget); vbox->setContentsMargins(0, 0, 0, 0); vbox->addWidget(userProfile, 0); vbox->addWidget(chatView, 1); m_roomListWidget = new QListWidget; splitter = new QSplitter(Qt::Horizontal, this); playerContainer = new QWidget(this); splitter->addWidget(m_roomListWidget); splitter->addWidget(playerContainer); splitter->addWidget(rightWidget); splitter->setStretchFactor(0, 10); splitter->setStretchFactor(1, 60); splitter->setStretchFactor(2, 30); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(splitter, 1); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); setLayout(mainLayout); // initConnect connect(AppEvent::instance(), &AppEvent::connectionStateChanged, this, [this](bool connected) { if (userProfile) { userProfile->setStatus(connected ? "在线" : "离线"); } }); connect(m_roomListWidget, &QListWidget::itemDoubleClicked, this, &MainPanel::roomItemChanged); connect(userProfile, &UserProfileWidget::logoutClicked, this, &MainPanel::logoutClicked); connect(webSocketClient, &WebSocketClient::liveStatus, this, [this](const QString &msg) { // 这里可以处理 liveStatus 相关逻辑 QJsonParseError err; QJsonDocument doc = QJsonDocument::fromJson(msg.toUtf8(), &err); if (err.error != QJsonParseError::NoError || !doc.isObject()) { qDebug() << "[MainPanel] liveStatus: 解析失败" << err.errorString(); return; } QJsonObject obj = doc.object(); int liveStatus = obj.value("liveStatus").toInt(0); // 默认-1 if (liveStatus == 1) { qDebug() << "[MainPanel] liveStatus: 直播中" << chatView; if (chatView) { const QString id = webSocketClient->roomId(); // 使用防抖机制处理频繁的请求 m_pendingRoomId = id; m_debounceTimer->start(); // 重新开始计时,如果在500ms内再次收到请求,会重置定时器 } // 你的处理逻辑 } else if (liveStatus == 2) { qDebug() << "[MainPanel] liveStatus: 未开播"; // 你的处理逻辑 } else { qDebug() << "[MainPanel] liveStatus: 未知状态" << liveStatus; } }); } MainPanel::~MainPanel() { if (userProfile) { delete userProfile; userProfile = nullptr; } } void MainPanel::setRole(const QStringList &roleList) { QWidget *newPlayer = nullptr; if (roleList.contains("role.admin")) { newPlayer = new AvRecorder(this); } else { newPlayer = new PlayWidget(this); } setPlayerWidget(newPlayer); // 如果是管理也就是教师 直接过滤当前教师的选项 if (AppEvent::instance()->hasRole("role.admin")) { // roomInfo.ownerId = AppEvent::instance()->userId(); m_roomListWidget->hide(); } else { m_roomListWidget->show(); } // 设置初始化信息 const QString &name = AppEvent::instance()->userName(); userProfile->setUsername(name); } void MainPanel::setPushRoomId(const QString &id) { // 推流配置 if (AvRecorder *avRecorder = qobject_cast(playerWidget)) { SettingsPage::Param param; param.liveUrl = "rtmp://106.55.186.74:1935/stream/V1"; param.liveName = id.toStdString(); avRecorder->setSettings(param); } // 重新进入房间 chatView->initWebsocket(id); } void MainPanel::setPlayerWidget(QWidget *newPlayer) { if (playerWidget) { playerWidget->setParent(nullptr); playerWidget->deleteLater(); } playerWidget = newPlayer; playerWidget->setParent(playerContainer); QLayout *oldLayout = playerContainer->layout(); if (oldLayout) { QLayoutItem *item; while ((item = oldLayout->takeAt(0)) != nullptr) { if (item->widget()) item->widget()->setParent(nullptr); delete item; } delete oldLayout; } QVBoxLayout *vbox = new QVBoxLayout(playerContainer); vbox->setContentsMargins(0, 0, 0, 0); vbox->addWidget(playerWidget); } void MainPanel::roomItemChanged(QListWidgetItem *item) { if (item) { const QString id = item->data(Qt::UserRole + 100).value(); if (!playerWidget) { return; } // // 推流配置 // if (AvRecorder *avRecorder = qobject_cast(playerWidget)) { // SettingsPage::Param param; // param.liveUrl = "rtmp://106.55.186.74:1935/stream/V1"; // param.liveName = id.toStdString(); // avRecorder->setSettings(param); // } // 拉取视频流程 if (PlayWidget *playWidget = qobject_cast(playerWidget)) { MaskOverlay::instance()->show(nullptr, 0, MaskOverlay::ActiveWindow); QFuture getRoomFuture = getRoomApi(id); QtPromise::QPromise roomListPromise = QtPromise::resolve(getRoomFuture); roomListPromise .then([this, playWidget, id](const HttpResponse &response) { qDebug() << response.code << response.data << response.message; if (response.code != 0) { BubbleTip::showTip(this, response.message, BubbleTip::Top, 3000); return; } RoomInfo roomInfo = JsonMapper::formJsonEx(response.data.toObject()); qDebug() << "roomInfo.liveStatus.has_value()" << roomInfo.liveStatus.has_value(); int status = roomInfo.liveStatus.value_or(0); if (status == 1) { qDebug() << "open" << ("rtmp://106.55.186.74:1935/stream/V1/" + id); playWidget->startToPlay("rtmp://106.55.186.74:1935/stream/V1/" + id); } }) .finally([]() { MaskOverlay::instance()->hide(); }); } } } void MainPanel::handleDebouncedPlay() { // 防抖处理后的播放逻辑 if (m_pendingRoomId.isEmpty() || !chatView) { return; } if (PlayWidget *playWidget = qobject_cast(playerWidget)) { if (!m_isStartingPlay) { m_isStartingPlay = true; qDebug() << "[MainPanel] 防抖处理后开始播放:" << m_pendingRoomId; playWidget->startToPlay("rtmp://106.55.186.74:1935/stream/V1/" + m_pendingRoomId); m_isStartingPlay = false; // 如果 startToPlay 是同步的 } } // 清空待处理的房间ID m_pendingRoomId.clear(); }