#include "onlineuserswidget.h" #include #include #include #include #include "network/networkaccessmanager.h" #include "qglobal.h" #include #include #include OnlineUsersWidget::OnlineUsersWidget(QWidget *parent) : QWidget(parent) , m_mainLayout(nullptr) , m_headerLayout(nullptr) , m_titleLabel(nullptr) , m_countLabel(nullptr) , m_refreshButton(nullptr) , m_searchEdit(nullptr) , m_usersTable(nullptr) , m_emptyStateLabel(nullptr) , m_contextMenu(nullptr) , m_privateMessageAction(nullptr) , m_viewProfileAction(nullptr) , m_kickUserAction(nullptr) , m_totalCount(0) { // 初始化统计数据 for (int i = 0; i < 7; ++i) { m_globalStats[i] = 0; } setupUI(); setupTable(); setupContextMenu(); applyStyles(); // 添加一些示例数据 addUser(OnlineUser("1", "管理员", "在线")); addUser(OnlineUser("2", "用户A", "在线")); addUser(OnlineUser("3", "用户B", "离开")); addUser(OnlineUser("4", "用户C", "忙碌")); } OnlineUsersWidget::~OnlineUsersWidget() {} void OnlineUsersWidget::setupUI() { m_mainLayout = new QVBoxLayout(this); m_mainLayout->setContentsMargins(8, 8, 8, 8); m_mainLayout->setSpacing(6); // 头部布局 m_headerLayout = new QHBoxLayout(); m_titleLabel = new QLabel("在线用户", this); m_titleLabel->setObjectName("titleLabel"); m_countLabel = new QLabel("(0)", this); m_countLabel->setObjectName("countLabel"); m_refreshButton = new QPushButton("刷新", this); m_refreshButton->setObjectName("refreshButton"); m_refreshButton->setMaximumWidth(60); m_headerLayout->addWidget(m_titleLabel); m_headerLayout->addWidget(m_countLabel); m_headerLayout->addStretch(); m_headerLayout->addWidget(m_refreshButton); // 搜索框 m_searchEdit = new QLineEdit(this); m_searchEdit->setPlaceholderText("搜索用户..."); m_searchEdit->setObjectName("searchEdit"); // 用户表格 m_usersTable = new QTableWidget(this); m_usersTable->setObjectName("usersTable"); // 空状态提示标签 m_emptyStateLabel = new QLabel(this); m_emptyStateLabel->setObjectName("emptyStateLabel"); m_emptyStateLabel->setText("请选择一个房间查看在线用户"); m_emptyStateLabel->setAlignment(Qt::AlignCenter); m_emptyStateLabel->setWordWrap(true); m_emptyStateLabel->hide(); // 默认隐藏 // 添加到主布局 m_mainLayout->addLayout(m_headerLayout); m_mainLayout->addWidget(m_searchEdit); m_mainLayout->addWidget(m_usersTable); m_mainLayout->addWidget(m_emptyStateLabel); // 连接信号 connect(m_refreshButton, &QPushButton::clicked, this, &OnlineUsersWidget::onRefreshClicked); connect(m_searchEdit, &QLineEdit::textChanged, this, &OnlineUsersWidget::onSearchTextChanged); } void OnlineUsersWidget::setupTable() { // 设置表格列 - 原有3列 + 新增7列 (0-6) m_usersTable->setColumnCount(10); QStringList headers; headers << "状态" << "用户名" << "最后活动" << "0" << "1" << "2" << "3" << "4" << "5" << "6"; m_usersTable->setHorizontalHeaderLabels(headers); // 设置表格属性 m_usersTable->setSelectionBehavior(QAbstractItemView::SelectRows); m_usersTable->setSelectionMode(QAbstractItemView::SingleSelection); m_usersTable->setAlternatingRowColors(true); m_usersTable->setShowGrid(false); m_usersTable->verticalHeader()->setVisible(false); // 设置列宽 QHeaderView *header = m_usersTable->horizontalHeader(); header->setStretchLastSection(false); header->resizeSection(0, 60); // 状态列 header->resizeSection(1, 120); // 用户名列 header->resizeSection(2, 80); // 最后活动列 // 设置新增的0-6列宽度 for (int i = 3; i < 10; ++i) { header->resizeSection(i, 40); } // 连接信号 connect(m_usersTable, &QTableWidget::itemDoubleClicked, [this](QTableWidgetItem *item) { if (item) { onTableDoubleClicked(item->row(), item->column()); } }); m_usersTable->setContextMenuPolicy(Qt::CustomContextMenu); connect(m_usersTable, &QTableWidget::customContextMenuRequested, this, &OnlineUsersWidget::onTableContextMenu); } void OnlineUsersWidget::setupContextMenu() { m_contextMenu = new QMenu(this); m_privateMessageAction = new QAction("发送私信", this); m_viewProfileAction = new QAction("查看资料", this); m_kickUserAction = new QAction("踢出用户", this); m_contextMenu->addAction(m_privateMessageAction); m_contextMenu->addAction(m_viewProfileAction); m_contextMenu->addSeparator(); m_contextMenu->addAction(m_kickUserAction); // 连接信号 connect(m_privateMessageAction, &QAction::triggered, [this]() { if (!m_selectedUserId.isEmpty()) { emit privateMessageRequested(m_selectedUserId, m_selectedUsername); } }); connect(m_viewProfileAction, &QAction::triggered, [this]() { if (!m_selectedUserId.isEmpty()) { emit userProfileRequested(m_selectedUserId, m_selectedUsername); } }); connect(m_kickUserAction, &QAction::triggered, [this]() { // 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;" // "}"); } void OnlineUsersWidget::addUser(const OnlineUser &user) { // 检查用户是否已存在 int existingRow = findUserRow(user.userId); if (existingRow >= 0) { // 更新现有用户 m_users[existingRow] = user; updateTableRow(existingRow, user); return; } // 添加新用户 m_users.append(user); // 如果当前有过滤条件,检查是否匹配 if (!m_currentFilter.isEmpty()) { if (!user.username.contains(m_currentFilter, Qt::CaseInsensitive)) { updateUserCountLabel(); return; } } // 添加到表格 int row = m_usersTable->rowCount(); m_usersTable->insertRow(row); updateTableRow(row, user); updateUserCountLabel(); // 确保表格可见(隐藏空状态) if (m_emptyStateLabel->isVisible()) { m_emptyStateLabel->hide(); m_usersTable->show(); } } void OnlineUsersWidget::removeUser(const QString &userId) { int row = findUserRow(userId); if (row >= 0) { m_users.removeAt(row); m_usersTable->removeRow(row); updateUserCountLabel(); } } void OnlineUsersWidget::updateUserStatus(const QString &userId, const QString &status) { int userIndex = -1; for (int i = 0; i < m_users.size(); ++i) { if (m_users[i].userId == userId) { userIndex = i; break; } } if (userIndex >= 0) { m_users[userIndex].status = status; m_users[userIndex].lastSeen = QDateTime::currentDateTime(); // 更新表格中对应的行 int row = findUserRow(userId); if (row >= 0) { updateTableRow(row, m_users[userIndex]); } } } void OnlineUsersWidget::updateUserList(const QJsonArray &users) { clearUsers(); for (const auto &value : users) { if (value.isObject()) { QJsonObject userObj = value.toObject(); OnlineUser user; user.userId = userObj["id"].toString(); user.username = userObj["username"].toString(); user.status = userObj["status"].toString("在线"); user.isAdmin = userObj["isAdmin"].toBool(false); if (userObj.contains("lastSeen")) { user.lastSeen = QDateTime::fromString(userObj["lastSeen"].toString(), Qt::ISODate); } else { user.lastSeen = QDateTime::currentDateTime(); } addUser(user); } } } void OnlineUsersWidget::clearUsers() { m_users.clear(); m_usersTable->setRowCount(0); updateUserCountLabel(); } QList OnlineUsersWidget::getAllUsers() const { return m_users; } OnlineUser OnlineUsersWidget::getUser(const QString &userId) const { for (const auto &user : m_users) { if (user.userId == userId) { return user; } } return OnlineUser(); } int OnlineUsersWidget::getUserCount() const { return m_users.size(); } void OnlineUsersWidget::setSearchVisible(bool visible) { m_searchEdit->setVisible(visible); } void OnlineUsersWidget::filterUsers(const QString &keyword) { m_currentFilter = keyword; // 清空表格 m_usersTable->setRowCount(0); // 重新添加匹配的用户 for (const auto &user : m_users) { if (keyword.isEmpty() || user.username.contains(keyword, Qt::CaseInsensitive)) { int row = m_usersTable->rowCount(); m_usersTable->insertRow(row); updateTableRow(row, user); } } updateUserCountLabel(); } void OnlineUsersWidget::onTableDoubleClicked(int row, int column) { Q_UNUSED(column); if (row >= 0 && row < m_usersTable->rowCount()) { QTableWidgetItem *userItem = m_usersTable->item(row, 1); // 用户名列 if (userItem) { QString username = userItem->text(); // 从用户列表中找到对应的userId for (const auto &user : m_users) { if (user.username == username) { emit userDoubleClicked(user.userId, username); break; } } } } } void OnlineUsersWidget::onTableContextMenu(const QPoint &position) { QTableWidgetItem *item = m_usersTable->itemAt(position); if (!item) return; int row = item->row(); QTableWidgetItem *userItem = m_usersTable->item(row, 1); if (!userItem) return; QString username = userItem->text(); // 从用户列表中找到对应的userId for (const auto &user : m_users) { if (user.username == username) { m_selectedUserId = user.userId; m_selectedUsername = username; // 根据用户权限显示/隐藏菜单项 m_kickUserAction->setVisible(user.isAdmin); // 示例:只有管理员能踢人 QPoint globalPos = m_usersTable->mapToGlobal(position); emit userRightClicked(user.userId, username, globalPos); m_contextMenu->exec(globalPos); break; } } } void OnlineUsersWidget::onSearchTextChanged(const QString &text) { filterUsers(text); } void OnlineUsersWidget::onRefreshClicked() { if (!m_currentRoomId.isEmpty()) { refreshRoomUsers(); } else { // 当没有房间ID时,显示空状态提示 clearUsers(); updateEmptyState(); qDebug() << "没有选择房间,显示空状态提示"; } } void OnlineUsersWidget::updateUserCountLabel() { int totalUsers = m_users.size(); int displayedUsers = m_usersTable->rowCount(); if (m_currentFilter.isEmpty()) { m_countLabel->setText(QString("(%1)").arg(totalUsers)); } else { m_countLabel->setText(QString("(%1/%2)").arg(displayedUsers).arg(totalUsers)); } } void OnlineUsersWidget::updateTableRow(int row, const OnlineUser &user) { // 状态列 QTableWidgetItem *statusItem = new QTableWidgetItem(getStatusIcon(user.status) + " " + user.status); statusItem->setFlags(statusItem->flags() & ~Qt::ItemIsEditable); m_usersTable->setItem(row, 0, statusItem); // 用户名列 QTableWidgetItem *nameItem = new QTableWidgetItem(user.username); nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable); if (user.isAdmin) { nameItem->setText(user.username + " (管理员)"); nameItem->setForeground(QColor("#e74c3c")); } m_usersTable->setItem(row, 1, nameItem); // 最后活动时间列 QString timeText = user.lastSeen.toString("hh:mm"); QTableWidgetItem *timeItem = new QTableWidgetItem(timeText); timeItem->setFlags(timeItem->flags() & ~Qt::ItemIsEditable); m_usersTable->setItem(row, 2, timeItem); // 添加0-6列的统计数据 for (int i = 0; i < 7; ++i) { QTableWidgetItem *statsItem = new QTableWidgetItem(QString::number(user.messageStats[i])); statsItem->setFlags(statsItem->flags() & ~Qt::ItemIsEditable); statsItem->setTextAlignment(Qt::AlignCenter); m_usersTable->setItem(row, i + 3, statsItem); } } int OnlineUsersWidget::findUserRow(const QString &userId) const { for (int i = 0; i < m_users.size(); ++i) { if (m_users[i].userId == userId) { // 在表格中查找对应行 for (int row = 0; row < m_usersTable->rowCount(); ++row) { QTableWidgetItem *nameItem = m_usersTable->item(row, 1); if (nameItem && nameItem->text().contains(m_users[i].username)) { return row; } } break; } } return -1; } QString OnlineUsersWidget::getStatusIcon(const QString &status) const { if (status == "在线") { return "🟢"; } else if (status == "离开") { return "🟡"; } else if (status == "忙碌") { return "🔴"; } else { return "⚪"; } } void OnlineUsersWidget::updateEmptyState() { // 根据当前状态显示相应的空状态提示 if (m_currentRoomId.isEmpty()) { m_emptyStateLabel->setText("请选择一个房间查看在线用户"); m_emptyStateLabel->show(); m_usersTable->hide(); } else { m_emptyStateLabel->hide(); m_usersTable->show(); } } void OnlineUsersWidget::updateUserListFromRoomUsers(const QList &roomUsers) { // 保存现有用户的统计数据 QHash existingUsers; for (const auto &user : m_users) { existingUsers[user.userId] = user; } clearUsers(); for (const auto &roomUser : roomUsers) { OnlineUser user; user.userId = roomUser.userId; user.username = roomUser.userName; user.status = "在线"; // 房间用户默认为在线状态 user.lastSeen = QDateTime::currentDateTime(); user.isAdmin = false; // 可以根据需要设置管理员状态 // 如果用户之前存在,恢复其统计数据 if (existingUsers.contains(user.userId)) { const OnlineUser &existingUser = existingUsers[user.userId]; for (int i = 0; i < 7; ++i) { user.messageStats[i] = existingUser.messageStats[i]; } user.isAdmin = existingUser.isAdmin; // 保持管理员状态 } addUser(user); } } void OnlineUsersWidget::setCurrentRoomId(const QString &roomId) { m_currentRoomId = roomId; if (!roomId.isEmpty()) { refreshRoomUsers(); } else { // 当房间ID为空时,显示空状态 clearUsers(); updateEmptyState(); } } void OnlineUsersWidget::refreshRoomUsers() { if (m_currentRoomId.isEmpty()) { qDebug() << "房间ID为空,无法刷新用户列表"; return; } qDebug() << "刷新房间用户列表,房间ID:" << m_currentRoomId; // 调用API获取房间用户列表 QFuture future = getRoomUsersApi(m_currentRoomId); // 使用QtPromise处理异步响应 QtPromise::QPromise roomUsersPromise = QtPromise::resolve(future); roomUsersPromise .then([this](const HttpResponse &response) { qDebug() << response.rawData; if (response.code == 0) { // 解析响应数据 qDebug() << "response.data" << response.data; if (response.data.isArray()) { QJsonArray userArray = response.data.toArray(); // 直接从数组解析用户数据 QList roomUsers; for (const QJsonValue &value : userArray) { if (value.isObject()) { QJsonObject userObj = value.toObject(); RoomUserInfo userInfo; userInfo.userId = userObj["userId"].toString(); userInfo.userName = userObj["userName"].toString(); userInfo.clientId = userObj["clientId"].toString(); roomUsers.append(userInfo); } } // 更新用户列表 updateUserListFromRoomUsers(roomUsers); qDebug() << "成功获取房间用户列表,用户数量:" << roomUsers.size(); } } else { qDebug() << "获取房间用户列表失败:" << response.message; } }) .fail([](const std::exception &e) { qDebug() << "获取房间用户列表异常:" << e.what(); }); } void OnlineUsersWidget::onUserListUpdate(const QString &roomId, const QJsonArray &userList) { // 检查是否是当前房间的用户列表更新 if (roomId != m_currentRoomId) { return; } qDebug() << "收到房间用户列表更新消息,房间ID:" << roomId << "用户数量:" << userList.size(); // 将QJsonArray转换为RoomUserInfo列表 QList roomUsers; for (const QJsonValue &value : userList) { if (value.isObject()) { QJsonObject userObj = value.toObject(); RoomUserInfo userInfo; userInfo.userId = userObj["userId"].toString(); userInfo.userName = userObj["userName"].toString(); userInfo.clientId = userObj["clientId"].toString(); roomUsers.append(userInfo); } } // 更新用户列表显示 updateUserListFromRoomUsers(roomUsers); } // 统计功能方法 (从 StatsWidget 迁移) void OnlineUsersWidget::updateStats(const QJsonObject& statsData) { qDebug() << "[OnlineUsersWidget] 收到统计更新:" << statsData; // 解析data数组并更新用户统计数据 if (statsData.contains("data") && statsData["data"].isArray()) { QJsonArray dataArray = statsData["data"].toArray(); // 重置全局累计数据 m_totalCount = 0; for (int i = 0; i < 7; ++i) { m_globalStats[i] = 0; } QDateTime latestUpdate; // 遍历所有用户数据进行更新 for (const QJsonValue& value : dataArray) { if (value.isObject()) { QJsonObject userStats = value.toObject(); QString userId = userStats["userId"].toString(); // 更新单个用户的统计数据 updateUserStats(userId, userStats); // 累加到全局统计 m_totalCount += userStats["totalCount"].toInt(); for (int i = 0; i < 7; ++i) { QString typeKey = QString("type%1Count").arg(i); m_globalStats[i] += userStats[typeKey].toInt(); } // 找到最新的更新时间 QString lastUpdateStr = userStats["lastUpdate"].toString(); QDateTime userUpdate = QDateTime::fromString(lastUpdateStr, Qt::ISODate); if (userUpdate.isValid() && (!latestUpdate.isValid() || userUpdate > latestUpdate)) { latestUpdate = userUpdate; } } } m_lastStatsUpdate = latestUpdate; qDebug() << "[OnlineUsersWidget] 全局统计信息已更新 - 总数:" << m_totalCount << "类型0-6:" << m_globalStats[0] << m_globalStats[1] << m_globalStats[2] << m_globalStats[3] << m_globalStats[4] << m_globalStats[5] << m_globalStats[6] << "用户数:" << dataArray.size(); } } void OnlineUsersWidget::updateUserStats(const QString &userId, const QJsonObject& userStats) { // 查找用户 int userIndex = -1; for (int i = 0; i < m_users.size(); ++i) { if (m_users[i].userId == userId) { userIndex = i; break; } } if (userIndex >= 0) { // 更新用户的统计数据 for (int i = 0; i < 7; ++i) { QString typeKey = QString("type%1Count").arg(i); m_users[userIndex].messageStats[i] = userStats[typeKey].toInt(); } // 更新表格显示 int row = findUserRow(userId); if (row >= 0) { updateTableRow(row, m_users[userIndex]); } qDebug() << "[OnlineUsersWidget] 用户统计已更新:" << userId << "统计数据:" << m_users[userIndex].messageStats[0] << m_users[userIndex].messageStats[1] << m_users[userIndex].messageStats[2] << m_users[userIndex].messageStats[3] << m_users[userIndex].messageStats[4] << m_users[userIndex].messageStats[5] << m_users[userIndex].messageStats[6]; } else { qDebug() << "[OnlineUsersWidget] 未找到用户:" << userId; } }