#include "MainPanel.h" #include #include #include #include #include #include #include #include #include "widgets/bubbletip.h" #include "widgets/chatView/chatwindow.h" #include "advanceddockingsystem/dockmanager.h" #include "widgets/maskoverlay.h" #include "widgets/userprofilewidget.h" #include "widgets/statswidget.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); statsWidget = new StatsWidget(this); // 初始化 DockManager m_dockManager = new ADS::DockManager(this); m_dockManager->setStyleSheet(""); // 使用应用程序的样式表 // 创建右侧面板作为可停靠的 DockWidget QWidget *rightWidget = new QWidget; QVBoxLayout *vbox = new QVBoxLayout(rightWidget); vbox->setContentsMargins(0, 0, 0, 0); vbox->addWidget(userProfile, 0); vbox->addWidget(statsWidget, 0); vbox->addWidget(chatView, 1); ADS::DockWidget* rightDockWidget = new ADS::DockWidget("聊天面板", this); rightDockWidget->setWidget(rightWidget); rightDockWidget->setFeature(ADS::DockWidget::DockWidgetClosable, true); // 创建中央内容 playerContainer = new QWidget(this); // 创建中央播放器 DockWidget ADS::DockWidget* centerDockWidget = new ADS::DockWidget("播放器", this); centerDockWidget->setWidget(playerContainer); centerDockWidget->setFeature(ADS::DockWidget::DockWidgetClosable, false); centerDockWidget->setFeature(ADS::DockWidget::DockWidgetMovable, false); centerDockWidget->setFeature(ADS::DockWidget::DockWidgetFloatable, false); // 将 DockWidget 添加到 DockManager // m_dockManager->addDockWidget(ADS::LeftDockWidgetArea, leftDockWidget); m_dockManager->addDockWidget(ADS::CenterDockWidgetArea, centerDockWidget); m_dockManager->addDockWidget(ADS::RightDockWidgetArea, rightDockWidget); // 保存 splitter 引用以保持兼容性 splitter = nullptr; // 不再使用 QSplitter QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(m_dockManager, 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(userProfile, &UserProfileWidget::logoutClicked, this, &MainPanel::logoutClicked); connect(webSocketClient, &WebSocketClient::statsUpdate, statsWidget, &StatsWidget::updateStats); 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); // 设置初始化信息 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); 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::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, 1); // 添加拉伸因子,让播放器组件占据所有可用空间 // 确保播放器组件能够正确拉伸 playerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); } 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(); }