onlineuserswidget.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721
  1. #include "onlineuserswidget.h"
  2. #include <QApplication>
  3. #include <QDateTime>
  4. #include <QDebug>
  5. #include <QJsonDocument>
  6. #include "network/networkaccessmanager.h"
  7. #include "qglobal.h"
  8. #include <qtpromise/qpromise.h>
  9. #include <qtpromise/qpromisefuture.h>
  10. #include <qtpromise/qpromisehelpers.h>
  11. OnlineUsersWidget::OnlineUsersWidget(QWidget *parent)
  12. : QWidget(parent)
  13. , m_mainLayout(nullptr)
  14. , m_headerLayout(nullptr)
  15. , m_titleLabel(nullptr)
  16. , m_countLabel(nullptr)
  17. , m_refreshButton(nullptr)
  18. , m_searchEdit(nullptr)
  19. , m_usersTable(nullptr)
  20. , m_emptyStateLabel(nullptr)
  21. , m_contextMenu(nullptr)
  22. , m_privateMessageAction(nullptr)
  23. , m_viewProfileAction(nullptr)
  24. , m_kickUserAction(nullptr)
  25. , m_totalCount(0)
  26. {
  27. // 初始化统计数据
  28. for (int i = 0; i < 7; ++i) {
  29. m_globalStats[i] = 0;
  30. }
  31. setupUI();
  32. setupTable();
  33. setupContextMenu();
  34. applyStyles();
  35. // 添加一些示例数据
  36. addUser(OnlineUser("1", "管理员", "在线"));
  37. addUser(OnlineUser("2", "用户A", "在线"));
  38. addUser(OnlineUser("3", "用户B", "离开"));
  39. addUser(OnlineUser("4", "用户C", "忙碌"));
  40. }
  41. OnlineUsersWidget::~OnlineUsersWidget() {}
  42. void OnlineUsersWidget::setupUI()
  43. {
  44. m_mainLayout = new QVBoxLayout(this);
  45. m_mainLayout->setContentsMargins(8, 8, 8, 8);
  46. m_mainLayout->setSpacing(6);
  47. // 头部布局
  48. m_headerLayout = new QHBoxLayout();
  49. m_titleLabel = new QLabel("在线用户", this);
  50. m_titleLabel->setObjectName("titleLabel");
  51. m_countLabel = new QLabel("(0)", this);
  52. m_countLabel->setObjectName("countLabel");
  53. m_refreshButton = new QPushButton("刷新", this);
  54. m_refreshButton->setObjectName("refreshButton");
  55. m_refreshButton->setMaximumWidth(60);
  56. m_headerLayout->addWidget(m_titleLabel);
  57. m_headerLayout->addWidget(m_countLabel);
  58. m_headerLayout->addStretch();
  59. m_headerLayout->addWidget(m_refreshButton);
  60. // 搜索框
  61. m_searchEdit = new QLineEdit(this);
  62. m_searchEdit->setPlaceholderText("搜索用户...");
  63. m_searchEdit->setObjectName("searchEdit");
  64. // 用户表格
  65. m_usersTable = new QTableWidget(this);
  66. m_usersTable->setObjectName("usersTable");
  67. // 空状态提示标签
  68. m_emptyStateLabel = new QLabel(this);
  69. m_emptyStateLabel->setObjectName("emptyStateLabel");
  70. m_emptyStateLabel->setText("请选择一个房间查看在线用户");
  71. m_emptyStateLabel->setAlignment(Qt::AlignCenter);
  72. m_emptyStateLabel->setWordWrap(true);
  73. m_emptyStateLabel->hide(); // 默认隐藏
  74. // 添加到主布局
  75. m_mainLayout->addLayout(m_headerLayout);
  76. m_mainLayout->addWidget(m_searchEdit);
  77. m_mainLayout->addWidget(m_usersTable);
  78. m_mainLayout->addWidget(m_emptyStateLabel);
  79. // 连接信号
  80. connect(m_refreshButton, &QPushButton::clicked, this, &OnlineUsersWidget::onRefreshClicked);
  81. connect(m_searchEdit, &QLineEdit::textChanged, this, &OnlineUsersWidget::onSearchTextChanged);
  82. }
  83. void OnlineUsersWidget::setupTable()
  84. {
  85. // 设置表格列 - 原有3列 + 新增7列 (0-6)
  86. m_usersTable->setColumnCount(10);
  87. QStringList headers;
  88. headers << "状态" << "用户名" << "最后活动" << "0" << "1" << "2" << "3" << "4" << "5" << "6";
  89. m_usersTable->setHorizontalHeaderLabels(headers);
  90. // 设置表格属性
  91. m_usersTable->setSelectionBehavior(QAbstractItemView::SelectRows);
  92. m_usersTable->setSelectionMode(QAbstractItemView::SingleSelection);
  93. m_usersTable->setAlternatingRowColors(true);
  94. m_usersTable->setShowGrid(false);
  95. m_usersTable->verticalHeader()->setVisible(false);
  96. // 设置列宽
  97. QHeaderView *header = m_usersTable->horizontalHeader();
  98. header->setStretchLastSection(false);
  99. header->resizeSection(0, 60); // 状态列
  100. header->resizeSection(1, 120); // 用户名列
  101. header->resizeSection(2, 80); // 最后活动列
  102. // 设置新增的0-6列宽度
  103. for (int i = 3; i < 10; ++i) {
  104. header->resizeSection(i, 40);
  105. }
  106. // 连接信号
  107. connect(m_usersTable, &QTableWidget::itemDoubleClicked, [this](QTableWidgetItem *item) {
  108. if (item) {
  109. onTableDoubleClicked(item->row(), item->column());
  110. }
  111. });
  112. m_usersTable->setContextMenuPolicy(Qt::CustomContextMenu);
  113. connect(m_usersTable,
  114. &QTableWidget::customContextMenuRequested,
  115. this,
  116. &OnlineUsersWidget::onTableContextMenu);
  117. }
  118. void OnlineUsersWidget::setupContextMenu()
  119. {
  120. m_contextMenu = new QMenu(this);
  121. m_privateMessageAction = new QAction("发送私信", this);
  122. m_viewProfileAction = new QAction("查看资料", this);
  123. m_kickUserAction = new QAction("踢出用户", this);
  124. m_contextMenu->addAction(m_privateMessageAction);
  125. m_contextMenu->addAction(m_viewProfileAction);
  126. m_contextMenu->addSeparator();
  127. m_contextMenu->addAction(m_kickUserAction);
  128. // 连接信号
  129. connect(m_privateMessageAction, &QAction::triggered, [this]() {
  130. if (!m_selectedUserId.isEmpty()) {
  131. emit privateMessageRequested(m_selectedUserId, m_selectedUsername);
  132. }
  133. });
  134. connect(m_viewProfileAction, &QAction::triggered, [this]() {
  135. if (!m_selectedUserId.isEmpty()) {
  136. emit userProfileRequested(m_selectedUserId, m_selectedUsername);
  137. }
  138. });
  139. connect(m_kickUserAction, &QAction::triggered, [this]() {
  140. // TODO: 实现踢出用户功能
  141. qDebug() << "踢出用户:" << m_selectedUsername;
  142. });
  143. }
  144. void OnlineUsersWidget::applyStyles()
  145. {
  146. // setStyleSheet("#titleLabel {"
  147. // " font-size: 14px;"
  148. // " font-weight: bold;"
  149. // " color: #2c3e50;"
  150. // "}"
  151. // "#countLabel {"
  152. // " font-size: 12px;"
  153. // " color: #7f8c8d;"
  154. // " margin-left: 5px;"
  155. // "}"
  156. // "#searchEdit {"
  157. // " padding: 6px;"
  158. // " border: 1px solid #bdc3c7;"
  159. // " border-radius: 3px;"
  160. // " font-size: 12px;"
  161. // "}"
  162. // "#usersTable {"
  163. // " border: 1px solid #bdc3c7;"
  164. // " border-radius: 3px;"
  165. // " background-color: white;"
  166. // " gridline-color: #ecf0f1;"
  167. // "}"
  168. // "#usersTable::item {"
  169. // " padding: 8px;"
  170. // " border-bottom: 1px solid #ecf0f1;"
  171. // "}"
  172. // "#usersTable::item:selected {"
  173. // " background-color: #3498db;"
  174. // " color: white;"
  175. // "}"
  176. // "#usersTable::item:hover {"
  177. // " background-color: #ecf0f1;"
  178. // "}"
  179. // "#emptyStateLabel {"
  180. // " font-size: 14px;"
  181. // " color: #7f8c8d;"
  182. // " padding: 40px 20px;"
  183. // " background-color: #f8f9fa;"
  184. // " border: 1px solid #e9ecef;"
  185. // " border-radius: 6px;"
  186. // " margin: 20px 0;"
  187. // "}");
  188. }
  189. void OnlineUsersWidget::addUser(const OnlineUser &user)
  190. {
  191. // 检查用户是否已存在
  192. int existingRow = findUserRow(user.userId);
  193. if (existingRow >= 0) {
  194. // 更新现有用户
  195. m_users[existingRow] = user;
  196. updateTableRow(existingRow, user);
  197. return;
  198. }
  199. // 添加新用户
  200. m_users.append(user);
  201. // 如果当前有过滤条件,检查是否匹配
  202. if (!m_currentFilter.isEmpty()) {
  203. if (!user.username.contains(m_currentFilter, Qt::CaseInsensitive)) {
  204. updateUserCountLabel();
  205. return;
  206. }
  207. }
  208. // 添加到表格
  209. int row = m_usersTable->rowCount();
  210. m_usersTable->insertRow(row);
  211. updateTableRow(row, user);
  212. updateUserCountLabel();
  213. // 确保表格可见(隐藏空状态)
  214. if (m_emptyStateLabel->isVisible()) {
  215. m_emptyStateLabel->hide();
  216. m_usersTable->show();
  217. }
  218. }
  219. void OnlineUsersWidget::removeUser(const QString &userId)
  220. {
  221. int row = findUserRow(userId);
  222. if (row >= 0) {
  223. m_users.removeAt(row);
  224. m_usersTable->removeRow(row);
  225. updateUserCountLabel();
  226. }
  227. }
  228. void OnlineUsersWidget::updateUserStatus(const QString &userId, const QString &status)
  229. {
  230. int userIndex = -1;
  231. for (int i = 0; i < m_users.size(); ++i) {
  232. if (m_users[i].userId == userId) {
  233. userIndex = i;
  234. break;
  235. }
  236. }
  237. if (userIndex >= 0) {
  238. m_users[userIndex].status = status;
  239. m_users[userIndex].lastSeen = QDateTime::currentDateTime();
  240. // 更新表格中对应的行
  241. int row = findUserRow(userId);
  242. if (row >= 0) {
  243. updateTableRow(row, m_users[userIndex]);
  244. }
  245. }
  246. }
  247. void OnlineUsersWidget::updateUserList(const QJsonArray &users)
  248. {
  249. clearUsers();
  250. for (const auto &value : users) {
  251. if (value.isObject()) {
  252. QJsonObject userObj = value.toObject();
  253. OnlineUser user;
  254. user.userId = userObj["id"].toString();
  255. user.username = userObj["username"].toString();
  256. user.status = userObj["status"].toString("在线");
  257. user.isAdmin = userObj["isAdmin"].toBool(false);
  258. if (userObj.contains("lastSeen")) {
  259. user.lastSeen = QDateTime::fromString(userObj["lastSeen"].toString(), Qt::ISODate);
  260. } else {
  261. user.lastSeen = QDateTime::currentDateTime();
  262. }
  263. addUser(user);
  264. }
  265. }
  266. }
  267. void OnlineUsersWidget::clearUsers()
  268. {
  269. m_users.clear();
  270. m_usersTable->setRowCount(0);
  271. updateUserCountLabel();
  272. }
  273. QList<OnlineUser> OnlineUsersWidget::getAllUsers() const
  274. {
  275. return m_users;
  276. }
  277. OnlineUser OnlineUsersWidget::getUser(const QString &userId) const
  278. {
  279. for (const auto &user : m_users) {
  280. if (user.userId == userId) {
  281. return user;
  282. }
  283. }
  284. return OnlineUser();
  285. }
  286. int OnlineUsersWidget::getUserCount() const
  287. {
  288. return m_users.size();
  289. }
  290. void OnlineUsersWidget::setSearchVisible(bool visible)
  291. {
  292. m_searchEdit->setVisible(visible);
  293. }
  294. void OnlineUsersWidget::filterUsers(const QString &keyword)
  295. {
  296. m_currentFilter = keyword;
  297. // 清空表格
  298. m_usersTable->setRowCount(0);
  299. // 重新添加匹配的用户
  300. for (const auto &user : m_users) {
  301. if (keyword.isEmpty() || user.username.contains(keyword, Qt::CaseInsensitive)) {
  302. int row = m_usersTable->rowCount();
  303. m_usersTable->insertRow(row);
  304. updateTableRow(row, user);
  305. }
  306. }
  307. updateUserCountLabel();
  308. }
  309. void OnlineUsersWidget::onTableDoubleClicked(int row, int column)
  310. {
  311. Q_UNUSED(column);
  312. if (row >= 0 && row < m_usersTable->rowCount()) {
  313. QTableWidgetItem *userItem = m_usersTable->item(row, 1); // 用户名列
  314. if (userItem) {
  315. QString username = userItem->text();
  316. // 从用户列表中找到对应的userId
  317. for (const auto &user : m_users) {
  318. if (user.username == username) {
  319. emit userDoubleClicked(user.userId, username);
  320. break;
  321. }
  322. }
  323. }
  324. }
  325. }
  326. void OnlineUsersWidget::onTableContextMenu(const QPoint &position)
  327. {
  328. QTableWidgetItem *item = m_usersTable->itemAt(position);
  329. if (!item)
  330. return;
  331. int row = item->row();
  332. QTableWidgetItem *userItem = m_usersTable->item(row, 1);
  333. if (!userItem)
  334. return;
  335. QString username = userItem->text();
  336. // 从用户列表中找到对应的userId
  337. for (const auto &user : m_users) {
  338. if (user.username == username) {
  339. m_selectedUserId = user.userId;
  340. m_selectedUsername = username;
  341. // 根据用户权限显示/隐藏菜单项
  342. m_kickUserAction->setVisible(user.isAdmin); // 示例:只有管理员能踢人
  343. QPoint globalPos = m_usersTable->mapToGlobal(position);
  344. emit userRightClicked(user.userId, username, globalPos);
  345. m_contextMenu->exec(globalPos);
  346. break;
  347. }
  348. }
  349. }
  350. void OnlineUsersWidget::onSearchTextChanged(const QString &text)
  351. {
  352. filterUsers(text);
  353. }
  354. void OnlineUsersWidget::onRefreshClicked()
  355. {
  356. if (!m_currentRoomId.isEmpty()) {
  357. refreshRoomUsers();
  358. } else {
  359. // 当没有房间ID时,显示空状态提示
  360. clearUsers();
  361. updateEmptyState();
  362. qDebug() << "没有选择房间,显示空状态提示";
  363. }
  364. }
  365. void OnlineUsersWidget::updateUserCountLabel()
  366. {
  367. int totalUsers = m_users.size();
  368. int displayedUsers = m_usersTable->rowCount();
  369. if (m_currentFilter.isEmpty()) {
  370. m_countLabel->setText(QString("(%1)").arg(totalUsers));
  371. } else {
  372. m_countLabel->setText(QString("(%1/%2)").arg(displayedUsers).arg(totalUsers));
  373. }
  374. }
  375. void OnlineUsersWidget::updateTableRow(int row, const OnlineUser &user)
  376. {
  377. // 状态列
  378. QTableWidgetItem *statusItem = new QTableWidgetItem(getStatusIcon(user.status) + " "
  379. + user.status);
  380. statusItem->setFlags(statusItem->flags() & ~Qt::ItemIsEditable);
  381. m_usersTable->setItem(row, 0, statusItem);
  382. // 用户名列
  383. QTableWidgetItem *nameItem = new QTableWidgetItem(user.username);
  384. nameItem->setFlags(nameItem->flags() & ~Qt::ItemIsEditable);
  385. if (user.isAdmin) {
  386. nameItem->setText(user.username + " (管理员)");
  387. nameItem->setForeground(QColor("#e74c3c"));
  388. }
  389. m_usersTable->setItem(row, 1, nameItem);
  390. // 最后活动时间列
  391. QString timeText = user.lastSeen.toString("hh:mm");
  392. QTableWidgetItem *timeItem = new QTableWidgetItem(timeText);
  393. timeItem->setFlags(timeItem->flags() & ~Qt::ItemIsEditable);
  394. m_usersTable->setItem(row, 2, timeItem);
  395. // 添加0-6列的统计数据
  396. for (int i = 0; i < 7; ++i) {
  397. QTableWidgetItem *statsItem = new QTableWidgetItem(QString::number(user.messageStats[i]));
  398. statsItem->setFlags(statsItem->flags() & ~Qt::ItemIsEditable);
  399. statsItem->setTextAlignment(Qt::AlignCenter);
  400. m_usersTable->setItem(row, i + 3, statsItem);
  401. }
  402. }
  403. int OnlineUsersWidget::findUserRow(const QString &userId) const
  404. {
  405. for (int i = 0; i < m_users.size(); ++i) {
  406. if (m_users[i].userId == userId) {
  407. // 在表格中查找对应行
  408. for (int row = 0; row < m_usersTable->rowCount(); ++row) {
  409. QTableWidgetItem *nameItem = m_usersTable->item(row, 1);
  410. if (nameItem && nameItem->text().contains(m_users[i].username)) {
  411. return row;
  412. }
  413. }
  414. break;
  415. }
  416. }
  417. return -1;
  418. }
  419. QString OnlineUsersWidget::getStatusIcon(const QString &status) const
  420. {
  421. if (status == "在线") {
  422. return "🟢";
  423. } else if (status == "离开") {
  424. return "🟡";
  425. } else if (status == "忙碌") {
  426. return "🔴";
  427. } else {
  428. return "⚪";
  429. }
  430. }
  431. void OnlineUsersWidget::updateEmptyState()
  432. {
  433. // 根据当前状态显示相应的空状态提示
  434. if (m_currentRoomId.isEmpty()) {
  435. m_emptyStateLabel->setText("请选择一个房间查看在线用户");
  436. m_emptyStateLabel->show();
  437. m_usersTable->hide();
  438. } else {
  439. m_emptyStateLabel->hide();
  440. m_usersTable->show();
  441. }
  442. }
  443. void OnlineUsersWidget::updateUserListFromRoomUsers(const QList<RoomUserInfo> &roomUsers)
  444. {
  445. // 保存现有用户的统计数据
  446. QHash<QString, OnlineUser> existingUsers;
  447. for (const auto &user : m_users) {
  448. existingUsers[user.userId] = user;
  449. }
  450. clearUsers();
  451. for (const auto &roomUser : roomUsers) {
  452. OnlineUser user;
  453. user.userId = roomUser.userId;
  454. user.username = roomUser.userName;
  455. user.status = "在线"; // 房间用户默认为在线状态
  456. user.lastSeen = QDateTime::currentDateTime();
  457. user.isAdmin = false; // 可以根据需要设置管理员状态
  458. // 如果用户之前存在,恢复其统计数据
  459. if (existingUsers.contains(user.userId)) {
  460. const OnlineUser &existingUser = existingUsers[user.userId];
  461. for (int i = 0; i < 7; ++i) {
  462. user.messageStats[i] = existingUser.messageStats[i];
  463. }
  464. user.isAdmin = existingUser.isAdmin; // 保持管理员状态
  465. }
  466. addUser(user);
  467. }
  468. }
  469. void OnlineUsersWidget::setCurrentRoomId(const QString &roomId)
  470. {
  471. m_currentRoomId = roomId;
  472. if (!roomId.isEmpty()) {
  473. refreshRoomUsers();
  474. } else {
  475. // 当房间ID为空时,显示空状态
  476. clearUsers();
  477. updateEmptyState();
  478. }
  479. }
  480. void OnlineUsersWidget::refreshRoomUsers()
  481. {
  482. if (m_currentRoomId.isEmpty()) {
  483. qDebug() << "房间ID为空,无法刷新用户列表";
  484. return;
  485. }
  486. qDebug() << "刷新房间用户列表,房间ID:" << m_currentRoomId;
  487. // 调用API获取房间用户列表
  488. QFuture<HttpResponse> future = getRoomUsersApi(m_currentRoomId);
  489. // 使用QtPromise处理异步响应
  490. QtPromise::QPromise<HttpResponse> roomUsersPromise = QtPromise::resolve(future);
  491. roomUsersPromise
  492. .then([this](const HttpResponse &response) {
  493. qDebug() << response.rawData;
  494. if (response.code == 0) {
  495. // 解析响应数据
  496. qDebug() << "response.data" << response.data;
  497. if (response.data.isArray()) {
  498. QJsonArray userArray = response.data.toArray();
  499. // 直接从数组解析用户数据
  500. QList<RoomUserInfo> roomUsers;
  501. for (const QJsonValue &value : userArray) {
  502. if (value.isObject()) {
  503. QJsonObject userObj = value.toObject();
  504. RoomUserInfo userInfo;
  505. userInfo.userId = userObj["userId"].toString();
  506. userInfo.userName = userObj["userName"].toString();
  507. userInfo.clientId = userObj["clientId"].toString();
  508. roomUsers.append(userInfo);
  509. }
  510. }
  511. // 更新用户列表
  512. updateUserListFromRoomUsers(roomUsers);
  513. qDebug() << "成功获取房间用户列表,用户数量:" << roomUsers.size();
  514. }
  515. } else {
  516. qDebug() << "获取房间用户列表失败:" << response.message;
  517. }
  518. })
  519. .fail([](const std::exception &e) { qDebug() << "获取房间用户列表异常:" << e.what(); });
  520. }
  521. void OnlineUsersWidget::onUserListUpdate(const QString &roomId, const QJsonArray &userList)
  522. {
  523. // 检查是否是当前房间的用户列表更新
  524. if (roomId != m_currentRoomId) {
  525. return;
  526. }
  527. qDebug() << "收到房间用户列表更新消息,房间ID:" << roomId << "用户数量:" << userList.size();
  528. // 将QJsonArray转换为RoomUserInfo列表
  529. QList<RoomUserInfo> roomUsers;
  530. for (const QJsonValue &value : userList) {
  531. if (value.isObject()) {
  532. QJsonObject userObj = value.toObject();
  533. RoomUserInfo userInfo;
  534. userInfo.userId = userObj["userId"].toString();
  535. userInfo.userName = userObj["userName"].toString();
  536. userInfo.clientId = userObj["clientId"].toString();
  537. roomUsers.append(userInfo);
  538. }
  539. }
  540. // 更新用户列表显示
  541. updateUserListFromRoomUsers(roomUsers);
  542. }
  543. // 统计功能方法 (从 StatsWidget 迁移)
  544. void OnlineUsersWidget::updateStats(const QJsonObject& statsData)
  545. {
  546. qDebug() << "[OnlineUsersWidget] 收到统计更新:" << statsData;
  547. // 解析data数组并更新用户统计数据
  548. if (statsData.contains("data") && statsData["data"].isArray()) {
  549. QJsonArray dataArray = statsData["data"].toArray();
  550. // 重置全局累计数据
  551. m_totalCount = 0;
  552. for (int i = 0; i < 7; ++i) {
  553. m_globalStats[i] = 0;
  554. }
  555. QDateTime latestUpdate;
  556. // 遍历所有用户数据进行更新
  557. for (const QJsonValue& value : dataArray) {
  558. if (value.isObject()) {
  559. QJsonObject userStats = value.toObject();
  560. QString userId = userStats["userId"].toString();
  561. // 更新单个用户的统计数据
  562. updateUserStats(userId, userStats);
  563. // 累加到全局统计
  564. m_totalCount += userStats["totalCount"].toInt();
  565. for (int i = 0; i < 7; ++i) {
  566. QString typeKey = QString("type%1Count").arg(i);
  567. m_globalStats[i] += userStats[typeKey].toInt();
  568. }
  569. // 找到最新的更新时间
  570. QString lastUpdateStr = userStats["lastUpdate"].toString();
  571. QDateTime userUpdate = QDateTime::fromString(lastUpdateStr, Qt::ISODate);
  572. if (userUpdate.isValid() && (!latestUpdate.isValid() || userUpdate > latestUpdate)) {
  573. latestUpdate = userUpdate;
  574. }
  575. }
  576. }
  577. m_lastStatsUpdate = latestUpdate;
  578. qDebug() << "[OnlineUsersWidget] 全局统计信息已更新 - 总数:" << m_totalCount
  579. << "类型0-6:" << m_globalStats[0] << m_globalStats[1] << m_globalStats[2]
  580. << m_globalStats[3] << m_globalStats[4] << m_globalStats[5] << m_globalStats[6]
  581. << "用户数:" << dataArray.size();
  582. }
  583. }
  584. void OnlineUsersWidget::updateUserStats(const QString &userId, const QJsonObject& userStats)
  585. {
  586. // 查找用户
  587. int userIndex = -1;
  588. for (int i = 0; i < m_users.size(); ++i) {
  589. if (m_users[i].userId == userId) {
  590. userIndex = i;
  591. break;
  592. }
  593. }
  594. if (userIndex >= 0) {
  595. // 更新用户的统计数据
  596. for (int i = 0; i < 7; ++i) {
  597. QString typeKey = QString("type%1Count").arg(i);
  598. m_users[userIndex].messageStats[i] = userStats[typeKey].toInt();
  599. }
  600. // 更新表格显示
  601. int row = findUserRow(userId);
  602. if (row >= 0) {
  603. updateTableRow(row, m_users[userIndex]);
  604. }
  605. qDebug() << "[OnlineUsersWidget] 用户统计已更新:" << userId
  606. << "统计数据:" << m_users[userIndex].messageStats[0]
  607. << m_users[userIndex].messageStats[1] << m_users[userIndex].messageStats[2]
  608. << m_users[userIndex].messageStats[3] << m_users[userIndex].messageStats[4]
  609. << m_users[userIndex].messageStats[5] << m_users[userIndex].messageStats[6];
  610. } else {
  611. qDebug() << "[OnlineUsersWidget] 未找到用户:" << userId;
  612. }
  613. }