diff --git a/src/Client/.promptx/pouch.json b/src/Client/.promptx/pouch.json
index 1a522c1..243cf8d 100644
--- a/src/Client/.promptx/pouch.json
+++ b/src/Client/.promptx/pouch.json
@@ -1,5 +1,5 @@
{
- "currentState": "memory_saved",
+ "currentState": "role_activated_with_memory",
"stateHistory": [
{
"from": "initial",
@@ -92,7 +92,31 @@
"--tags",
"项目进展 Qt开发 BattlefieldExplorationSystem 设备管理 地图集成 Phase4完成"
]
+ },
+ {
+ "from": "memory_saved",
+ "command": "init",
+ "timestamp": "2025-06-21T10:53:24.434Z",
+ "args": [
+ {
+ "workingDirectory": "/home/hzk/Software_Architecture/src/Client"
+ }
+ ]
+ },
+ {
+ "from": "initialized",
+ "command": "welcome",
+ "timestamp": "2025-06-21T10:53:28.298Z",
+ "args": []
+ },
+ {
+ "from": "role_discovery",
+ "command": "action",
+ "timestamp": "2025-06-21T10:53:32.598Z",
+ "args": [
+ "qt-ui-developer"
+ ]
}
],
- "lastUpdated": "2025-06-19T10:34:01.577Z"
+ "lastUpdated": "2025-06-21T10:53:32.605Z"
}
diff --git a/src/Client/.promptx/resource/project.registry.json b/src/Client/.promptx/resource/project.registry.json
index aa6af00..e740bfc 100644
--- a/src/Client/.promptx/resource/project.registry.json
+++ b/src/Client/.promptx/resource/project.registry.json
@@ -4,8 +4,8 @@
"metadata": {
"version": "2.0.0",
"description": "project 级资源注册表",
- "createdAt": "2025-06-19T10:21:01.701Z",
- "updatedAt": "2025-06-19T10:21:01.702Z",
+ "createdAt": "2025-06-21T10:53:24.437Z",
+ "updatedAt": "2025-06-21T10:53:24.439Z",
"resourceCount": 1
},
"resources": [
@@ -17,9 +17,9 @@
"description": "专业角色,提供特定领域的专业能力",
"reference": "@project://.promptx/resource/domain/qt-ui-developer/qt-ui-developer.role.md",
"metadata": {
- "createdAt": "2025-06-19T10:21:01.701Z",
- "updatedAt": "2025-06-19T10:21:01.701Z",
- "scannedAt": "2025-06-19T10:21:01.701Z"
+ "createdAt": "2025-06-21T10:53:24.438Z",
+ "updatedAt": "2025-06-21T10:53:24.438Z",
+ "scannedAt": "2025-06-21T10:53:24.438Z"
}
}
],
diff --git a/src/Client/BattlefieldExplorationSystem b/src/Client/BattlefieldExplorationSystem
index 5800020..e20da90 100755
Binary files a/src/Client/BattlefieldExplorationSystem and b/src/Client/BattlefieldExplorationSystem differ
diff --git a/src/Client/forms/dialogs/DeviceDialog.ui b/src/Client/forms/dialogs/DeviceDialog.ui
index e108ba4..51fe919 100644
--- a/src/Client/forms/dialogs/DeviceDialog.ui
+++ b/src/Client/forms/dialogs/DeviceDialog.ui
@@ -6,14 +6,539 @@
0
0
- 1184
- 734
+ 800
+ 600
- Dialog
+ 设备详情
+
+ true
+
+
+
+ 8
+
+
+ 12
+
+
+ 12
+
+
+ 12
+
+
+ 12
+
+ -
+
+
+ 12
+
+
-
+
+
+
+ 64
+ 64
+
+
+
+
+ 64
+ 64
+
+
+
+ 🤖
+
+
+ Qt::AlignCenter
+
+
+ font-size: 48px;
+
+
+
+ -
+
+
+ 4
+
+
-
+
+
+
+ 18
+ 75
+ true
+
+
+
+ 设备名称
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 设备ID: DEV001
+
+
+
+ -
+
+
+
+ 12
+
+
+
+ 设备类型: 无人机
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+
+ 80
+ 30
+
+
+
+
+ 75
+ true
+
+
+
+ 在线
+
+
+ Qt::AlignCenter
+
+
+ color: white; background-color: green; border-radius: 15px; padding: 5px;
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ -
+
+
+ 0
+
+
+
+ 基本信息
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+ 12
+
+
+ 8
+
+
+ 16
+
+
+ 12
+
+
+ 16
+
+
+ 12
+
+
-
+
+
+ IP地址:
+
+
+
+ -
+
+
+ 192.168.1.100
+
+
+
+ -
+
+
+ 端口:
+
+
+
+ -
+
+
+ 8080
+
+
+
+ -
+
+
+ 位置坐标:
+
+
+
+ -
+
+
+ 116.40, 39.90
+
+
+
+ -
+
+
+ 信号强度:
+
+
+
+ -
+
+
+ 85
+
+
+ %p%
+
+
+
+ -
+
+
+ 电池电量:
+
+
+
+ -
+
+
+ 95
+
+
+ %p%
+
+
+
+ -
+
+
+ 固件版本:
+
+
+
+ -
+
+
+ v2.1.0
+
+
+
+
+
+
+
+ 状态信息
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ Qt::AlignHCenter|Qt::AlignTop
+
+
+ 12
+
+
+ 8
+
+
+ 16
+
+
+ 12
+
+
+ 16
+
+
+ 12
+
+ -
+
+
+ 最后心跳:
+
+
+
+ -
+
+
+ 2024-01-01 12:30:45
+
+
+
+ -
+
+
+ 创建时间:
+
+
+
+ -
+
+
+ 2024-01-01 08:00:00
+
+
+
+ -
+
+
+ 更新时间:
+
+
+
+ -
+
+
+ 2024-01-01 12:30:45
+
+
+
+ -
+
+
+ 运行时长:
+
+
+
+ -
+
+
+ 4小时30分钟
+
+
+
+
+
+
+
+ 操作控制
+
+
+
+ 8
+
+
+ 12
+
+
+ 12
+
+
+ 12
+
+
+ 12
+
+ -
+
+
+ 8
+
+
-
+
+
+ 连接
+
+
+
+ -
+
+
+ 断开
+
+
+
+ -
+
+
+ 定位
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+
+
+ -
+
+
+ 操作日志
+
+
+
+ 6
+
+
+ 8
+
+
+ 8
+
+
+ 8
+
+
+ 8
+
+
-
+
+
+ true
+
+
+ QAbstractItemView::SelectRows
+
+
+
+ 时间
+
+
+
+
+ 操作
+
+
+
+
+ 结果
+
+
+
+
+ 操作员
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ 8
+
+
-
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ 刷新
+
+
+
+ -
+
+
+ 关闭
+
+
+
+
+
+
-
+
+
+ closeButton
+ clicked()
+ DeviceDialog
+ accept()
+
+
+ 745
+ 569
+
+
+ 399
+ 299
+
+
+
+
diff --git a/src/Client/include/ui/dialogs/DeviceDialog.h b/src/Client/include/ui/dialogs/DeviceDialog.h
index 515851f..0ab6bff 100644
--- a/src/Client/include/ui/dialogs/DeviceDialog.h
+++ b/src/Client/include/ui/dialogs/DeviceDialog.h
@@ -2,6 +2,11 @@
#define DEVICEDIALOG_H
#include
+#include
+#include
+#include
+#include
+#include
QT_BEGIN_NAMESPACE
namespace Ui {
@@ -9,6 +14,11 @@ class DeviceDialog;
}
QT_END_NAMESPACE
+/**
+ * @brief 设备详情对话框
+ *
+ * 显示设备的详细信息,包括基本信息、状态信息和操作日志
+ */
class DeviceDialog : public QDialog
{
Q_OBJECT
@@ -17,10 +27,130 @@ public:
explicit DeviceDialog(QWidget *parent = nullptr);
~DeviceDialog();
- void addDeviceInfo(QString name, QString type, QString status, QString position);
+ /**
+ * @brief 设置设备详细信息
+ * @param deviceId 设备ID
+ * @param name 设备名称
+ * @param type 设备类型
+ * @param ip IP地址
+ * @param port 端口号
+ * @param longitude 经度
+ * @param latitude 纬度
+ * @param state 设备状态
+ * @param signalStrength 信号强度
+ * @param batteryLevel 电池电量
+ * @param firmwareVersion 固件版本
+ * @param lastHeartbeat 最后心跳时间
+ * @param createdAt 创建时间
+ * @param updatedAt 更新时间
+ */
+ void setDeviceInfo(const QString &deviceId, const QString &name, const QString &type,
+ const QString &ip, int port, double longitude, double latitude,
+ int state, int signalStrength, int batteryLevel,
+ const QString &firmwareVersion, const QString &lastHeartbeat,
+ const QString &createdAt, const QString &updatedAt);
+
+ /**
+ * @brief 加载设备操作日志
+ * @param deviceId 设备ID
+ */
+ void loadOperationLogs(const QString &deviceId);
+
+ /**
+ * @brief 刷新设备信息
+ */
+ void refreshDeviceInfo();
+
+public slots:
+ /**
+ * @brief 连接设备
+ */
+ void onConnectClicked();
+
+ /**
+ * @brief 断开设备
+ */
+ void onDisconnectClicked();
+
+ /**
+ * @brief 定位设备
+ */
+ void onLocateClicked();
+
+ /**
+ * @brief 刷新按钮点击
+ */
+ void onRefreshClicked();
+
+signals:
+ /**
+ * @brief 请求连接设备信号
+ * @param deviceId 设备ID
+ */
+ void deviceConnectRequested(const QString &deviceId);
+
+ /**
+ * @brief 请求断开设备信号
+ * @param deviceId 设备ID
+ */
+ void deviceDisconnectRequested(const QString &deviceId);
+
+ /**
+ * @brief 请求定位设备信号
+ * @param deviceId 设备ID
+ */
+ void deviceLocationRequested(const QString &deviceId);
+
+private:
+ /**
+ * @brief 初始化UI样式
+ */
+ void setupStyle();
+
+ /**
+ * @brief 连接信号槽
+ */
+ void connectSignals();
+
+ /**
+ * @brief 根据设备类型设置图标
+ * @param type 设备类型
+ */
+ void setDeviceIcon(const QString &type);
+
+ /**
+ * @brief 根据状态设置状态标签
+ * @param state 状态值
+ */
+ void setStatusLabel(int state);
+
+ /**
+ * @brief 计算运行时长
+ * @param createdTime 创建时间
+ * @return 运行时长字符串
+ */
+ QString calculateWorkingTime(const QString &createdTime);
+
+ /**
+ * @brief 初始化操作日志表格
+ */
+ void initializeOperationLogTable();
+
+ /**
+ * @brief 记录操作日志
+ * @param operation 操作类型
+ * @param operatorName 操作员名称
+ */
+ void logOperation(const QString &operation, const QString &operatorName);
+
+ /**
+ * @brief 设置高对比度字体
+ */
+ void setHighContrastFonts();
private:
Ui::DeviceDialog *ui;
+ QString m_currentDeviceId; ///< 当前显示的设备ID
};
#endif // DEVICEDIALOG_H
\ No newline at end of file
diff --git a/src/Client/src/ui/dialogs/DeviceDialog.cpp b/src/Client/src/ui/dialogs/DeviceDialog.cpp
index 24e1d12..b30563a 100644
--- a/src/Client/src/ui/dialogs/DeviceDialog.cpp
+++ b/src/Client/src/ui/dialogs/DeviceDialog.cpp
@@ -1,18 +1,52 @@
+/**
+ * @file DeviceDialog.cpp
+ * @brief 设备详情对话框实现
+ * @author CasualtySightPlus Team
+ * @date 2024-01-01
+ * @version 2.0
+ */
+
#include "ui/dialogs/DeviceDialog.h"
#include "build/ui_DeviceDialog.h"
-#include
-#include
-#include
+
+// Qt headers
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// Qt SQL headers
+#include
+#include
+#include
DeviceDialog::DeviceDialog(QWidget *parent) :
QDialog(parent),
ui(new Ui::DeviceDialog)
{
ui->setupUi(this);
- setWindowTitle("机器人列表");
- setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
- setAttribute(Qt::WA_TranslucentBackground);
- setStyleSheet("background-color: rgba(255, 255, 255, 150);"); // 设置透明度为 150 的白色背景
+
+ // 设置窗口属性
+ setWindowTitle("设备详情");
+ setWindowFlags(Qt::Dialog | Qt::WindowTitleHint | Qt::WindowCloseButtonHint);
+ setModal(true);
+
+ // 初始化UI样式
+ setupStyle();
+
+ // 连接信号槽
+ connectSignals();
+
+ // 初始化操作日志表格
+ initializeOperationLogTable();
+
+ // 强制设置高对比度字体
+ setHighContrastFonts();
+
+ qDebug() << "DeviceDialog created successfully";
}
DeviceDialog::~DeviceDialog()
@@ -20,18 +54,606 @@ DeviceDialog::~DeviceDialog()
delete ui;
}
-void DeviceDialog::addDeviceInfo(QString name, QString type, QString status, QString position)
+void DeviceDialog::setDeviceInfo(const QString &deviceId, const QString &name, const QString &type,
+ const QString &ip, int port, double longitude, double latitude,
+ int state, int signalStrength, int batteryLevel,
+ const QString &firmwareVersion, const QString &lastHeartbeat,
+ const QString &createdAt, const QString &updatedAt)
+{
+ m_currentDeviceId = deviceId;
+
+ // 设置设备图标
+ setDeviceIcon(type);
+
+ // 设置基本信息
+ ui->deviceNameLabel->setText(name);
+ ui->deviceIdLabel->setText(QString("设备ID: %1").arg(deviceId));
+
+ QString typeDisplayName = (type == "uav") ? "无人机" :
+ (type == "dog") ? "地面机器人" : "未知设备";
+ ui->deviceTypeLabel->setText(QString("设备类型: %1").arg(typeDisplayName));
+
+ // 设置状态标签
+ setStatusLabel(state);
+
+ // 定义数值标签的强对比度样式
+ QString valueStyle = "QLabel {"
+ " color: rgb(255, 255, 255);" // 纯白色字体
+ " background: rgba(100, 200, 255, 0.2);"
+ " border: 1px solid rgba(100, 200, 255, 0.4);"
+ " border-radius: 4px;"
+ " padding: 4px 8px;"
+ " font-weight: bold;"
+ " font-size: 13px;"
+ "}";
+
+ // 设置网络信息 - 直接应用样式
+ ui->ipAddressValue->setText(ip);
+ ui->ipAddressValue->setStyleSheet(valueStyle);
+ ui->portValue->setText(QString::number(port));
+ ui->portValue->setStyleSheet(valueStyle);
+
+ // 设置位置信息 - 直接应用样式
+ ui->locationValue->setText(QString("%1, %2").arg(longitude, 0, 'f', 6).arg(latitude, 0, 'f', 6));
+ ui->locationValue->setStyleSheet(valueStyle);
+
+ // 设置信号强度和电池电量
+ ui->signalStrengthBar->setValue(signalStrength);
+ ui->batteryLevelBar->setValue(batteryLevel);
+
+ // 设置固件版本 - 直接应用样式
+ ui->firmwareValue->setText(firmwareVersion.isEmpty() ? "未知" : firmwareVersion);
+ ui->firmwareValue->setStyleSheet(valueStyle);
+
+ // 设置时间信息 - 直接应用样式
+ ui->lastHeartbeatValue->setText(lastHeartbeat.isEmpty() ? "无数据" : lastHeartbeat);
+ ui->lastHeartbeatValue->setStyleSheet(valueStyle);
+ ui->createdAtValue->setText(createdAt);
+ ui->createdAtValue->setStyleSheet(valueStyle);
+ ui->updatedAtValue->setText(updatedAt);
+ ui->updatedAtValue->setStyleSheet(valueStyle);
+
+ // 计算并设置运行时长 - 直接应用样式
+ ui->workingTimeValue->setText(calculateWorkingTime(createdAt));
+ ui->workingTimeValue->setStyleSheet(valueStyle);
+
+ // 设置所有标签的样式
+ QString labelStyle = "QLabel {"
+ " color: rgb(255, 255, 255);" // 纯白色
+ " font-weight: 600;"
+ " font-size: 13px;"
+ "}";
+
+ // 应用到所有标签标题
+ ui->label_ip->setStyleSheet(labelStyle);
+ ui->label_port->setStyleSheet(labelStyle);
+ ui->label_location->setStyleSheet(labelStyle);
+ ui->label_signal->setStyleSheet(labelStyle);
+ ui->label_battery->setStyleSheet(labelStyle);
+ ui->label_firmware->setStyleSheet(labelStyle);
+ ui->label_lastHeartbeat->setStyleSheet(labelStyle);
+ ui->label_createdAt->setStyleSheet(labelStyle);
+ ui->label_updatedAt->setStyleSheet(labelStyle);
+ ui->label_workingTime->setStyleSheet(labelStyle);
+
+ // 设置头部标签样式
+ QString headerStyle = "QLabel {"
+ " color: rgb(255, 255, 255);"
+ " font-weight: bold;"
+ "}";
+ ui->deviceNameLabel->setStyleSheet(headerStyle);
+ ui->deviceIdLabel->setStyleSheet(headerStyle);
+ ui->deviceTypeLabel->setStyleSheet(headerStyle);
+
+ // 加载操作日志
+ loadOperationLogs(deviceId);
+
+ qDebug() << "Device info set for:" << deviceId << name;
+}
+
+void DeviceDialog::loadOperationLogs(const QString &deviceId)
+{
+ // 连接数据库
+ QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "DeviceDialog_LogQuery");
+ db.setHostName("localhost");
+ db.setPort(3306);
+ db.setDatabaseName("Client");
+ db.setUserName("root");
+ db.setPassword("hzk200407140238");
+
+ if (!db.open()) {
+ qWarning() << "Failed to connect to database for operation logs:" << db.lastError().text();
+ return;
+ }
+
+ // 查询操作日志
+ QSqlQuery query(db);
+ QString sql = "SELECT operation_time, operation, operation_result, operator "
+ "FROM device_operation_logs "
+ "WHERE device_id = ? "
+ "ORDER BY operation_time DESC "
+ "LIMIT 50";
+
+ query.prepare(sql);
+ query.addBindValue(deviceId);
+
+ if (!query.exec()) {
+ qWarning() << "Failed to query operation logs:" << query.lastError().text();
+ db.close();
+ return;
+ }
+
+ // 清空表格
+ ui->operationLogTable->setRowCount(0);
+
+ // 填充数据
+ int row = 0;
+ while (query.next()) {
+ ui->operationLogTable->insertRow(row);
+
+ QString operationTime = query.value(0).toString();
+ QString operation = query.value(1).toString();
+ QString result = query.value(2).toString();
+ QString operatorName = query.value(3).toString();
+
+ ui->operationLogTable->setItem(row, 0, new QTableWidgetItem(operationTime));
+ ui->operationLogTable->setItem(row, 1, new QTableWidgetItem(operation));
+ ui->operationLogTable->setItem(row, 2, new QTableWidgetItem(result));
+ ui->operationLogTable->setItem(row, 3, new QTableWidgetItem(operatorName.isEmpty() ? "系统" : operatorName));
+
+ // 根据操作结果设置颜色
+ QTableWidgetItem *resultItem = ui->operationLogTable->item(row, 2);
+ if (result == "success") {
+ resultItem->setBackground(QBrush(QColor(144, 238, 144))); // 浅绿色
+ } else if (result == "failed") {
+ resultItem->setBackground(QBrush(QColor(255, 182, 193))); // 浅红色
+ } else if (result == "timeout") {
+ resultItem->setBackground(QBrush(QColor(255, 255, 224))); // 浅黄色
+ }
+
+ row++;
+ }
+
+ db.close();
+
+ qDebug() << "Loaded" << row << "operation log entries for device" << deviceId;
+}
+
+void DeviceDialog::refreshDeviceInfo()
+{
+ if (m_currentDeviceId.isEmpty()) {
+ return;
+ }
+
+ // 连接数据库
+ QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "DeviceDialog_Refresh");
+ db.setHostName("localhost");
+ db.setPort(3306);
+ db.setDatabaseName("Client");
+ db.setUserName("root");
+ db.setPassword("hzk200407140238");
+
+ if (!db.open()) {
+ qWarning() << "Failed to connect to database for refresh:" << db.lastError().text();
+ QMessageBox::warning(this, "错误", "无法连接到数据库");
+ return;
+ }
+
+ // 查询设备信息
+ QSqlQuery query(db);
+ QString sql = "SELECT name, device_type, ip, port, longitude, latitude, state, "
+ "signal_strength, battery_level, firmware_version, last_heartbeat, "
+ "created_at, updated_at "
+ "FROM devices WHERE id = ?";
+
+ query.prepare(sql);
+ query.addBindValue(m_currentDeviceId);
+
+ if (!query.exec() || !query.next()) {
+ qWarning() << "Failed to query device info:" << query.lastError().text();
+ QMessageBox::warning(this, "错误", "无法获取设备信息");
+ db.close();
+ return;
+ }
+
+ // 更新设备信息
+ QString name = query.value("name").toString();
+ QString type = query.value("device_type").toString();
+ QString ip = query.value("ip").toString();
+ int port = query.value("port").toInt();
+ double longitude = query.value("longitude").toDouble();
+ double latitude = query.value("latitude").toDouble();
+ int state = query.value("state").toInt();
+ int signalStrength = query.value("signal_strength").toInt();
+ int batteryLevel = query.value("battery_level").toInt();
+ QString firmwareVersion = query.value("firmware_version").toString();
+ QString lastHeartbeat = query.value("last_heartbeat").toString();
+ QString createdAt = query.value("created_at").toString();
+ QString updatedAt = query.value("updated_at").toString();
+
+ db.close();
+
+ // 更新显示
+ setDeviceInfo(m_currentDeviceId, name, type, ip, port, longitude, latitude,
+ state, signalStrength, batteryLevel, firmwareVersion,
+ lastHeartbeat, createdAt, updatedAt);
+
+ QMessageBox::information(this, "刷新完成", "设备信息已更新");
+}
+
+void DeviceDialog::onConnectClicked()
+{
+ if (!m_currentDeviceId.isEmpty()) {
+ emit deviceConnectRequested(m_currentDeviceId);
+
+ // 记录操作日志
+ logOperation("connect", "用户操作");
+ }
+}
+
+void DeviceDialog::onDisconnectClicked()
+{
+ if (!m_currentDeviceId.isEmpty()) {
+ emit deviceDisconnectRequested(m_currentDeviceId);
+
+ // 记录操作日志
+ logOperation("disconnect", "用户操作");
+ }
+}
+
+void DeviceDialog::onLocateClicked()
+{
+ if (!m_currentDeviceId.isEmpty()) {
+ emit deviceLocationRequested(m_currentDeviceId);
+
+ // 记录操作日志
+ logOperation("locate", "用户操作");
+ }
+}
+
+void DeviceDialog::onRefreshClicked()
+{
+ refreshDeviceInfo();
+}
+
+void DeviceDialog::setupStyle()
+{
+ // 设置对话框整体样式
+ setStyleSheet(
+ "QDialog {"
+ " background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1,"
+ " stop:0 rgb(20, 30, 40), stop:1 rgb(30, 40, 50));"
+ " color: rgb(255, 255, 255);" // 纯白色字体
+ "}"
+
+ // 标签样式 - 最强对比度
+ "QLabel {"
+ " color: rgb(255, 255, 255);" // 纯白色
+ " background: transparent;"
+ " font-size: 14px;" // 增大字体
+ " font-weight: 600;" // 加粗
+ " padding: 3px 6px;" // 适当内边距
+ "}"
+
+ // 表单布局样式 - 更紧凑
+ "QFormLayout {"
+ " spacing: 8px;" // 减少行间距
+ "}"
+
+ // 数值标签样式 - 突出显示
+ "QLabel[class='value-label'] {"
+ " color: rgb(100, 200, 255);" // 蓝色突出显示数值
+ " font-weight: 600;"
+ " background: rgba(100, 200, 255, 0.1);"
+ " border: 1px solid rgba(100, 200, 255, 0.2);"
+ " border-radius: 3px;"
+ " padding: 4px 8px;"
+ " margin: 1px;"
+ "}"
+
+ // 进度条样式 - 更清晰
+ "QProgressBar {"
+ " border: 2px solid rgba(100, 200, 255, 0.4);"
+ " border-radius: 6px;"
+ " text-align: center;"
+ " background-color: rgba(45, 65, 95, 0.4);"
+ " color: rgb(255, 255, 255);" // 白色文字
+ " font-weight: bold;"
+ " font-size: 12px;"
+ " min-height: 20px;" // 减少高度使更紧凑
+ " max-height: 20px;"
+ "}"
+ "QProgressBar::chunk {"
+ " background: qlineargradient(x1:0, y1:0, x2:1, y2:0,"
+ " stop:0 rgba(100, 200, 255, 0.8),"
+ " stop:1 rgba(50, 150, 255, 1.0));"
+ " border-radius: 4px;"
+ "}"
+
+ // 按钮样式 - 更清晰
+ "QPushButton {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
+ " stop:0 rgba(45, 65, 95, 0.9), "
+ " stop:1 rgba(25, 40, 65, 0.9));"
+ " color: rgb(255, 255, 255);" // 纯白字体
+ " border: 2px solid rgba(100, 200, 255, 0.6);"
+ " padding: 6px 12px;" // 减少按钮内边距
+ " border-radius: 5px;"
+ " font-weight: bold;"
+ " font-size: 12px;"
+ " min-height: 24px;" // 减少按钮高度
+ "}"
+ "QPushButton:hover {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
+ " stop:0 rgba(100, 200, 255, 0.8), "
+ " stop:1 rgba(45, 120, 180, 0.8));"
+ " border: 2px solid rgba(100, 200, 255, 1.0);"
+ " color: rgb(255, 255, 255);"
+ "}"
+ "QPushButton:pressed {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1, "
+ " stop:0 rgba(100, 200, 255, 1.0), "
+ " stop:1 rgba(45, 120, 180, 1.0));"
+ "}"
+
+ // 选项卡样式 - 更清晰
+ "QTabWidget::pane {"
+ " border: 1px solid rgba(100, 200, 255, 0.4);"
+ " background: rgba(15, 22, 32, 0.6);"
+ " margin-top: 2px;" // 减少顶部边距
+ "}"
+ "QTabBar::tab {"
+ " background: rgba(45, 65, 95, 0.7);"
+ " color: rgb(220, 230, 242);"
+ " padding: 6px 12px;" // 减少选项卡内边距
+ " margin-right: 1px;"
+ " border-top-left-radius: 4px;"
+ " border-top-right-radius: 4px;"
+ " font-size: 12px;"
+ " font-weight: 600;"
+ " min-height: 20px;"
+ "}"
+ "QTabBar::tab:selected {"
+ " background: rgba(100, 200, 255, 0.9);"
+ " color: rgb(255, 255, 255);"
+ "}"
+ "QTabBar::tab:hover:!selected {"
+ " background: rgba(100, 200, 255, 0.5);"
+ "}"
+
+ // 表格样式 - 最强对比度
+ "QTableWidget {"
+ " background-color: rgba(10, 15, 25, 0.95);"
+ " alternate-background-color: rgba(20, 25, 35, 0.95);"
+ " gridline-color: rgba(100, 200, 255, 0.4);"
+ " color: rgb(255, 255, 255);" // 纯白色
+ " font-size: 12px;" // 增大字体
+ " font-weight: 500;"
+ " selection-background-color: rgba(100, 200, 255, 0.6);"
+ "}"
+ "QTableWidget::item {"
+ " padding: 4px 6px;" // 减少单元格内边距
+ " border: none;"
+ "}"
+ "QHeaderView::section {"
+ " background-color: rgba(45, 65, 95, 0.9);"
+ " color: rgb(255, 255, 255);"
+ " padding: 6px 8px;" // 减少表头内边距
+ " border: 1px solid rgba(100, 200, 255, 0.4);"
+ " font-weight: bold;"
+ " font-size: 11px;"
+ "}"
+
+ // 分组框样式
+ "QGroupBox {"
+ " color: rgb(240, 248, 255);"
+ " font-weight: bold;"
+ " font-size: 12px;"
+ " border: 2px solid rgba(100, 200, 255, 0.4);"
+ " border-radius: 5px;"
+ " margin-top: 8px;" // 减少顶部边距
+ " padding-top: 5px;"
+ "}"
+ "QGroupBox::title {"
+ " subcontrol-origin: margin;"
+ " left: 8px;"
+ " padding: 0 4px 0 4px;"
+ " color: rgb(100, 200, 255);"
+ "}"
+ );
+}
+
+void DeviceDialog::connectSignals()
+{
+ // 连接按钮信号
+ connect(ui->connectButton, &QPushButton::clicked, this, &DeviceDialog::onConnectClicked);
+ connect(ui->disconnectButton, &QPushButton::clicked, this, &DeviceDialog::onDisconnectClicked);
+ connect(ui->locateButton, &QPushButton::clicked, this, &DeviceDialog::onLocateClicked);
+ connect(ui->refreshButton, &QPushButton::clicked, this, &DeviceDialog::onRefreshClicked);
+}
+
+void DeviceDialog::setDeviceIcon(const QString &type)
+{
+ if (type == "uav") {
+ ui->deviceIconLabel->setText("🚁");
+ ui->deviceIconLabel->setStyleSheet("font-size: 48px; color: #52C2F2;");
+ } else if (type == "dog") {
+ ui->deviceIconLabel->setText("🤖");
+ ui->deviceIconLabel->setStyleSheet("font-size: 48px; color: #52C2F2;");
+ } else {
+ ui->deviceIconLabel->setText("❓");
+ ui->deviceIconLabel->setStyleSheet("font-size: 48px; color: #888888;");
+ }
+}
+
+void DeviceDialog::setStatusLabel(int state)
{
- // 创建一个新的机器人信息部件
- QWidget *widget = new QWidget();
- QVBoxLayout *layout = new QVBoxLayout(widget);
- layout->addWidget(new QLabel("机器人名称:" + name));
- layout->addWidget(new QLabel("机器人类型:" + type));
- layout->addWidget(new QLabel("机器人状态:" + status));
- layout->addWidget(new QLabel("机器人位置:" + position));
- layout->addStretch();
- widget->setLayout(layout);
+ QString statusText;
+ QString statusStyle;
+
+ switch (state) {
+ case 0: // 离线
+ statusText = "离线";
+ statusStyle = "color: white; background-color: #FF6B6B; border-radius: 15px; padding: 5px;";
+ break;
+ case 1: // 在线
+ statusText = "在线";
+ statusStyle = "color: white; background-color: #4ECDC4; border-radius: 15px; padding: 5px;";
+ break;
+ case 2: // 工作中
+ statusText = "工作中";
+ statusStyle = "color: white; background-color: #45B7D1; border-radius: 15px; padding: 5px;";
+ break;
+ case 3: // 错误
+ statusText = "错误";
+ statusStyle = "color: white; background-color: #FF8C42; border-radius: 15px; padding: 5px;";
+ break;
+ default:
+ statusText = "未知";
+ statusStyle = "color: white; background-color: #888888; border-radius: 15px; padding: 5px;";
+ break;
+ }
+
+ ui->deviceStatusLabel->setText(statusText);
+ ui->deviceStatusLabel->setStyleSheet(statusStyle);
+}
+
+QString DeviceDialog::calculateWorkingTime(const QString &createdTime)
+{
+ if (createdTime.isEmpty()) {
+ return "未知";
+ }
+
+ QDateTime created = QDateTime::fromString(createdTime, "yyyy-MM-dd hh:mm:ss");
+ if (!created.isValid()) {
+ return "未知";
+ }
+
+ QDateTime now = QDateTime::currentDateTime();
+ qint64 secondsElapsed = created.secsTo(now);
+
+ int days = secondsElapsed / (24 * 3600);
+ int hours = (secondsElapsed % (24 * 3600)) / 3600;
+ int minutes = (secondsElapsed % 3600) / 60;
+
+ QString result;
+ if (days > 0) {
+ result += QString("%1天").arg(days);
+ }
+ if (hours > 0) {
+ result += QString("%1小时").arg(hours);
+ }
+ if (minutes > 0) {
+ result += QString("%1分钟").arg(minutes);
+ }
+
+ return result.isEmpty() ? "刚刚创建" : result;
+}
- // 将机器人信息部件添加到布局中
- layout->addWidget(widget);
+void DeviceDialog::initializeOperationLogTable()
+{
+ // 设置表格列宽
+ ui->operationLogTable->horizontalHeader()->setStretchLastSection(true);
+ ui->operationLogTable->setColumnWidth(0, 150); // 时间列
+ ui->operationLogTable->setColumnWidth(1, 100); // 操作列
+ ui->operationLogTable->setColumnWidth(2, 80); // 结果列
+
+ // 设置表格属性
+ ui->operationLogTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+ ui->operationLogTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+ ui->operationLogTable->setSortingEnabled(false);
+}
+
+void DeviceDialog::logOperation(const QString &operation, const QString &operatorName)
+{
+ // 记录操作到数据库
+ QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "DeviceDialog_LogOperation");
+ db.setHostName("localhost");
+ db.setPort(3306);
+ db.setDatabaseName("Client");
+ db.setUserName("root");
+ db.setPassword("hzk200407140238");
+
+ if (!db.open()) {
+ qWarning() << "Failed to connect to database for logging operation:" << db.lastError().text();
+ return;
+ }
+
+ QSqlQuery query(db);
+ QString sql = "INSERT INTO device_operation_logs (device_id, device_type, operation, operation_result, operator) "
+ "VALUES (?, (SELECT device_type FROM devices WHERE id = ? LIMIT 1), ?, 'success', ?)";
+
+ query.prepare(sql);
+ query.addBindValue(m_currentDeviceId);
+ query.addBindValue(m_currentDeviceId);
+ query.addBindValue(operation);
+ query.addBindValue(operatorName);
+
+ if (!query.exec()) {
+ qWarning() << "Failed to log operation:" << query.lastError().text();
+ } else {
+ qDebug() << "Operation logged:" << operation << "for device" << m_currentDeviceId;
+ }
+
+ db.close();
+}
+
+void DeviceDialog::setHighContrastFonts()
+{
+ // 创建高对比度字体
+ QFont boldFont = this->font();
+ boldFont.setPointSize(13);
+ boldFont.setWeight(QFont::Bold);
+
+ QFont normalFont = this->font();
+ normalFont.setPointSize(12);
+ normalFont.setWeight(QFont::Medium);
+
+ // 创建调色板确保文字是白色
+ QPalette palette = this->palette();
+ palette.setColor(QPalette::WindowText, QColor(255, 255, 255));
+ palette.setColor(QPalette::Text, QColor(255, 255, 255));
+ palette.setColor(QPalette::ButtonText, QColor(255, 255, 255));
+
+ // 应用到所有控件
+ this->setPalette(palette);
+
+ // 设置字体到对话框
+ this->setFont(normalFont);
+
+ // 递归设置所有子控件的字体和颜色
+ QList labels = this->findChildren();
+ for (QLabel* label : labels) {
+ label->setPalette(palette);
+ if (label->objectName().contains("Value") ||
+ label->objectName().contains("deviceName") ||
+ label->objectName().contains("deviceId") ||
+ label->objectName().contains("deviceType")) {
+ label->setFont(boldFont);
+ } else {
+ label->setFont(normalFont);
+ }
+
+ // 强制设置样式
+ label->setStyleSheet("QLabel { color: rgb(255, 255, 255); font-weight: bold; }");
+ }
+
+ // 设置表格字体
+ if (ui->operationLogTable) {
+ ui->operationLogTable->setFont(normalFont);
+ ui->operationLogTable->setPalette(palette);
+ ui->operationLogTable->setStyleSheet(
+ "QTableWidget { "
+ " color: rgb(255, 255, 255); "
+ " font-weight: 500; "
+ " background-color: rgba(10, 15, 25, 0.95); "
+ "} "
+ "QTableWidget::item { "
+ " color: rgb(255, 255, 255); "
+ " font-weight: 500; "
+ "}"
+ );
+ }
+
+ qDebug() << "High contrast fonts applied";
}
diff --git a/src/Client/src/ui/main/MainWindow.cpp b/src/Client/src/ui/main/MainWindow.cpp
index 02b9d22..234832e 100644
--- a/src/Client/src/ui/main/MainWindow.cpp
+++ b/src/Client/src/ui/main/MainWindow.cpp
@@ -8,6 +8,7 @@
#include "ui/main/MainWindow.h"
#include "build/ui_MainWindow.h"
+#include "ui/dialogs/DeviceDialog.h"
// Qt GUI头文件
#include
@@ -794,10 +795,79 @@ void MainWindow::onDeviceLocationRequested(const QString &deviceId)
void MainWindow::onDeviceDetailsRequested(const QString &deviceId)
{
qDebug() << "Device details requested for:" << deviceId;
- // TODO: 实现设备详情显示逻辑
- // 例如:打开设备详情对话框、显示设备参数等
- QMessageBox::information(this, "设备详情",
- QString("设备详情功能正在开发中\n设备ID: %1").arg(deviceId));
+
+ // 连接数据库获取设备详细信息
+ QSqlDatabase db = QSqlDatabase::addDatabase("QMYSQL", "MainWindow_DeviceDetails");
+ db.setHostName("localhost");
+ db.setPort(3306);
+ db.setDatabaseName("Client");
+ db.setUserName("root");
+ db.setPassword("hzk200407140238");
+
+ if (!db.open()) {
+ qWarning() << "Failed to connect to database for device details:" << db.lastError().text();
+ QMessageBox::warning(this, "错误", "无法连接到数据库");
+ return;
+ }
+
+ // 查询设备信息
+ QSqlQuery query(db);
+ QString sql = "SELECT name, device_type, ip, port, longitude, latitude, state, "
+ "signal_strength, battery_level, firmware_version, last_heartbeat, "
+ "created_at, updated_at "
+ "FROM devices WHERE id = ?";
+
+ query.prepare(sql);
+ query.addBindValue(deviceId);
+
+ if (!query.exec() || !query.next()) {
+ qWarning() << "Failed to query device details:" << query.lastError().text();
+ QMessageBox::warning(this, "错误",
+ QString("无法找到设备信息\n设备ID: %1").arg(deviceId));
+ db.close();
+ return;
+ }
+
+ // 获取设备信息
+ QString name = query.value("name").toString();
+ QString type = query.value("device_type").toString();
+ QString ip = query.value("ip").toString();
+ int port = query.value("port").toInt();
+ double longitude = query.value("longitude").toDouble();
+ double latitude = query.value("latitude").toDouble();
+ int state = query.value("state").toInt();
+ int signalStrength = query.value("signal_strength").toInt();
+ int batteryLevel = query.value("battery_level").toInt();
+ QString firmwareVersion = query.value("firmware_version").toString();
+ QString lastHeartbeat = query.value("last_heartbeat").toString();
+ QString createdAt = query.value("created_at").toString();
+ QString updatedAt = query.value("updated_at").toString();
+
+ db.close();
+
+ // 创建并显示设备详情对话框
+ DeviceDialog *dialog = new DeviceDialog(this);
+
+ // 设置设备信息
+ dialog->setDeviceInfo(deviceId, name, type, ip, port, longitude, latitude,
+ state, signalStrength, batteryLevel, firmwareVersion,
+ lastHeartbeat, createdAt, updatedAt);
+
+ // 连接设备操作信号
+ connect(dialog, &DeviceDialog::deviceConnectRequested,
+ this, &MainWindow::onDeviceControlRequested);
+ connect(dialog, &DeviceDialog::deviceDisconnectRequested,
+ this, &MainWindow::onDeviceControlRequested);
+ connect(dialog, &DeviceDialog::deviceLocationRequested,
+ this, &MainWindow::onDeviceLocationRequested);
+
+ // 显示对话框
+ dialog->exec();
+
+ // 清理
+ dialog->deleteLater();
+
+ qDebug() << "Device details dialog shown for:" << deviceId;
}
void MainWindow::onAddDeviceRequested(const QString &deviceType)