zhuizhu 6 ay önce
ebeveyn
işleme
889bdfa578

+ 6 - 0
MainPanel.cpp

@@ -321,6 +321,12 @@ void MainPanel::setRole(const QStringList &roleList)
         m_streamButton->setVisible(isRec);
         m_streamButton->setText(tr("推流"));
     }
+
+    // 更新在线用户组件的权限状态
+    if (m_onlineUsersWidget) {
+        qDebug() << roleList;
+        m_onlineUsersWidget->setUserRoles(roleList);
+    }
 }
 
 void MainPanel::setPushRoomId(const QString &id)

+ 12 - 0
api/chatapi.cpp

@@ -31,4 +31,16 @@ QFuture<HttpResponse> getRoomList(int page, int pageSize)
     return TC::RequestClient::globalInstance()->getAsync("/api/rooms", params);
 }
 
+QFuture<HttpResponse> resetRoomStats(const QString& roomId)
+{
+    QString url = QString("/api/chat/room/stats/reset/%1").arg(roomId);
+    return TC::RequestClient::globalInstance()->postAsync(url, QJsonDocument());
+}
+
+QFuture<HttpResponse> resetUserStats(const QString& roomId, const QString& userId)
+{
+    QString url = QString("/api/chat/stats/reset/%1/%2").arg(roomId, userId);
+    return TC::RequestClient::globalInstance()->postAsync(url, QJsonDocument());
+}
+
 } // namespace ChatApi

+ 15 - 0
api/chatapi.h

@@ -26,6 +26,21 @@ QFuture<HttpResponse> createRoom(const QString& roomName, const QString& descrip
  */
 QFuture<HttpResponse> getRoomList(int page = 1, int pageSize = 10);
 
+/**
+ * 重置房间统计数据
+ * @param roomId 房间ID
+ * @return 返回包含基本响应的 Future
+ */
+QFuture<HttpResponse> resetRoomStats(const QString& roomId);
+
+/**
+ * 重置用户消息统计数据
+ * @param roomId 房间ID
+ * @param userId 用户ID
+ * @return 返回包含基本响应的 Future
+ */
+QFuture<HttpResponse> resetUserStats(const QString& roomId, const QString& userId);
+
 } // namespace ChatApi
 
 #endif // CHATAPI_H

+ 4 - 3
config/networkconfig.cpp

