diff --git a/src/Client/BattlefieldExplorationSystem b/src/Client/BattlefieldExplorationSystem
index e20da90c..dc88f611 100755
Binary files a/src/Client/BattlefieldExplorationSystem and b/src/Client/BattlefieldExplorationSystem differ
diff --git a/src/Client/BattlefieldExplorationSystem.pro b/src/Client/BattlefieldExplorationSystem.pro
index 29f16305..cc5584a4 100644
--- a/src/Client/BattlefieldExplorationSystem.pro
+++ b/src/Client/BattlefieldExplorationSystem.pro
@@ -27,7 +27,9 @@ SOURCES += \
src/ui/main/MainWindow.cpp \
src/ui/dialogs/DeviceDialog.cpp \
src/ui/components/DeviceCard.cpp \
- src/ui/components/DeviceListPanel.cpp
+ src/ui/components/DeviceListPanel.cpp \
+ src/ui/components/SystemLogPanel.cpp \
+ src/utils/SystemLogger.cpp
# Header files - 按模块组织
HEADERS += \
@@ -36,7 +38,9 @@ HEADERS += \
include/ui/main/MainWindow.h \
include/ui/dialogs/DeviceDialog.h \
include/ui/components/DeviceCard.h \
- include/ui/components/DeviceListPanel.h
+ include/ui/components/DeviceListPanel.h \
+ include/ui/components/SystemLogPanel.h \
+ include/utils/SystemLogger.h
# UI forms - 按模块组织
FORMS += \
diff --git a/src/Client/doc/README.md b/src/Client/doc/README.md
index 7d645405..394197f0 100644
--- a/src/Client/doc/README.md
+++ b/src/Client/doc/README.md
@@ -24,6 +24,7 @@ API文档、组件设计、技术实现细节等
**当前文档**:
- `phase3_ui_refactor_plan.md` - Phase 3界面重构技术设计文档
+- `system_log_design.md` - 系统日志功能设计文档 (Phase 5)
**后续文档**:
- `api_documentation.md` - API接口文档
@@ -52,8 +53,8 @@ API文档、组件设计、技术实现细节等
- `code_refactor_summary.md` - 代码重构和模块化改造总结
- `phase3_completion_report.md` - Phase 3界面重构完成报告
-**后续文档**:
-- `phase2_completion_report.md` - Phase 2完成报告
+**计划文档**:
+- `phase5_completion_report.md` - Phase 5功能增强完成报告 (进行中)
- `testing_report.md` - 测试报告
- `performance_analysis.md` - 性能分析报告
- `final_project_report.md` - 最终项目报告
@@ -108,6 +109,9 @@ Git工作流程、分支策略、代码审查等
| 日期 | 文档 | 变更描述 | 作者 |
|------|------|----------|------|
| 2025-06-18 | 全部 | 初始化文档目录结构,迁移Phase 1文档 | Claude |
+| 2024-12-21 | task.md | 更新Phase 5系统日志功能开发进展 | Qt UI Developer |
+| 2024-12-21 | system_log_design.md | 创建系统日志功能技术设计文档 | Qt UI Developer |
+| 2024-12-21 | README.md | 更新文档索引,添加新的技术文档链接 | Qt UI Developer |
---
diff --git a/src/Client/doc/planning/task.md b/src/Client/doc/planning/task.md
index 26101a87..2dd08f63 100644
--- a/src/Client/doc/planning/task.md
+++ b/src/Client/doc/planning/task.md
@@ -102,18 +102,25 @@
- [x] 添加数据统计图表显示
- [x] 添加系统运行状态指示器
-### Phase 5: 功能模块重构和增强 (优先级: 中)
+### Phase 5: 功能模块重构和增强 (优先级: 中) 🚧 **进行中**
-#### 5.1 设备管理功能增强
+#### 5.1 系统日志功能开发 🚧 **当前任务**
+- [x] **UI重构**: 删除重复的设备管理按钮,为系统日志让出空间
+- [ ] **组件开发**: 创建SystemLogPanel组件和SystemLogger单例管理器
+- [ ] **界面集成**: 使用QSplitter实现日志与设备管理的35%:65%空间分配
+- [ ] **日志功能**: 实现多级别日志记录、格式化显示、过滤搜索功能
+- [ ] **系统集成**: 在关键操作点集成日志记录(设备操作、数据库、地图交互)
+
+#### 5.2 设备管理功能增强
- [ ] 重构添加设备对话框,提升用户体验
- [ ] 实现设备批量管理功能
- [ ] 添加设备配置导入/导出功能
- [ ] 实现设备连接测试功能
-#### 5.2 系统功能模块
+#### 5.3 系统功能模块
- [ ] 实现系统设置管理界面
- [ ] 添加用户权限管理功能
-- [ ] 实现操作日志记录功能
+- [x] **已集成**: 操作日志记录功能(通过系统日志实现)
- [ ] 添加系统备份和恢复功能
### Phase 6: 样式和主题系统 (优先级: 中)
@@ -295,11 +302,11 @@ CREATE TABLE dog_devices (
- 完整的状态指示系统和交互反馈机制
### 当前状态 🚧
-**当前阶段**: Phase 4 - 地图和可视化组件优化 ✅ **已完成**
-**完成日期**: 2024年12月19日
-**进展情况**: 设备卡片界面已成功集成到主窗口,地图集成完全实现,设备-地图交互功能正常
+**当前阶段**: Phase 5 - 功能模块重构和增强 🚧 **进行中**
+**开始日期**: 2024年12月21日
+**进展情况**: Phase 4已完全完成,开始Phase 5系统日志功能开发
-**最新进展** (2024年12月19日):
+**Phase 4 最终成果** (2024年12月19日):
✅ **组件集成完成**: DeviceListPanel已成功集成到MainWindow左侧面板
✅ **设备卡片显示**: 4个测试设备(2个无人机+2个机器狗)正常显示
✅ **过滤功能**: 设备搜索和分类过滤功能正常工作
@@ -310,6 +317,13 @@ CREATE TABLE dog_devices (
✅ **设备图标系统**: 不同设备类型显示不同图标(无人机/机器狗)
✅ **状态色彩显示**: 根据设备状态显示不同颜色(在线/警告/离线)
+**Phase 5 最新进展** (2024年12月21日):
+🚧 **UI重构开始**: 开始系统日志功能开发,移除重复的设备管理按钮
+✅ **按钮清理完成**: 成功删除MainWindow中4个重复的设备管理按钮
+✅ **空间预留**: 在左侧面板为系统日志预留350px垂直空间
+🚧 **组件开发中**: 准备创建SystemLogPanel和SystemLogger组件
+🎯 **目标架构**: 35%系统日志 + 65%设备管理的垂直分割布局
+
**Phase 4 重大里程碑达成** ✅:
- 🎯 **设备-地图集成**: 成功实现设备列表与地图的双向交互
- 🎯 **可视化增强**: 地图标记系统支持实时设备状态显示
@@ -324,14 +338,26 @@ CREATE TABLE dog_devices (
- **设备类型图标**: 无人机和机器狗不同图标显示系统
- **交互体验**: 点击设备卡片自动聚焦到地图位置
-### 下一步计划
-1. ✅ ~~**组件集成**: 将新的设备卡片界面集成到主窗口~~ **已完成**
-2. ✅ ~~**数据库连接**: 连接真实的设备数据库,实现数据同步(当前使用测试数据)~~ **已完成**
-3. ✅ ~~**地图集成优化**: 优化现有地图显示和交互功能~~ **已完成**
-4. ✅ ~~**设备位置显示**: 在地图上实时显示设备位置标记~~ **已完成**
-5. ✅ ~~**设备-地图交互**: 实现点击设备定位功能~~ **已完成**
-6. 📋 **硬件集成准备**: 为后续硬件设备接入做接口准备
-7. 📋 **Phase 5功能增强**: 准备进入下一阶段的功能模块开发
+### Phase 5 系统日志功能开发计划
+
+#### 当前进展 🚧
+1. ✅ **UI空间预留**: 删除重复按钮,为系统日志预留350px空间
+2. 🚧 **组件架构设计**: SystemLogPanel + SystemLogger单例设计
+3. 📋 **界面开发**: 实现紧凑军用风格的日志显示界面
+4. 📋 **功能实现**: 多级别日志、格式化、过滤、搜索功能
+5. 📋 **布局集成**: QSplitter实现35%:65%垂直分割
+6. 📋 **系统集成**: 在关键操作点添加日志记录
+
+#### 系统日志功能规格
+- **日志级别**: Info, Warning, Error, Success, Debug
+- **显示特性**: 时间戳、颜色编码、图标标识
+- **交互功能**: 清空、暂停/恢复、级别过滤
+- **性能优化**: 行数限制、内存管理、异步更新
+- **集成点**: 设备操作、数据库、地图交互、错误处理
+
+### 长期规划
+6. 📋 **硬件集成准备**: 为后续硬件设备接入做接口准备
+7. 📋 **Phase 6样式优化**: 主题系统和视觉规范完善
---
diff --git a/src/Client/doc/technical/system_log_design.md b/src/Client/doc/technical/system_log_design.md
new file mode 100644
index 00000000..6ac8acb5
--- /dev/null
+++ b/src/Client/doc/technical/system_log_design.md
@@ -0,0 +1,322 @@
+# 系统日志功能设计文档
+
+## 文档信息
+- **文档版本**: v1.0
+- **创建日期**: 2024年12月21日
+- **作者**: Qt UI Developer Expert
+- **项目阶段**: Phase 5 - 功能模块重构和增强
+
+## 概述
+
+系统日志功能是BattlefieldExplorationSystem项目Phase 5的核心特性,旨在替换左侧面板重复的设备管理按钮,提供系统操作的实时监控和记录功能。
+
+### 设计目标
+
+1. **消除功能重复**: 移除与设备管理面板重复的按钮
+2. **增强系统透明度**: 实时显示关键操作信息
+3. **提升调试能力**: 便于开发和维护阶段的问题追踪
+4. **专业化界面**: 符合军用系统的专业要求
+
+## 架构设计
+
+### 整体架构
+
+```
+左侧面板布局 (使用QSplitter):
+├── 系统日志面板 (SystemLogPanel) - 35% 空间
+│ ├── 头部控制区 (40px)
+│ ├── 日志显示区 (260-310px, 可滚动)
+│ └── 状态信息区 (20px, 可选)
+├── 分隔器 (QSplitter::handle) - 8px
+└── 设备管理面板 (DeviceListPanel) - 65% 空间
+ └── 现有的设备管理功能
+```
+
+### 核心组件
+
+#### 1. SystemLogger (单例管理器)
+```cpp
+class SystemLogger : public QObject
+{
+ Q_OBJECT
+
+public:
+ enum LogLevel {
+ Debug = 0,
+ Info = 1,
+ Warning = 2,
+ Error = 3,
+ Success = 4
+ };
+
+ static SystemLogger* getInstance();
+
+ void logInfo(const QString &message);
+ void logWarning(const QString &message);
+ void logError(const QString &message);
+ void logSuccess(const QString &message);
+ void logDebug(const QString &message);
+
+signals:
+ void logAdded(LogLevel level, const QString &message);
+
+private:
+ static SystemLogger *s_instance;
+ SystemLogger(QObject *parent = nullptr);
+};
+```
+
+#### 2. SystemLogPanel (界面组件)
+```cpp
+class SystemLogPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ explicit SystemLogPanel(QWidget *parent = nullptr);
+
+public slots:
+ void addLog(SystemLogger::LogLevel level, const QString &message);
+ void clearLogs();
+ void pauseLogging();
+ void resumeLogging();
+ void setLogLevelFilter(SystemLogger::LogLevel minLevel);
+
+private:
+ QTextEdit *m_logTextEdit;
+ QPushButton *m_clearButton;
+ QPushButton *m_pauseButton;
+ QComboBox *m_levelFilter;
+ QLabel *m_statusLabel;
+
+ bool m_isPaused;
+ SystemLogger::LogLevel m_minLevel;
+ int m_logCounts[5]; // 各级别日志计数
+};
+```
+
+## 界面设计
+
+### 视觉风格
+
+**军用深蓝风格**, 与现有界面保持一致:
+- **主色调**: 深蓝灰色背景 `rgb(15, 22, 32)` → `rgb(25, 35, 45)`
+- **强调色**: 青蓝色边框 `rgba(82, 194, 242, 0.3)`
+- **文字色**: 浅色文字 `rgb(220, 230, 242)`
+
+### 组件布局
+
+#### 头部控制区 (40px)
+```
+[🖥️ 系统日志] [清空] [暂停] [级别过滤▼]
+```
+
+#### 日志显示区 (主要区域)
+```
+HH:MM:SS.mmm 🔵 设备连接成功: UAV001
+HH:MM:SS.mmm 🟡 网络延迟较高: 150ms
+HH:MM:SS.mmm 🔴 数据库连接失败: 超时
+HH:MM:SS.mmm 🟢 设备定位完成: DOG001
+```
+
+#### 状态信息区 (20px, 可选)
+```
+总计: 156 | 错误: 3 | 警告: 12 | 就绪
+```
+
+### 日志格式设计
+
+#### 格式规范
+```
+[时间戳] [级别图标] [消息内容]
+```
+
+#### 级别定义
+- **🔍 Debug**: 开发调试信息 (灰色 `#9E9E9E`)
+- **🔵 Info**: 一般操作信息 (蓝色 `#52C2F2`)
+- **🟡 Warning**: 警告信息 (黄色 `#FFD700`)
+- **🔴 Error**: 错误信息 (红色 `#FF4444`)
+- **🟢 Success**: 成功操作 (绿色 `#00FF7F`)
+
+#### 格式化函数
+```cpp
+QString formatLogEntry(SystemLogger::LogLevel level, const QString &message)
+{
+ QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
+ QString levelIcon, levelColor;
+
+ switch(level) {
+ case Info: levelIcon = "🔵"; levelColor = "#52C2F2"; break;
+ case Warning: levelIcon = "🟡"; levelColor = "#FFD700"; break;
+ case Error: levelIcon = "🔴"; levelColor = "#FF4444"; break;
+ case Success: levelIcon = "🟢"; levelColor = "#00FF7F"; break;
+ case Debug: levelIcon = "🔍"; levelColor = "#9E9E9E"; break;
+ }
+
+ return QString("[%2] %3 %4")
+ .arg(levelColor)
+ .arg(timestamp)
+ .arg(levelIcon)
+ .arg(message);
+}
+```
+
+## 功能规格
+
+### 核心功能
+
+#### 1. 日志记录
+- **多级别支持**: Debug, Info, Warning, Error, Success
+- **时间戳**: 精确到毫秒的时间记录
+- **颜色编码**: 不同级别使用不同颜色显示
+- **图标标识**: 直观的视觉识别
+
+#### 2. 日志管理
+- **清空日志**: 一键清除所有日志记录
+- **暂停/恢复**: 暂停日志更新,便于查看
+- **级别过滤**: 只显示指定级别以上的日志
+- **行数限制**: 自动管理内存,限制最大行数
+
+#### 3. 高级功能
+- **自动滚动**: 新日志自动滚动到底部
+- **搜索功能**: 在日志中搜索关键词 (可选)
+- **导出功能**: 导出日志到文件 (可选)
+
+### 集成点
+
+系统日志将集成到以下关键操作点:
+
+#### 1. 设备管理操作
+```cpp
+// 设备添加
+SystemLogger::getInstance()->logInfo("设备添加成功: " + deviceName);
+
+// 设备连接
+SystemLogger::getInstance()->logSuccess("设备连接成功: " + deviceId);
+SystemLogger::getInstance()->logError("设备连接失败: " + deviceId + " - " + errorMsg);
+
+// 设备删除
+SystemLogger::getInstance()->logInfo("设备删除: " + deviceName);
+```
+
+#### 2. 数据库操作
+```cpp
+// 数据库连接
+SystemLogger::getInstance()->logSuccess("数据库连接成功");
+SystemLogger::getInstance()->logError("数据库连接失败: " + error);
+
+// 数据操作
+SystemLogger::getInstance()->logInfo("加载了 " + QString::number(count) + " 个设备");
+```
+
+#### 3. 地图交互
+```cpp
+// 地图操作
+SystemLogger::getInstance()->logInfo("地图初始化完成");
+SystemLogger::getInstance()->logSuccess("设备定位完成: " + deviceId);
+```
+
+#### 4. 系统事件
+```cpp
+// 系统启动
+SystemLogger::getInstance()->logInfo("系统启动完成");
+
+// 错误处理
+SystemLogger::getInstance()->logWarning("网络延迟较高: " + QString::number(latency) + "ms");
+```
+
+## 性能考虑
+
+### 内存管理
+- **行数限制**: 最大500行,超出自动删除最旧记录
+- **异步更新**: 日志记录不阻塞主线程
+- **智能刷新**: 避免频繁UI更新造成性能问题
+
+### 用户体验
+- **响应速度**: 日志添加不影响界面响应
+- **视觉效果**: 平滑的滚动和更新动画
+- **可用性**: 直观的控制按钮和快捷操作
+
+## 空间分配方案
+
+### QSplitter布局
+```cpp
+// 创建垂直分割器
+QSplitter *leftSplitter = new QSplitter(Qt::Vertical, this);
+
+// 系统日志面板
+SystemLogPanel *logPanel = new SystemLogPanel(this);
+logPanel->setMinimumHeight(200); // 最小高度
+logPanel->setMaximumHeight(400); // 最大高度
+
+// 设备管理面板
+DeviceListPanel *devicePanel = new DeviceListPanel(this);
+devicePanel->setMinimumHeight(300); // 最小高度
+
+// 设置分割比例 (35% : 65%)
+leftSplitter->addWidget(logPanel);
+leftSplitter->addWidget(devicePanel);
+leftSplitter->setSizes(QList() << 350 << 650);
+```
+
+### 响应式调整
+- **小屏幕**: 自动调整比例,保证最小可用空间
+- **大屏幕**: 维持设计比例,提供最佳用户体验
+- **用户可调**: 支持用户拖拽分割线调整比例
+
+## 实施计划
+
+### Phase 1: 核心组件开发
+1. 创建 SystemLogger 单例管理器
+2. 创建 SystemLogPanel 界面组件
+3. 实现基础的日志记录和显示功能
+
+### Phase 2: 界面集成
+1. 修改 MainWindow 布局,移除重复按钮
+2. 使用 QSplitter 实现分割布局
+3. 集成系统日志面板到左侧面板
+
+### Phase 3: 功能完善
+1. 实现日志过滤和搜索功能
+2. 添加高级控制功能 (清空、暂停等)
+3. 优化性能和用户体验
+
+### Phase 4: 系统集成
+1. 在关键操作点添加日志记录
+2. 完善错误处理和异常记录
+3. 测试和调试整体功能
+
+## 技术风险与应对
+
+### 主要风险
+1. **性能影响**: 频繁的日志更新可能影响界面性能
+2. **内存占用**: 大量日志可能导致内存占用过高
+3. **用户体验**: 日志信息过多可能干扰主要功能
+
+### 应对策略
+1. **异步处理**: 使用异步机制避免阻塞主线程
+2. **智能限制**: 设置合理的行数和更新频率限制
+3. **用户控制**: 提供暂停、过滤等用户控制选项
+
+## 测试策略
+
+### 功能测试
+- 各级别日志记录和显示正确性
+- 过滤和搜索功能准确性
+- 清空和暂停功能可靠性
+
+### 性能测试
+- 大量日志的性能表现
+- 内存使用情况监控
+- 界面响应速度测试
+
+### 集成测试
+- 与现有功能的兼容性
+- 空间分配的正确性
+- 用户交互的流畅性
+
+---
+
+**文档状态**: 🟢 **已完成**
+**下次更新**: 根据实施进展进行更新
+**相关文档**: task.md, phase5_completion_report.md
\ No newline at end of file
diff --git a/src/Client/forms/main/MainWindow.ui b/src/Client/forms/main/MainWindow.ui
index 29a1d0e5..bb34b376 100644
--- a/src/Client/forms/main/MainWindow.ui
+++ b/src/Client/forms/main/MainWindow.ui
@@ -262,198 +262,37 @@ border-radius: 1px;
-
-
-
- 6
+
+
+
+
+ 0
+ 350
+
-
-
-
-
-
-
-
-
- 0
- 70
-
-
-
-
- 18
- 75
- true
-
-
-
- 机器人列表
-
-
-
- -
-
-
-
- 40
- 40
-
-
-
-
- 40
- 40
-
-
-
- border-image: url(:/image/res/image/tab.svg);
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 85
-
-
-
-
- 20
- 75
- true
-
-
-
- 添加机器人
-
-
-
- -
-
-
-
- 40
- 40
-
-
-
-
- 40
- 40
-
-
-
- border-image: url(:/image/res/image/robotbtn.svg);
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 85
-
-
-
-
- 20
- 75
- true
-
-
-
- 添加无人机
-
-
-
- -
-
-
-
- 40
- 40
-
-
-
-
- 40
- 40
-
-
-
- border-image: url(:/image/res/image/UAV.svg);
-
-
-
-
-
-
-
-
- -
-
-
-
-
-
-
- 0
- 70
-
-
-
-
- 18
- 75
- true
-
-
-
- 无人机列表
-
-
-
- -
-
-
-
- 40
- 40
-
-
-
-
- 40
- 40
-
-
-
- false
-
-
- border-image: url(:/image/res/image/tab.svg);
-
-
-
-
-
-
-
-
-
+
+ color: rgb(82, 194, 242);
+font-size: 16px;
+font-weight: bold;
+padding: 20px;
+margin: 10px;
+background: qlineargradient(x1:0, y1:0, x2:1, y2:1,
+ stop:0 rgba(82, 194, 242, 0.1),
+ stop:1 rgba(45, 120, 180, 0.1));
+border: 2px dashed rgba(82, 194, 242, 0.5);
+border-radius: 8px;
+
+
+ 🖥️ 系统日志面板
+
+此区域将显示系统日志信息
+包括设备操作、连接状态、
+地图交互等关键信息
+
+
+ Qt::AlignCenter
+
+
-
diff --git a/src/Client/include/ui/components/SystemLogPanel.h b/src/Client/include/ui/components/SystemLogPanel.h
new file mode 100644
index 00000000..04a6a201
--- /dev/null
+++ b/src/Client/include/ui/components/SystemLogPanel.h
@@ -0,0 +1,202 @@
+/**
+ * @file SystemLogPanel.h
+ * @brief 系统日志面板界面组件头文件
+ * @author Qt UI Developer Expert
+ * @date 2024-12-21
+ * @version 1.0
+ */
+
+#ifndef SYSTEM_LOG_PANEL_H
+#define SYSTEM_LOG_PANEL_H
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// 前向声明
+class SystemLogger;
+
+/**
+ * @class SystemLogPanel
+ * @brief 系统日志显示面板组件
+ *
+ * 系统日志面板是BattlefieldExplorationSystem中的核心UI组件,
+ * 用于实时显示系统操作日志、设备状态变化、错误信息等关键信息。
+ *
+ * 主要功能:
+ * - 多级别日志显示(Debug, Info, Warning, Error, Success)
+ * - 实时日志更新和格式化显示
+ * - 日志过滤和搜索功能
+ * - 日志清空、暂停/恢复控制
+ * - 军用风格的界面设计
+ */
+class SystemLogPanel : public QWidget
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief 构造函数
+ * @param parent 父控件指针
+ */
+ explicit SystemLogPanel(QWidget *parent = nullptr);
+
+ /**
+ * @brief 析构函数
+ */
+ ~SystemLogPanel();
+
+ /**
+ * @brief 日志级别枚举(与SystemLogger保持一致)
+ */
+ enum LogLevel {
+ Debug = 0, ///< 调试信息
+ Info = 1, ///< 一般信息
+ Warning = 2, ///< 警告信息
+ Error = 3, ///< 错误信息
+ Success = 4 ///< 成功信息
+ };
+
+public slots:
+ /**
+ * @brief 添加日志条目
+ * @param level 日志级别
+ * @param message 日志消息内容
+ */
+ void addLog(LogLevel level, const QString &message);
+
+ /**
+ * @brief 清空所有日志
+ */
+ void clearLogs();
+
+ /**
+ * @brief 暂停日志更新
+ */
+ void pauseLogging();
+
+ /**
+ * @brief 恢复日志更新
+ */
+ void resumeLogging();
+
+ /**
+ * @brief 设置日志级别过滤
+ * @param minLevel 最小显示级别
+ */
+ void setLogLevelFilter(LogLevel minLevel);
+
+private slots:
+ /**
+ * @brief 处理清空按钮点击
+ */
+ void onClearButtonClicked();
+
+ /**
+ * @brief 处理暂停/恢复按钮点击
+ */
+ void onPauseButtonClicked();
+
+ /**
+ * @brief 处理级别过滤器变化
+ * @param index 选中的过滤级别索引
+ */
+ void onLevelFilterChanged(int index);
+
+ /**
+ * @brief 更新状态信息显示
+ */
+ void updateStatusInfo();
+
+private:
+ /**
+ * @brief 初始化UI界面
+ */
+ void setupUI();
+
+ /**
+ * @brief 设置界面样式
+ */
+ void setupStyle();
+
+ /**
+ * @brief 连接信号和槽
+ */
+ void connectSignals();
+
+ /**
+ * @brief 格式化日志条目
+ * @param level 日志级别
+ * @param message 消息内容
+ * @return 格式化后的HTML字符串
+ */
+ QString formatLogEntry(LogLevel level, const QString &message);
+
+ /**
+ * @brief 获取级别图标
+ * @param level 日志级别
+ * @return 对应的图标字符串
+ */
+ QString getLevelIcon(LogLevel level);
+
+ /**
+ * @brief 获取级别颜色
+ * @param level 日志级别
+ * @return 对应的颜色字符串
+ */
+ QString getLevelColor(LogLevel level);
+
+ /**
+ * @brief 获取级别名称
+ * @param level 日志级别
+ * @return 对应的级别名称
+ */
+ QString getLevelName(LogLevel level);
+
+ /**
+ * @brief 限制日志行数,防止内存占用过高
+ */
+ void limitLogLines();
+
+ /**
+ * @brief 自动滚动到底部
+ */
+ void scrollToBottom();
+
+private:
+ // UI组件
+ QTextEdit *m_logTextEdit; ///< 日志显示文本框
+ QPushButton *m_clearButton; ///< 清空按钮
+ QPushButton *m_pauseButton; ///< 暂停/恢复按钮
+ QComboBox *m_levelFilter; ///< 级别过滤下拉框
+ QLabel *m_statusLabel; ///< 状态信息标签
+ QLabel *m_titleLabel; ///< 标题标签
+
+ // 布局管理
+ QVBoxLayout *m_mainLayout; ///< 主布局
+ QHBoxLayout *m_controlLayout; ///< 控制按钮布局
+ QHBoxLayout *m_statusLayout; ///< 状态信息布局
+
+ // 状态变量
+ bool m_isPaused; ///< 是否暂停日志更新
+ LogLevel m_minLevel; ///< 最小显示级别
+ int m_logCounts[5]; ///< 各级别日志计数
+ int m_totalLogCount; ///< 总日志数量
+ int m_maxLogLines; ///< 最大日志行数限制
+
+ // 定时器
+ QTimer *m_statusUpdateTimer; ///< 状态更新定时器
+
+ // 样式常量
+ static const int MAX_LOG_LINES; ///< 最大日志行数
+ static const int STATUS_UPDATE_INTERVAL; ///< 状态更新间隔(ms)
+};
+
+#endif // SYSTEM_LOG_PANEL_H
\ No newline at end of file
diff --git a/src/Client/include/ui/main/MainWindow.h b/src/Client/include/ui/main/MainWindow.h
index 41e15fe8..f226443a 100644
--- a/src/Client/include/ui/main/MainWindow.h
+++ b/src/Client/include/ui/main/MainWindow.h
@@ -24,6 +24,7 @@
#include
#include
#include
+#include
// Qt控件头文件
#include
@@ -40,6 +41,7 @@
// 自定义模块头文件
// #include "AudioModule/IntelligenceUI.h" // 暂时注释掉,待实现
#include "ui/components/DeviceListPanel.h"
+#include "ui/components/SystemLogPanel.h"
// 标准库头文件
#include
@@ -230,6 +232,11 @@ private:
*/
void setupDeviceListPanel();
+ /**
+ * @brief 设置系统日志面板和左侧面板分割器
+ */
+ void setupSystemLogPanel();
+
/**
* @brief 连接信号和槽
*/
@@ -249,6 +256,8 @@ private:
Ui::MainWindow *m_ui; ///< UI界面指针
// IntelligenceUI *m_intelligenceUI; ///< 情报传达界面指针(暂时注释掉)
DeviceListPanel *m_deviceListPanel; ///< 设备列表面板组件
+ SystemLogPanel *m_systemLogPanel; ///< 系统日志面板组件
+ QSplitter *m_leftPanelSplitter; ///< 左侧面板分割器
QVector> m_robotList; ///< 机器人列表(名称-IP地址对)
QVector> m_uavList; ///< 无人机列表(名称-IP地址对)
// 人脸识别相关成员变量已移除(功能暂未实现)
diff --git a/src/Client/include/utils/SystemLogger.h b/src/Client/include/utils/SystemLogger.h
new file mode 100644
index 00000000..716f4e40
--- /dev/null
+++ b/src/Client/include/utils/SystemLogger.h
@@ -0,0 +1,178 @@
+/**
+ * @file SystemLogger.h
+ * @brief 系统日志管理器单例类头文件
+ * @author Qt UI Developer Expert
+ * @date 2024-12-21
+ * @version 1.0
+ */
+
+#ifndef SYSTEM_LOGGER_H
+#define SYSTEM_LOGGER_H
+
+#include
+#include
+#include
+#include
+#include
+
+/**
+ * @class SystemLogger
+ * @brief 系统日志管理器单例类
+ *
+ * SystemLogger是战场探索系统的核心日志管理组件,采用单例模式设计,
+ * 负责统一管理和分发系统中的各种日志信息。
+ *
+ * 主要功能:
+ * - 多级别日志记录(Debug, Info, Warning, Error, Success)
+ * - 线程安全的日志记录
+ * - 信号机制实时通知UI组件
+ * - 统一的日志接口,便于系统各模块调用
+ *
+ * 使用方式:
+ * @code
+ * SystemLogger::getInstance()->logInfo("设备连接成功");
+ * SystemLogger::getInstance()->logError("数据库连接失败");
+ * @endcode
+ */
+class SystemLogger : public QObject
+{
+ Q_OBJECT
+
+public:
+ /**
+ * @brief 日志级别枚举
+ */
+ enum LogLevel {
+ Debug = 0, ///< 调试信息 - 开发阶段使用
+ Info = 1, ///< 一般信息 - 正常操作记录
+ Warning = 2, ///< 警告信息 - 需要注意的情况
+ Error = 3, ///< 错误信息 - 系统错误和异常
+ Success = 4 ///< 成功信息 - 重要操作成功完成
+ };
+
+ /**
+ * @brief 获取单例实例
+ * @return SystemLogger单例指针
+ */
+ static SystemLogger* getInstance();
+
+ /**
+ * @brief 销毁单例实例
+ * 通常在应用程序退出时调用
+ */
+ static void destroyInstance();
+
+ /**
+ * @brief 记录调试信息
+ * @param message 日志消息内容
+ */
+ void logDebug(const QString &message);
+
+ /**
+ * @brief 记录一般信息
+ * @param message 日志消息内容
+ */
+ void logInfo(const QString &message);
+
+ /**
+ * @brief 记录警告信息
+ * @param message 日志消息内容
+ */
+ void logWarning(const QString &message);
+
+ /**
+ * @brief 记录错误信息
+ * @param message 日志消息内容
+ */
+ void logError(const QString &message);
+
+ /**
+ * @brief 记录成功信息
+ * @param message 日志消息内容
+ */
+ void logSuccess(const QString &message);
+
+ /**
+ * @brief 通用日志记录方法
+ * @param level 日志级别
+ * @param message 日志消息内容
+ */
+ void log(LogLevel level, const QString &message);
+
+ /**
+ * @brief 设置是否启用控制台输出
+ * @param enabled true为启用,false为禁用
+ */
+ void setConsoleOutputEnabled(bool enabled);
+
+ /**
+ * @brief 获取级别名称字符串
+ * @param level 日志级别
+ * @return 级别名称
+ */
+ static QString getLevelString(LogLevel level);
+
+signals:
+ /**
+ * @brief 日志添加信号
+ * @param level 日志级别
+ * @param message 日志消息内容
+ *
+ * 当有新日志记录时发出此信号,UI组件可以连接此信号来实时更新显示
+ */
+ void logAdded(LogLevel level, const QString &message);
+
+private:
+ /**
+ * @brief 私有构造函数(单例模式)
+ * @param parent 父对象指针
+ */
+ explicit SystemLogger(QObject *parent = nullptr);
+
+ /**
+ * @brief 私有析构函数(单例模式)
+ */
+ ~SystemLogger();
+
+ /**
+ * @brief 禁用拷贝构造函数
+ */
+ SystemLogger(const SystemLogger&) = delete;
+
+ /**
+ * @brief 禁用赋值运算符
+ */
+ SystemLogger& operator=(const SystemLogger&) = delete;
+
+ /**
+ * @brief 内部日志记录实现
+ * @param level 日志级别
+ * @param message 日志消息内容
+ */
+ void logInternal(LogLevel level, const QString &message);
+
+ /**
+ * @brief 输出到控制台
+ * @param level 日志级别
+ * @param message 日志消息内容
+ */
+ void outputToConsole(LogLevel level, const QString &message);
+
+private:
+ static SystemLogger *s_instance; ///< 单例实例指针
+ static QMutex s_mutex; ///< 线程安全互斥锁
+
+ bool m_consoleOutputEnabled; ///< 是否启用控制台输出
+ QMutex m_logMutex; ///< 日志记录互斥锁
+};
+
+/**
+ * @brief 便捷宏定义,简化日志调用
+ */
+#define LOG_DEBUG(msg) SystemLogger::getInstance()->logDebug(msg)
+#define LOG_INFO(msg) SystemLogger::getInstance()->logInfo(msg)
+#define LOG_WARNING(msg) SystemLogger::getInstance()->logWarning(msg)
+#define LOG_ERROR(msg) SystemLogger::getInstance()->logError(msg)
+#define LOG_SUCCESS(msg) SystemLogger::getInstance()->logSuccess(msg)
+
+#endif // SYSTEM_LOGGER_H
\ No newline at end of file
diff --git a/src/Client/src/ui/components/DeviceCard.cpp b/src/Client/src/ui/components/DeviceCard.cpp
index 5107bc8a..8b4e53a0 100644
--- a/src/Client/src/ui/components/DeviceCard.cpp
+++ b/src/Client/src/ui/components/DeviceCard.cpp
@@ -7,6 +7,7 @@
*/
#include "ui/components/DeviceCard.h"
+#include "utils/SystemLogger.h"
// Qt GUI头文件
#include
@@ -60,6 +61,7 @@ DeviceCard::DeviceCard(const DeviceInfo &device, QWidget *parent)
setAttribute(Qt::WA_Hover, true);
qDebug() << "DeviceCard created for device:" << device.name;
+ SystemLogger::getInstance()->logDebug(QString("创建设备卡片: %1").arg(device.name));
}
DeviceCard::~DeviceCard()
@@ -436,7 +438,11 @@ void DeviceCard::refreshStatus()
void DeviceCard::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
- setSelected(!m_isSelected);
+ bool newSelected = !m_isSelected;
+ setSelected(newSelected);
+ if (newSelected) {
+ SystemLogger::getInstance()->logInfo(QString("选中设备: %1").arg(m_deviceInfo.name));
+ }
event->accept();
}
QWidget::mousePressEvent(event);
@@ -523,6 +529,7 @@ void DeviceCard::paintEvent(QPaintEvent *event)
void DeviceCard::onDetailsClicked()
{
qDebug() << "Details clicked for device:" << m_deviceInfo.name;
+ SystemLogger::getInstance()->logInfo(QString("查看设备详情: %1").arg(m_deviceInfo.name));
emit deviceDetailsRequested(m_deviceInfo.id);
}
@@ -536,10 +543,12 @@ void DeviceCard::onControlClicked()
// 当前在线,切换为离线
newStatus = DeviceStatus::Offline;
qDebug() << "Disconnecting device:" << m_deviceInfo.name;
+ SystemLogger::getInstance()->logInfo(QString("正在断开连接: %1").arg(m_deviceInfo.name));
} else {
// 当前离线,切换为在线
newStatus = DeviceStatus::Online;
qDebug() << "Connecting device:" << m_deviceInfo.name;
+ SystemLogger::getInstance()->logInfo(QString("正在连接设备: %1").arg(m_deviceInfo.name));
}
// 更新数据库中的状态
@@ -557,8 +566,13 @@ void DeviceCard::onControlClicked()
qDebug() << "Device status successfully updated:" << m_deviceInfo.name
<< "to" << (newStatus == DeviceStatus::Online ? "Online" : "Offline");
+
+ // 记录连接状态变更成功
+ QString statusText = (newStatus == DeviceStatus::Online) ? "上线" : "离线";
+ SystemLogger::getInstance()->logSuccess(QString("设备 %1 已%2").arg(m_deviceInfo.name).arg(statusText));
} else {
qWarning() << "Failed to update device status in database for:" << m_deviceInfo.name;
+ SystemLogger::getInstance()->logError(QString("设备状态更新失败: %1").arg(m_deviceInfo.name));
// 可以显示错误提示给用户
}
}
@@ -566,6 +580,7 @@ void DeviceCard::onControlClicked()
void DeviceCard::onLocationClicked()
{
qDebug() << "Location clicked for device:" << m_deviceInfo.name;
+ SystemLogger::getInstance()->logInfo(QString("请求设备定位: %1").arg(m_deviceInfo.name));
emit deviceLocationRequested(m_deviceInfo.id);
}
diff --git a/src/Client/src/ui/components/DeviceListPanel.cpp b/src/Client/src/ui/components/DeviceListPanel.cpp
index c447b0e5..7a1d36f7 100644
--- a/src/Client/src/ui/components/DeviceListPanel.cpp
+++ b/src/Client/src/ui/components/DeviceListPanel.cpp
@@ -7,6 +7,7 @@
*/
#include "ui/components/DeviceListPanel.h"
+#include "utils/SystemLogger.h"
// Qt GUI头文件
#include
@@ -290,6 +291,7 @@ int DeviceListPanel::getOnlineDeviceCount() const
void DeviceListPanel::refreshDeviceList()
{
qDebug() << "Refreshing device list...";
+ SystemLogger::getInstance()->logInfo("正在刷新设备列表...");
// 清除现有设备卡片
clearAllDeviceCards();
@@ -312,6 +314,7 @@ void DeviceListPanel::refreshDeviceList()
updateDeviceCountStats();
qDebug() << "Device list refreshed. Total devices:" << m_allDevices.size();
+ SystemLogger::getInstance()->logSuccess(QString("设备列表刷新完成,共加载 %1 个设备").arg(m_allDevices.size()));
}
void DeviceListPanel::addDevice(const DeviceInfo &device)
@@ -335,6 +338,7 @@ void DeviceListPanel::addDevice(const DeviceInfo &device)
updateDeviceCountStats();
qDebug() << "Device added:" << device.name;
+ SystemLogger::getInstance()->logSuccess(QString("设备已添加: %1").arg(device.name));
}
}
@@ -345,6 +349,15 @@ void DeviceListPanel::removeDevice(const QString &deviceId)
return;
}
+ // 获取设备名称用于日志
+ QString deviceName = "未知设备";
+ for (const auto &device : m_allDevices) {
+ if (device.id == deviceId) {
+ deviceName = device.name;
+ break;
+ }
+ }
+
// 移除设备卡片
DeviceCard *card = m_deviceCards.take(deviceId);
card->deleteLater();
@@ -365,6 +378,7 @@ void DeviceListPanel::removeDevice(const QString &deviceId)
updateDeviceCountStats();
qDebug() << "Device removed:" << deviceId;
+ SystemLogger::getInstance()->logWarning(QString("设备已移除: %1").arg(deviceName));
}
void DeviceListPanel::updateDevice(const DeviceInfo &device)
@@ -469,6 +483,7 @@ QList DeviceListPanel::loadDevicesFromDatabase()
if (db.open()) {
qDebug() << "Successfully connected to Client database";
+ SystemLogger::getInstance()->logSuccess("成功连接到数据库");
QSqlQuery query(db);
QString sql = "SELECT id, name, device_type, state, ip, port, longitude, latitude, signal_strength, battery_level FROM devices";
@@ -513,6 +528,7 @@ QList DeviceListPanel::loadDevicesFromDatabase()
db.close();
} else {
qWarning() << "Failed to connect to Client database:" << db.lastError().text();
+ SystemLogger::getInstance()->logError("数据库连接失败");
}
} catch (const std::exception& e) {
qWarning() << "Database connection exception:" << e.what();
@@ -557,6 +573,7 @@ bool DeviceListPanel::deleteDeviceFromDatabase(const QString &deviceId)
if (query.exec()) {
if (query.numRowsAffected() > 0) {
qDebug() << "Successfully deleted device from database:" << deviceId;
+ SystemLogger::getInstance()->logSuccess("设备从数据库中删除成功");
success = true;
// 从内存中移除设备
@@ -588,11 +605,13 @@ bool DeviceListPanel::deleteDeviceFromDatabase(const QString &deviceId)
}
} else {
qWarning() << "Failed to execute delete query:" << query.lastError().text();
+ SystemLogger::getInstance()->logError("数据库删除操作失败");
}
db.close();
} else {
qWarning() << "Failed to connect to database for deletion:" << db.lastError().text();
+ SystemLogger::getInstance()->logError("删除操作数据库连接失败");
}
// 清理数据库连接
diff --git a/src/Client/src/ui/components/SystemLogPanel.cpp b/src/Client/src/ui/components/SystemLogPanel.cpp
new file mode 100644
index 00000000..cde94c22
--- /dev/null
+++ b/src/Client/src/ui/components/SystemLogPanel.cpp
@@ -0,0 +1,476 @@
+/**
+ * @file SystemLogPanel.cpp
+ * @brief 系统日志面板界面组件实现
+ * @author Qt UI Developer Expert
+ * @date 2024-12-21
+ * @version 1.0
+ */
+
+#include "ui/components/SystemLogPanel.h"
+#include "utils/SystemLogger.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+// 静态常量定义
+const int SystemLogPanel::MAX_LOG_LINES = 500;
+const int SystemLogPanel::STATUS_UPDATE_INTERVAL = 2000; // 2秒
+
+SystemLogPanel::SystemLogPanel(QWidget *parent)
+ : QWidget(parent)
+ , m_logTextEdit(nullptr)
+ , m_clearButton(nullptr)
+ , m_pauseButton(nullptr)
+ , m_levelFilter(nullptr)
+ , m_statusLabel(nullptr)
+ , m_titleLabel(nullptr)
+ , m_mainLayout(nullptr)
+ , m_controlLayout(nullptr)
+ , m_statusLayout(nullptr)
+ , m_isPaused(false)
+ , m_minLevel(Debug)
+ , m_totalLogCount(0)
+ , m_maxLogLines(MAX_LOG_LINES)
+ , m_statusUpdateTimer(nullptr)
+{
+ // 初始化日志计数器
+ for (int i = 0; i < 5; ++i) {
+ m_logCounts[i] = 0;
+ }
+
+ setupUI();
+ setupStyle();
+ connectSignals();
+
+ // 连接到SystemLogger的信号
+ connect(SystemLogger::getInstance(), &SystemLogger::logAdded,
+ this, [this](SystemLogger::LogLevel level, const QString &message) {
+ addLog(static_cast(level), message);
+ });
+
+ qDebug() << "SystemLogPanel initialized successfully";
+}
+
+SystemLogPanel::~SystemLogPanel()
+{
+ if (m_statusUpdateTimer) {
+ m_statusUpdateTimer->stop();
+ }
+ qDebug() << "SystemLogPanel destroyed";
+}
+
+void SystemLogPanel::setupUI()
+{
+ // 创建主布局
+ m_mainLayout = new QVBoxLayout(this);
+ m_mainLayout->setSpacing(4);
+ m_mainLayout->setContentsMargins(8, 8, 8, 10);
+
+ // 创建标题标签
+ m_titleLabel = new QLabel("🖥️ 系统日志", this);
+ m_titleLabel->setMinimumHeight(25);
+ m_titleLabel->setAlignment(Qt::AlignCenter);
+
+ // 创建控制按钮布局
+ m_controlLayout = new QHBoxLayout();
+ m_controlLayout->setSpacing(4);
+
+ // 创建控制按钮
+ m_clearButton = new QPushButton("清空", this);
+ m_clearButton->setMinimumSize(68, 30);
+ m_clearButton->setMaximumSize(68, 30);
+
+ m_pauseButton = new QPushButton("暂停", this);
+ m_pauseButton->setMinimumSize(68, 30);
+ m_pauseButton->setMaximumSize(68, 30);
+
+ // 创建级别过滤器
+ m_levelFilter = new QComboBox(this);
+ m_levelFilter->addItem("全部", static_cast(Debug));
+ m_levelFilter->addItem("信息+", static_cast(Info));
+ m_levelFilter->addItem("警告+", static_cast(Warning));
+ m_levelFilter->addItem("错误+", static_cast(Error));
+ m_levelFilter->addItem("成功", static_cast(Success));
+ m_levelFilter->setMinimumSize(88, 30);
+ m_levelFilter->setMaximumSize(88, 30);
+
+ // 添加控制组件到布局
+ m_controlLayout->addWidget(m_clearButton);
+ m_controlLayout->addWidget(m_pauseButton);
+ m_controlLayout->addStretch();
+ m_controlLayout->addWidget(m_levelFilter);
+
+ // 创建日志显示文本框
+ m_logTextEdit = new QTextEdit(this);
+ m_logTextEdit->setReadOnly(true);
+ m_logTextEdit->setMinimumHeight(250);
+ m_logTextEdit->setMaximumHeight(350);
+ m_logTextEdit->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+ m_logTextEdit->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
+
+ // 创建状态信息标签
+ m_statusLabel = new QLabel("就绪", this);
+ m_statusLabel->setMinimumHeight(26);
+ m_statusLabel->setMaximumHeight(28);
+ m_statusLabel->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
+
+ // 创建状态布局
+ m_statusLayout = new QHBoxLayout();
+ m_statusLayout->setContentsMargins(0, 0, 0, 0);
+ m_statusLayout->addWidget(m_statusLabel);
+ m_statusLayout->addStretch();
+
+ // 添加所有组件到主布局
+ m_mainLayout->addWidget(m_titleLabel);
+ m_mainLayout->addLayout(m_controlLayout);
+ m_mainLayout->addWidget(m_logTextEdit);
+ m_mainLayout->addLayout(m_statusLayout);
+
+ // 创建状态更新定时器
+ m_statusUpdateTimer = new QTimer(this);
+ m_statusUpdateTimer->setInterval(STATUS_UPDATE_INTERVAL);
+ m_statusUpdateTimer->start();
+
+ qDebug() << "SystemLogPanel UI setup completed";
+}
+
+void SystemLogPanel::setupStyle()
+{
+ // 主面板样式
+ setStyleSheet(
+ "SystemLogPanel {"
+ " background-color: rgba(25, 35, 45, 0.95);"
+ " border: 2px solid rgba(82, 194, 242, 0.4);"
+ " border-radius: 8px;"
+ " padding: 4px;"
+ "}"
+ );
+
+ // 标题样式
+ m_titleLabel->setStyleSheet(
+ "QLabel {"
+ " color: rgb(82, 194, 242);"
+ " font-size: 14px;"
+ " font-weight: bold;"
+ " padding: 4px 8px;"
+ " background: qlineargradient(x1:0, y1:0, x2:1, y2:1,"
+ " stop:0 rgba(82, 194, 242, 0.2),"
+ " stop:1 rgba(45, 120, 180, 0.2));"
+ " border: 1px solid rgba(82, 194, 242, 0.5);"
+ " border-radius: 4px;"
+ "}"
+ );
+
+ // 按钮通用样式
+ QString buttonStyle =
+ "QPushButton {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+ " stop:0 rgba(45, 65, 95, 0.8),"
+ " stop:1 rgba(25, 40, 65, 0.8));"
+ " color: rgb(220, 230, 242);"
+ " border: 1px solid rgba(82, 194, 242, 0.5);"
+ " border-radius: 4px;"
+ " font-size: 12px;"
+ " font-weight: bold;"
+ " padding: 3px 8px;"
+ "}"
+ "QPushButton:hover {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+ " stop:0 rgba(82, 194, 242, 0.6),"
+ " stop:1 rgba(45, 120, 180, 0.6));"
+ " border: 1px solid rgba(82, 194, 242, 0.8);"
+ "}"
+ "QPushButton:pressed {"
+ " background: qlineargradient(x1:0, y1:0, x2:0, y2:1,"
+ " stop:0 rgba(82, 194, 242, 0.8),"
+ " stop:1 rgba(45, 120, 180, 0.8));"
+ "}";
+
+ m_clearButton->setStyleSheet(buttonStyle);
+ m_pauseButton->setStyleSheet(buttonStyle);
+
+ // 下拉框样式
+ m_levelFilter->setStyleSheet(
+ "QComboBox {"
+ " background: rgba(25, 40, 65, 0.8);"
+ " color: rgb(220, 230, 242);"
+ " border: 1px solid rgba(82, 194, 242, 0.5);"
+ " border-radius: 4px;"
+ " padding: 3px 8px;"
+ " font-size: 12px;"
+ " font-weight: bold;"
+ "}"
+ "QComboBox::drop-down {"
+ " subcontrol-origin: padding;"
+ " subcontrol-position: top right;"
+ " width: 15px;"
+ " border-left: 1px solid rgba(82, 194, 242, 0.5);"
+ "}"
+ "QComboBox::down-arrow {"
+ " width: 8px;"
+ " height: 8px;"
+ "}"
+ "QComboBox QAbstractItemView {"
+ " background-color: rgba(25, 40, 65, 0.95);"
+ " color: rgb(220, 230, 242);"
+ " border: 1px solid rgba(82, 194, 242, 0.5);"
+ " border-radius: 4px;"
+ " selection-background-color: rgba(82, 194, 242, 0.3);"
+ "}"
+ );
+
+ // 文本框样式
+ m_logTextEdit->setStyleSheet(
+ "QTextEdit {"
+ " background-color: rgba(15, 22, 32, 0.9);"
+ " color: rgb(220, 230, 242);"
+ " border: 1px solid rgba(82, 194, 242, 0.4);"
+ " border-radius: 6px;"
+ " padding: 6px;"
+ " font-family: 'Consolas', 'Monaco', monospace;"
+ " font-size: 13px;"
+ " line-height: 1.4;"
+ " selection-background-color: rgba(82, 194, 242, 0.3);"
+ "}"
+ "QScrollBar:vertical {"
+ " background-color: rgba(30, 44, 62, 0.8);"
+ " width: 10px;"
+ " border-radius: 5px;"
+ "}"
+ "QScrollBar::handle:vertical {"
+ " background-color: rgba(82, 194, 242, 0.6);"
+ " border-radius: 5px;"
+ " min-height: 20px;"
+ "}"
+ "QScrollBar::handle:vertical:hover {"
+ " background-color: rgba(82, 194, 242, 0.8);"
+ "}"
+ );
+
+ // 状态标签样式
+ m_statusLabel->setStyleSheet(
+ "QLabel {"
+ " color: rgb(150, 180, 210);"
+ " font-size: 12px;"
+ " font-weight: normal;"
+ " padding: 3px 6px;"
+ " background: transparent;"
+ "}"
+ );
+
+ qDebug() << "SystemLogPanel styles applied";
+}
+
+void SystemLogPanel::connectSignals()
+{
+ // 连接按钮信号
+ connect(m_clearButton, &QPushButton::clicked,
+ this, &SystemLogPanel::onClearButtonClicked);
+ connect(m_pauseButton, &QPushButton::clicked,
+ this, &SystemLogPanel::onPauseButtonClicked);
+
+ // 连接下拉框信号
+ connect(m_levelFilter, QOverload::of(&QComboBox::currentIndexChanged),
+ this, &SystemLogPanel::onLevelFilterChanged);
+
+ // 连接定时器信号
+ connect(m_statusUpdateTimer, &QTimer::timeout,
+ this, &SystemLogPanel::updateStatusInfo);
+
+ qDebug() << "SystemLogPanel signals connected";
+}
+
+void SystemLogPanel::addLog(LogLevel level, const QString &message)
+{
+ // 如果暂停则不添加日志
+ if (m_isPaused) {
+ return;
+ }
+
+ // 检查级别过滤
+ if (level < m_minLevel) {
+ return;
+ }
+
+ // 更新计数器
+ if (level >= 0 && level < 5) {
+ m_logCounts[level]++;
+ }
+ m_totalLogCount++;
+
+ // 格式化并添加日志条目
+ QString formattedEntry = formatLogEntry(level, message);
+ m_logTextEdit->append(formattedEntry);
+
+ // 限制日志行数
+ limitLogLines();
+
+ // 自动滚动到底部
+ scrollToBottom();
+
+ qDebug() << QString("Log added: [%1] %2").arg(getLevelName(level)).arg(message);
+}
+
+void SystemLogPanel::clearLogs()
+{
+ m_logTextEdit->clear();
+
+ // 重置计数器
+ for (int i = 0; i < 5; ++i) {
+ m_logCounts[i] = 0;
+ }
+ m_totalLogCount = 0;
+
+ // 更新状态信息
+ updateStatusInfo();
+
+ qDebug() << "System logs cleared";
+}
+
+void SystemLogPanel::pauseLogging()
+{
+ m_isPaused = true;
+ m_pauseButton->setText("恢复");
+ updateStatusInfo();
+ qDebug() << "Logging paused";
+}
+
+void SystemLogPanel::resumeLogging()
+{
+ m_isPaused = false;
+ m_pauseButton->setText("暂停");
+ updateStatusInfo();
+ qDebug() << "Logging resumed";
+}
+
+void SystemLogPanel::setLogLevelFilter(LogLevel minLevel)
+{
+ m_minLevel = minLevel;
+ // 更新下拉框选择
+ for (int i = 0; i < m_levelFilter->count(); ++i) {
+ if (m_levelFilter->itemData(i).toInt() == static_cast(minLevel)) {
+ m_levelFilter->setCurrentIndex(i);
+ break;
+ }
+ }
+ qDebug() << "Log level filter set to:" << getLevelName(minLevel);
+}
+
+void SystemLogPanel::onClearButtonClicked()
+{
+ clearLogs();
+}
+
+void SystemLogPanel::onPauseButtonClicked()
+{
+ if (m_isPaused) {
+ resumeLogging();
+ } else {
+ pauseLogging();
+ }
+}
+
+void SystemLogPanel::onLevelFilterChanged(int index)
+{
+ if (index >= 0 && index < m_levelFilter->count()) {
+ LogLevel newLevel = static_cast(m_levelFilter->itemData(index).toInt());
+ m_minLevel = newLevel;
+ qDebug() << "Log level filter changed to:" << getLevelName(newLevel);
+ }
+}
+
+void SystemLogPanel::updateStatusInfo()
+{
+ QString statusText = QString("总计: %1 | 错误: %2 | 警告: %3")
+ .arg(m_totalLogCount)
+ .arg(m_logCounts[Error])
+ .arg(m_logCounts[Warning]);
+
+ if (m_isPaused) {
+ statusText += " | 已暂停";
+ } else {
+ statusText += " | 运行中";
+ }
+
+ m_statusLabel->setText(statusText);
+}
+
+QString SystemLogPanel::formatLogEntry(LogLevel level, const QString &message)
+{
+ QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
+ QString levelIcon = getLevelIcon(level);
+ QString levelColor = getLevelColor(level);
+
+ return QString("[%2] %3 %4")
+ .arg(levelColor)
+ .arg(timestamp)
+ .arg(levelIcon)
+ .arg(message);
+}
+
+QString SystemLogPanel::getLevelIcon(LogLevel level)
+{
+ switch (level) {
+ case Debug: return "🔍";
+ case Info: return "🔵";
+ case Warning: return "🟡";
+ case Error: return "🔴";
+ case Success: return "🟢";
+ default: return "⚪";
+ }
+}
+
+QString SystemLogPanel::getLevelColor(LogLevel level)
+{
+ switch (level) {
+ case Debug: return "#9E9E9E";
+ case Info: return "#52C2F2";
+ case Warning: return "#FFD700";
+ case Error: return "#FF4444";
+ case Success: return "#00FF7F";
+ default: return "#FFFFFF";
+ }
+}
+
+QString SystemLogPanel::getLevelName(LogLevel level)
+{
+ switch (level) {
+ case Debug: return "Debug";
+ case Info: return "Info";
+ case Warning: return "Warning";
+ case Error: return "Error";
+ case Success: return "Success";
+ default: return "Unknown";
+ }
+}
+
+void SystemLogPanel::limitLogLines()
+{
+ // 获取文档和光标
+ QTextDocument *document = m_logTextEdit->document();
+ int blockCount = document->blockCount();
+
+ // 如果超过最大行数,删除最旧的行
+ if (blockCount > m_maxLogLines) {
+ QTextCursor cursor(document);
+ cursor.movePosition(QTextCursor::Start);
+ cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor,
+ blockCount - m_maxLogLines);
+ cursor.removeSelectedText();
+ }
+}
+
+void SystemLogPanel::scrollToBottom()
+{
+ QScrollBar *scrollBar = m_logTextEdit->verticalScrollBar();
+ scrollBar->setValue(scrollBar->maximum());
+}
\ 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 b30563ad..c7bd330e 100644
--- a/src/Client/src/ui/dialogs/DeviceDialog.cpp
+++ b/src/Client/src/ui/dialogs/DeviceDialog.cpp
@@ -8,6 +8,7 @@
#include "ui/dialogs/DeviceDialog.h"
#include "build/ui_DeviceDialog.h"
+#include "utils/SystemLogger.h"
// Qt headers
#include
@@ -61,6 +62,7 @@ void DeviceDialog::setDeviceInfo(const QString &deviceId, const QString &name, c
const QString &createdAt, const QString &updatedAt)
{
m_currentDeviceId = deviceId;
+ SystemLogger::getInstance()->logInfo(QString("打开设备详情对话框: %1").arg(name));
// 设置设备图标
setDeviceIcon(type);
@@ -284,6 +286,7 @@ void DeviceDialog::refreshDeviceInfo()
void DeviceDialog::onConnectClicked()
{
if (!m_currentDeviceId.isEmpty()) {
+ SystemLogger::getInstance()->logInfo("从详情对话框请求连接设备");
emit deviceConnectRequested(m_currentDeviceId);
// 记录操作日志
@@ -294,6 +297,7 @@ void DeviceDialog::onConnectClicked()
void DeviceDialog::onDisconnectClicked()
{
if (!m_currentDeviceId.isEmpty()) {
+ SystemLogger::getInstance()->logInfo("从详情对话框请求断开设备");
emit deviceDisconnectRequested(m_currentDeviceId);
// 记录操作日志
@@ -304,6 +308,7 @@ void DeviceDialog::onDisconnectClicked()
void DeviceDialog::onLocateClicked()
{
if (!m_currentDeviceId.isEmpty()) {
+ SystemLogger::getInstance()->logInfo("从详情对话框请求设备定位");
emit deviceLocationRequested(m_currentDeviceId);
// 记录操作日志
@@ -313,6 +318,7 @@ void DeviceDialog::onLocateClicked()
void DeviceDialog::onRefreshClicked()
{
+ SystemLogger::getInstance()->logInfo("刷新设备信息");
refreshDeviceInfo();
}
diff --git a/src/Client/src/ui/main/MainWindow.cpp b/src/Client/src/ui/main/MainWindow.cpp
index 234832ea..b541d81f 100644
--- a/src/Client/src/ui/main/MainWindow.cpp
+++ b/src/Client/src/ui/main/MainWindow.cpp
@@ -9,6 +9,7 @@
#include "ui/main/MainWindow.h"
#include "build/ui_MainWindow.h"
#include "ui/dialogs/DeviceDialog.h"
+#include "utils/SystemLogger.h"
// Qt GUI头文件
#include
@@ -42,11 +43,14 @@
#include
#include
#include
+#include
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, m_ui(new Ui::MainWindow)
, m_deviceListPanel(nullptr)
+ , m_systemLogPanel(nullptr)
+ , m_leftPanelSplitter(nullptr)
// , m_intelligenceUI(nullptr) // 暂时注释掉
{
m_ui->setupUi(this);
@@ -84,22 +88,60 @@ void MainWindow::setupUI()
// 初始化随机数生成器
qsrand(QTime::currentTime().msec());
- // 创建并集成DeviceListPanel到左侧面板
- setupDeviceListPanel();
+ // 创建并集成SystemLogPanel和DeviceListPanel到左侧面板
+ setupSystemLogPanel();
// 恢复地图显示控制
setupMapDisplay();
- // 控制添加机器人
- addRobotControl(m_ui->addrobot);
- // 控制机器人列表
- robotsInfosControl(m_ui->robottab);
+ // 注意:原有的重复设备管理按钮已被移除,功能集成在DeviceListPanel中
+
+ // 记录系统启动日志
+ SystemLogger::getInstance()->logInfo("系统启动完成");
}
-void MainWindow::setupDeviceListPanel()
+void MainWindow::setupSystemLogPanel()
{
+ // 创建系统日志面板
+ m_systemLogPanel = new SystemLogPanel(this);
+
// 创建设备列表面板
m_deviceListPanel = new DeviceListPanel(this);
+ // 创建垂直分割器
+ m_leftPanelSplitter = new QSplitter(Qt::Vertical, this);
+
+ // 设置系统日志面板的高度限制
+ m_systemLogPanel->setMinimumHeight(200);
+ m_systemLogPanel->setMaximumHeight(400);
+
+ // 设置设备管理面板的高度限制
+ m_deviceListPanel->setMinimumHeight(300);
+
+ // 添加面板到分割器
+ m_leftPanelSplitter->addWidget(m_systemLogPanel);
+ m_leftPanelSplitter->addWidget(m_deviceListPanel);
+
+ // 设置分割比例 (35% : 65%)
+ m_leftPanelSplitter->setSizes(QList() << 350 << 650);
+
+ // 设置分割器样式
+ m_leftPanelSplitter->setStyleSheet(
+ "QSplitter::handle {"
+ " background: qlineargradient(x1:0, y1:0, x2:1, y2:0,"
+ " stop:0 rgba(82, 194, 242, 0.3),"
+ " stop:0.5 rgba(82, 194, 242, 0.8),"
+ " stop:1 rgba(82, 194, 242, 0.3));"
+ " border-radius: 2px;"
+ " height: 8px;"
+ "}"
+ "QSplitter::handle:hover {"
+ " background: qlineargradient(x1:0, y1:0, x2:1, y2:0,"
+ " stop:0 rgba(82, 194, 242, 0.5),"
+ " stop:0.5 rgba(82, 194, 242, 1.0),"
+ " stop:1 rgba(82, 194, 242, 0.5));"
+ "}"
+ );
+
// 获取左侧面板的布局
QVBoxLayout *leftLayout = qobject_cast(m_ui->leftPanel->layout());
if (leftLayout) {
@@ -111,8 +153,8 @@ void MainWindow::setupDeviceListPanel()
}
}
- // 将DeviceListPanel添加到左侧面板
- leftLayout->addWidget(m_deviceListPanel);
+ // 将分割器添加到左侧面板
+ leftLayout->addWidget(m_leftPanelSplitter);
// 连接DeviceListPanel信号
connect(m_deviceListPanel, &DeviceListPanel::deviceSelected,
@@ -126,12 +168,20 @@ void MainWindow::setupDeviceListPanel()
connect(m_deviceListPanel, &DeviceListPanel::addDeviceRequested,
this, &MainWindow::onAddDeviceRequested);
- qDebug() << "DeviceListPanel integrated into left panel - original content hidden";
+ qDebug() << "SystemLogPanel and DeviceListPanel integrated with QSplitter (35%:65%)";
+ SystemLogger::getInstance()->logInfo("系统日志面板初始化完成");
} else {
qWarning() << "Failed to get left panel layout";
+ SystemLogger::getInstance()->logError("左侧面板布局获取失败");
}
}
+void MainWindow::setupDeviceListPanel()
+{
+ // 此方法已被setupSystemLogPanel()替代,保留以兼容可能的调用
+ qDebug() << "setupDeviceListPanel() is deprecated, use setupSystemLogPanel() instead";
+}
+
void MainWindow::setupStyle()
{
// 设置按钮样式 - 现代化军用风格
@@ -162,10 +212,7 @@ void MainWindow::setupStyle()
"}";
// 应用样式到所有按钮
- m_ui->robottab->setStyleSheet(buttonStyle);
- m_ui->addrobot->setStyleSheet(buttonStyle);
- m_ui->addUAV->setStyleSheet(buttonStyle);
- m_ui->UAVtab->setStyleSheet(buttonStyle);
+ // 注意:原有的重复设备管理按钮已被移除
m_ui->UAVview->setStyleSheet(buttonStyle);
m_ui->robotView->setStyleSheet(buttonStyle);
m_ui->robotMapping->setStyleSheet(buttonStyle);
@@ -178,8 +225,7 @@ void MainWindow::setupStyle()
void MainWindow::connectSignals()
{
// 连接按钮信号
- connect(m_ui->addUAV, &QPushButton::clicked, this, &MainWindow::onAddUAVClicked);
- connect(m_ui->UAVtab, &QPushButton::clicked, this, &MainWindow::onUAVTabClicked);
+ // 注意:原有的重复设备管理按钮信号已被移除
connect(m_ui->UAVview, &QPushButton::clicked, this, &MainWindow::onUAVViewClicked);
connect(m_ui->robotView, &QPushButton::clicked, this, &MainWindow::onRobotViewClicked);
connect(m_ui->robotMapping, &QPushButton::clicked, this, &MainWindow::onRobotMappingClicked);
@@ -424,6 +470,9 @@ void MainWindow::onAddRobotClicked()
m_robotList.append(qMakePair(name, ip));
QMessageBox::information(this, "成功", "机器人添加成功!");
+ // 记录成功日志
+ SystemLogger::getInstance()->logSuccess(QString("机器人添加成功: %1 (%2)").arg(name).arg(deviceId));
+
// 刷新设备列表
if (m_deviceListPanel) {
m_deviceListPanel->refreshDeviceList();
@@ -432,6 +481,7 @@ void MainWindow::onAddRobotClicked()
dialog->accept();
} else {
QMessageBox::warning(this, "错误", "保存到数据库失败!");
+ SystemLogger::getInstance()->logError(QString("机器人添加失败: %1 - 数据库保存失败").arg(name));
}
} else {
QMessageBox::warning(this, "错误", "请填写完整信息!");
@@ -611,6 +661,9 @@ void MainWindow::onAddUAVClicked()
m_uavList.append(qMakePair(name, ip));
QMessageBox::information(this, "成功", "无人机添加成功!");
+ // 记录成功日志
+ SystemLogger::getInstance()->logSuccess(QString("无人机添加成功: %1 (%2)").arg(name).arg(deviceId));
+
// 刷新设备列表
if (m_deviceListPanel) {
m_deviceListPanel->refreshDeviceList();
@@ -619,6 +672,7 @@ void MainWindow::onAddUAVClicked()
dialog->accept();
} else {
QMessageBox::warning(this, "错误", "保存到数据库失败!");
+ SystemLogger::getInstance()->logError(QString("无人机添加失败: %1 - 数据库保存失败").arg(name));
}
} else {
QMessageBox::warning(this, "错误", "请填写完整信息!");
@@ -724,6 +778,7 @@ void MainWindow::onDeviceControlRequested(const QString &deviceId)
void MainWindow::onDeviceLocationRequested(const QString &deviceId)
{
qDebug() << "Device location requested for:" << deviceId;
+ SystemLogger::getInstance()->logInfo(QString("请求设备定位: %1").arg(deviceId));
// 从设备列表面板获取设备信息
if (m_deviceListPanel) {
@@ -785,6 +840,7 @@ void MainWindow::onDeviceLocationRequested(const QString &deviceId)
}
qDebug() << QString("设备 %1 定位到位置: (%2, %3)").arg(deviceName).arg(latitude).arg(longitude);
+ SystemLogger::getInstance()->logSuccess(QString("设备定位完成: %1 -> (%2, %3)").arg(deviceName).arg(latitude).arg(longitude));
} else {
QMessageBox::warning(this, "设备定位",
QString("无法获取设备位置信息\n设备ID: %1").arg(deviceId));
@@ -806,6 +862,7 @@ void MainWindow::onDeviceDetailsRequested(const QString &deviceId)
if (!db.open()) {
qWarning() << "Failed to connect to database for device details:" << db.lastError().text();
+ SystemLogger::getInstance()->logError("数据库连接失败 - 无法查询设备详情");
QMessageBox::warning(this, "错误", "无法连接到数据库");
return;
}
@@ -888,6 +945,7 @@ void MainWindow::onAddDeviceRequested(const QString &deviceType)
void MainWindow::setupMapDisplay()
{
qDebug() << "Setting up map display...";
+ SystemLogger::getInstance()->logInfo("开始设置地图显示");
// 创建WebEngineView来显示地图
QWebEngineView* webView = new QWebEngineView(m_ui->MapDisplayer);
@@ -911,9 +969,11 @@ void MainWindow::setupMapDisplay()
connect(webView, &QWebEngineView::loadFinished, this, [this](bool success) {
if (success) {
qDebug() << "Map loaded successfully, initializing device markers...";
+ SystemLogger::getInstance()->logSuccess("地图加载完成");
QTimer::singleShot(1000, this, &MainWindow::initializeDeviceMarkersOnMap);
} else {
qDebug() << "Map loading failed!";
+ SystemLogger::getInstance()->logError("地图加载失败");
}
});
}
@@ -976,6 +1036,7 @@ bool MainWindow::addDeviceToDatabase(const QString &deviceId, const QString &nam
if (!db.open()) {
qWarning() << "Failed to connect to database for adding device:" << db.lastError().text();
+ SystemLogger::getInstance()->logError("数据库连接失败 - 无法添加设备");
return false;
}
diff --git a/src/Client/src/utils/SystemLogger.cpp b/src/Client/src/utils/SystemLogger.cpp
new file mode 100644
index 00000000..7cb5bd89
--- /dev/null
+++ b/src/Client/src/utils/SystemLogger.cpp
@@ -0,0 +1,158 @@
+/**
+ * @file SystemLogger.cpp
+ * @brief 系统日志管理器单例类实现
+ * @author Qt UI Developer Expert
+ * @date 2024-12-21
+ * @version 1.0
+ */
+
+#include "utils/SystemLogger.h"
+#include
+#include
+#include
+#include
+#include
+
+// 静态成员初始化
+SystemLogger* SystemLogger::s_instance = nullptr;
+QMutex SystemLogger::s_mutex;
+
+SystemLogger::SystemLogger(QObject *parent)
+ : QObject(parent)
+ , m_consoleOutputEnabled(true)
+{
+ qDebug() << "SystemLogger instance created";
+}
+
+SystemLogger::~SystemLogger()
+{
+ qDebug() << "SystemLogger instance destroyed";
+}
+
+SystemLogger* SystemLogger::getInstance()
+{
+ // 双重检查锁定模式确保线程安全
+ if (s_instance == nullptr) {
+ QMutexLocker locker(&s_mutex);
+ if (s_instance == nullptr) {
+ s_instance = new SystemLogger();
+ }
+ }
+ return s_instance;
+}
+
+void SystemLogger::destroyInstance()
+{
+ QMutexLocker locker(&s_mutex);
+ if (s_instance != nullptr) {
+ delete s_instance;
+ s_instance = nullptr;
+ }
+}
+
+void SystemLogger::logDebug(const QString &message)
+{
+ log(Debug, message);
+}
+
+void SystemLogger::logInfo(const QString &message)
+{
+ log(Info, message);
+}
+
+void SystemLogger::logWarning(const QString &message)
+{
+ log(Warning, message);
+}
+
+void SystemLogger::logError(const QString &message)
+{
+ log(Error, message);
+}
+
+void SystemLogger::logSuccess(const QString &message)
+{
+ log(Success, message);
+}
+
+void SystemLogger::log(LogLevel level, const QString &message)
+{
+ logInternal(level, message);
+}
+
+void SystemLogger::setConsoleOutputEnabled(bool enabled)
+{
+ QMutexLocker locker(&m_logMutex);
+ m_consoleOutputEnabled = enabled;
+
+ QString statusMsg = enabled ? "Console output enabled" : "Console output disabled";
+ qDebug() << "SystemLogger:" << statusMsg;
+}
+
+QString SystemLogger::getLevelString(LogLevel level)
+{
+ switch (level) {
+ case Debug: return "DEBUG";
+ case Info: return "INFO";
+ case Warning: return "WARNING";
+ case Error: return "ERROR";
+ case Success: return "SUCCESS";
+ default: return "UNKNOWN";
+ }
+}
+
+void SystemLogger::logInternal(LogLevel level, const QString &message)
+{
+ // 线程安全保护
+ QMutexLocker locker(&m_logMutex);
+
+ // 输出到控制台(如果启用)
+ if (m_consoleOutputEnabled) {
+ outputToConsole(level, message);
+ }
+
+ // 发出信号通知UI组件
+ emit logAdded(level, message);
+}
+
+void SystemLogger::outputToConsole(LogLevel level, const QString &message)
+{
+ QString timestamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz");
+ QString levelStr = getLevelString(level);
+ QString logLine = QString("[%1] [%2] %3").arg(timestamp, levelStr, message);
+
+ // 根据日志级别选择输出流
+ switch (level) {
+ case Error:
+ // 错误输出到标准错误流
+ std::cerr << logLine.toStdString() << std::endl;
+ break;
+ case Warning:
+ // 警告也输出到标准错误流
+ std::cerr << logLine.toStdString() << std::endl;
+ break;
+ default:
+ // 其他级别输出到标准输出流
+ std::cout << logLine.toStdString() << std::endl;
+ break;
+ }
+
+ // 同时也输出到Qt的调试系统
+ switch (level) {
+ case Debug:
+ qDebug().noquote() << logLine;
+ break;
+ case Info:
+ qInfo().noquote() << logLine;
+ break;
+ case Warning:
+ qWarning().noquote() << logLine;
+ break;
+ case Error:
+ qCritical().noquote() << logLine;
+ break;
+ case Success:
+ qInfo().noquote() << logLine; // 成功信息使用qInfo输出
+ break;
+ }
+}
\ No newline at end of file