@@ -86,17 +86,18 @@ bool NetworkConfig::isValid() const
 
 void NetworkConfig::initDefaults()
 {
+    const QString ip = "106.55.186.74";
     // 106.55.186.74
     // 服务器配置默认值
-    m_serverConfig.host = "127.0.0.1"; // 使用项目中的生产服务器
+    m_serverConfig.host = ip; //"127.0.0.1"; // 使用项目中的生产服务器
     m_serverConfig.port = 8200;
     m_serverConfig.useHttps = false;
     m_serverConfig.apiPath = "/api";
     
     // 流媒体配置 (默认使用RTMP协议)
     m_streamConfig.protocol = StreamProtocol::RTSP;
-    m_streamConfig.host = "127.0.0.1"; // 使用项目中的生产服务器
-    m_streamConfig.port = 554;
+    m_streamConfig.host = ip; // "127.0.0.1"; // 使用项目中的生产服务器
+    m_streamConfig.port = 8554;
     m_streamConfig.app = "stream";
     m_streamConfig.streamKey = "V1";
     

+ 7 - 1
widgets/chatView/chatwindow.cpp

@@ -355,7 +355,7 @@ void ChatWindow::setupInputArea()
 
     m_imageButton = new QPushButton("图片", this);
     m_fileButton = new QPushButton("文件", this);
-    m_streamButton = new QPushButton("推流", this);
+    m_streamButton = new QPushButton("提问通知", this);
     m_sendButton = new QPushButton("发送", this);
 
     buttonLayout->addWidget(m_imageButton);
@@ -390,6 +390,12 @@ void ChatWindow::connectSignals()
     connect(m_fileButton, &QPushButton::clicked, this, &ChatWindow::onFileClicked);
     connect(m_streamButton, &QPushButton::clicked, this, &ChatWindow::onStreamButtonClicked);
 
+    if (AppEvent::instance()->hasRole("role.admin")) {
+        m_streamButton->setVisible(true);
+    } else {
+        m_streamButton->setVisible(false);
+    }
+
     // 快速按钮信号连接
     if (m_quickButtonGroup) {
         const QList<QAbstractButton *> buttons = m_quickButtonGroup->buttons();

+ 174 - 53
widgets/onlineuserswidget.cpp

@@ -5,6 +5,7 @@
 #include <QJsonDocument>
 #include "network/networkaccessmanager.h"
 #include "qglobal.h"
+#include "api/chatapi.h"
 
 #include <qtpromise/qpromise.h>
 #include <qtpromise/qpromisefuture.h>
@@ -17,6 +18,7 @@ OnlineUsersWidget::OnlineUsersWidget(QWidget *parent)
     , m_titleLabel(nullptr)
     , m_countLabel(nullptr)
     , m_refreshButton(nullptr)
+    , m_resetRoomStatsButton(nullptr)
     , m_searchEdit(nullptr)
     , m_usersTable(nullptr)
     , m_emptyStateLabel(nullptr)
@@ -24,6 +26,8 @@ OnlineUsersWidget::OnlineUsersWidget(QWidget *parent)
     , m_privateMessageAction(nullptr)
     , m_viewProfileAction(nullptr)
     , m_kickUserAction(nullptr)
+    , m_resetUserStatsAction(nullptr)
+    , m_hasRecorderPermission(false)
     , m_totalCount(0)
 {
     // 初始化统计数据
@@ -34,7 +38,9 @@ OnlineUsersWidget::OnlineUsersWidget(QWidget *parent)
     setupUI();
     setupTable();
     setupContextMenu();
-    applyStyles();
+
+    // 初始化权限状态(默认无权限)
+    updateButtonPermissions();
 
     // 添加一些示例数据
     addUser(OnlineUser("1", "管理员", "在线"));
@@ -64,9 +70,14 @@ void OnlineUsersWidget::setupUI()
     m_refreshButton->setObjectName("refreshButton");
     m_refreshButton->setMaximumWidth(60);
 
+    m_resetRoomStatsButton = new QPushButton("重置统计", this);
+    m_resetRoomStatsButton->setObjectName("resetRoomStatsButton");
+    m_resetRoomStatsButton->setMaximumWidth(80);
+
     m_headerLayout->addWidget(m_titleLabel);
     m_headerLayout->addWidget(m_countLabel);
     m_headerLayout->addStretch();
+    m_headerLayout->addWidget(m_resetRoomStatsButton);
     m_headerLayout->addWidget(m_refreshButton);
 
     // 搜索框
@@ -94,6 +105,7 @@ void OnlineUsersWidget::setupUI()
 
     // 连接信号
     connect(m_refreshButton, &QPushButton::clicked, this, &OnlineUsersWidget::onRefreshClicked);
+    connect(m_resetRoomStatsButton, &QPushButton::clicked, this, &OnlineUsersWidget::resetRoomStats);
     connect(m_searchEdit, &QLineEdit::textChanged, this, &OnlineUsersWidget::onSearchTextChanged);
 }
 
@@ -144,11 +156,13 @@ void OnlineUsersWidget::setupContextMenu()
     m_privateMessageAction = new QAction("发送私信", this);
     m_viewProfileAction = new QAction("查看资料", this);
     m_kickUserAction = new QAction("踢出用户", this);
+    m_resetUserStatsAction = new QAction("重置统计数据", this);
 
     m_contextMenu->addAction(m_privateMessageAction);
     m_contextMenu->addAction(m_viewProfileAction);
     m_contextMenu->addSeparator();
     m_contextMenu->addAction(m_kickUserAction);
+    m_contextMenu->addAction(m_resetUserStatsAction);
 
     // 连接信号
     connect(m_privateMessageAction, &QAction::triggered, [this]() {
@@ -167,61 +181,15 @@ void OnlineUsersWidget::setupContextMenu()
         // TODO: 实现踢出用户功能
         qDebug() << "踢出用户:" << m_selectedUsername;
     });
-}
 
-void OnlineUsersWidget::applyStyles()
-{
-    // setStyleSheet("#titleLabel {"
-    //               "    font-size: 14px;"
-    //               "    font-weight: bold;"
-    //               "    color: #2c3e50;"
-    //               "}"
-
-    //               "#countLabel {"
-    //               "    font-size: 12px;"
-    //               "    color: #7f8c8d;"
-    //               "    margin-left: 5px;"
-    //               "}"
-
-    //               "#searchEdit {"
-    //               "    padding: 6px;"
-    //               "    border: 1px solid #bdc3c7;"
-    //               "    border-radius: 3px;"
-    //               "    font-size: 12px;"
-    //               "}"
-
-    //               "#usersTable {"
-    //               "    border: 1px solid #bdc3c7;"
-    //               "    border-radius: 3px;"
-    //               "    background-color: white;"
-    //               "    gridline-color: #ecf0f1;"
-    //               "}"
-
-    //               "#usersTable::item {"
-    //               "    padding: 8px;"
-    //               "    border-bottom: 1px solid #ecf0f1;"
-    //               "}"
-
-    //               "#usersTable::item:selected {"
-    //               "    background-color: #3498db;"
-    //               "    color: white;"
-    //               "}"
-
-    //               "#usersTable::item:hover {"
-    //               "    background-color: #ecf0f1;"
-    //               "}"
-
-    //               "#emptyStateLabel {"
-    //               "    font-size: 14px;"
-    //               "    color: #7f8c8d;"
-    //               "    padding: 40px 20px;"
-    //               "    background-color: #f8f9fa;"
-    //               "    border: 1px solid #e9ecef;"
-    //               "    border-radius: 6px;"
-    //               "    margin: 20px 0;"
-    //               "}");
+    connect(m_resetUserStatsAction, &QAction::triggered, [this]() {
+        if (!m_selectedUserId.isEmpty()) {
+            resetUserStats(m_selectedUserId);
+        }
+    });
 }
 
+
 void OnlineUsersWidget::addUser(const OnlineUser &user)
 {
     // 检查用户是否已存在
@@ -652,6 +620,28 @@ void OnlineUsersWidget::updateStats(const QJsonObject& statsData)
         }
         QDateTime latestUpdate;
         
+        // 如果dataArray为空,清理所有用户的统计数据显示
+        if (dataArray.isEmpty()) {
+            qDebug() << "[OnlineUsersWidget] dataArray为空,清理所有用户统计数据显示";
+            
+            // 遍历表格中的所有用户,将统计列设置为0
+            for (int row = 0; row < m_usersTable->rowCount(); ++row) {
+                // 清理统计列 (列3-9,对应type0-type6的统计数据)
+                for (int col = 3; col < 10; ++col) {
+                    QTableWidgetItem* item = m_usersTable->item(row, col);
+                    if (item) {
+                        item->setText("0");
+                    } else {
+                        m_usersTable->setItem(row, col, new QTableWidgetItem("0"));
+                    }
+                }
+            }
+            
+            m_lastStatsUpdate = QDateTime();
+            qDebug() << "[OnlineUsersWidget] 已清理所有用户统计数据显示";
+            return;
+        }
+        
         // 遍历所有用户数据进行更新
         for (const QJsonValue& value : dataArray) {
             if (value.isObject()) {
@@ -719,3 +709,134 @@ void OnlineUsersWidget::updateUserStats(const QString &userId, const QJsonObject
         qDebug() << "[OnlineUsersWidget] 未找到用户:" << userId;
     }
 }
+
+void OnlineUsersWidget::resetRoomStats()
+{
+    if (m_currentRoomId.isEmpty()) {
+        qDebug() << "房间ID为空,无法重置房间统计数据";
+        return;
+    }
+
+    qDebug() << "重置房间统计数据,房间ID:" << m_currentRoomId;
+
+    // 调用API重置房间统计数据
+    QFuture<HttpResponse> future = ChatApi::resetRoomStats(m_currentRoomId);
+
+    // 使用QtPromise处理异步响应
+    QtPromise::QPromise<HttpResponse> resetPromise = QtPromise::resolve(future);
+
+    resetPromise
+        .then([this](const HttpResponse &response) {
+            if (response.code == 0) {
+                qDebug() << "房间统计数据重置成功";
+                
+                // 重置本地全局统计数据
+                m_totalCount = 0;
+                for (int i = 0; i < 7; ++i) {
+                    m_globalStats[i] = 0;
+                }
+                
+                // 重置所有用户的统计数据
+                for (auto &user : m_users) {
+                    for (int i = 0; i < 7; ++i) {
+                        user.messageStats[i] = 0;
+                    }
+                }
+                
+                // 刷新表格显示
+                for (int row = 0; row < m_usersTable->rowCount(); ++row) {
+                    QTableWidgetItem *nameItem = m_usersTable->item(row, 1);
+                    if (nameItem) {
+                        QString username = nameItem->text();
+                        // 找到对应用户并更新表格行
+                        for (const auto &user : m_users) {
+                            if (user.username == username || nameItem->text().contains(user.username)) {
+                                updateTableRow(row, user);
+                                break;
+                            }
+                        }
+                    }
+                }
+                
+            } else {
+                qDebug() << "重置房间统计数据失败:" << response.message;
+            }
+        })
+        .fail([](const std::exception &e) { 
+            qDebug() << "重置房间统计数据异常:" << e.what(); 
+        });
+}
+
+void OnlineUsersWidget::resetUserStats(const QString &userId)
+{
+    if (m_currentRoomId.isEmpty()) {
+        qDebug() << "房间ID为空,无法重置用户统计数据";
+        return;
+    }
+
+    if (userId.isEmpty()) {
+        qDebug() << "用户ID为空,无法重置用户统计数据";
+        return;
+    }
+
+    qDebug() << "重置用户统计数据,房间ID:" << m_currentRoomId << "用户ID:" << userId;
+
+    // 调用API重置用户统计数据
+    QFuture<HttpResponse> future = ChatApi::resetUserStats(m_currentRoomId, userId);
+
+    // 使用QtPromise处理异步响应
+    QtPromise::QPromise<HttpResponse> resetPromise = QtPromise::resolve(future);
+
+    resetPromise
+        .then([this, userId](const HttpResponse &response) {
+            if (response.code == 0) {
+                qDebug() << "用户统计数据重置成功,用户ID:" << userId;
+                
+                // 重置本地用户统计数据
+                for (auto &user : m_users) {
+                    if (user.userId == userId) {
+                        for (int i = 0; i < 7; ++i) {
+                            user.messageStats[i] = 0;
+                        }
+                        
+                        // 更新表格中对应的行
+                        int row = findUserRow(userId);
+                        if (row >= 0) {
+                            updateTableRow(row, user);
+                        }
+                        break;
+                    }
+                }
+                
+            } else {
+                qDebug() << "重置用户统计数据失败:" << response.message;
+            }
+        })
+        .fail([](const std::exception &e) { 
+            qDebug() << "重置用户统计数据异常:" << e.what(); 
+        });
+}
+
+// 权限控制方法
+void OnlineUsersWidget::setUserRoles(const QStringList &roleList)
+{
+    m_userRoles = roleList;
+    
+    // 检查是否有录制权限
+    m_hasRecorderPermission = roleList.contains("role.admin") || 
+                             roleList.contains("role.recorder") || 
+                             roleList.contains("录制");
+    
+    // 更新按钮权限状态
+    updateButtonPermissions();
+}
+
+void OnlineUsersWidget::updateButtonPermissions()
+{
+    if (m_resetRoomStatsButton) {
+        m_resetRoomStatsButton->setVisible(m_hasRecorderPermission);
+        if (m_hasRecorderPermission) {
+            m_resetRoomStatsButton->setToolTip("重置房间统计数据");
+        }
+    }
+}

+ 15 - 2
widgets/onlineuserswidget.h

@@ -75,6 +75,14 @@ public:
     // 统计功能 (从 StatsWidget 迁移)
     void updateStats(const QJsonObject& statsData);
     void updateUserStats(const QString &userId, const QJsonObject& userStats);
+    
+    // 权限控制
+    void setUserRoles(const QStringList &roleList);
+    void updateButtonPermissions();
+    
+    // 重置统计数据功能
+    void resetRoomStats();
+    void resetUserStats(const QString &userId);
 
 signals:
     // 用户交互信号
@@ -96,7 +104,6 @@ private:
     void setupUI();
     void setupTable();
     void setupContextMenu();
-    void applyStyles();
     void updateTableRow(int row, const OnlineUser &user);
     int findUserRow(const QString &userId) const;
     QString getStatusIcon(const QString &status) const;
@@ -108,6 +115,7 @@ private:
     QLabel *m_titleLabel;
     QLabel *m_countLabel;
     QPushButton *m_refreshButton;
+    QPushButton *m_resetRoomStatsButton;
     QLineEdit *m_searchEdit;
     QTableWidget *m_usersTable;
     QLabel *m_emptyStateLabel;  // 空状态提示标签
@@ -117,12 +125,17 @@ private:
     QAction *m_privateMessageAction;
     QAction *m_viewProfileAction;
     QAction *m_kickUserAction;  // 仅管理员可见
+    QAction *m_resetUserStatsAction;  // 重置用户统计数据
     
-    // 数据
+    // 数据成员
     QList<OnlineUser> m_users;
     QString m_currentFilter;
     QString m_currentRoomId;
     
+    // 权限相关
+    QStringList m_userRoles;  // 用户角色列表
+    bool m_hasRecorderPermission;  // 是否有录制权限
+    
     // 统计数据 (从 StatsWidget 迁移)
     int m_totalCount;
     int m_globalStats[7];  // 全局统计数据 (对应0-6类型)