Ver código fonte

任务界面

flower_linux 5 meses atrás
pai
commit
ad46e93da3
38 arquivos alterados com 5706 adições e 79 exclusões
  1. 28 0
      CMakeLists.txt
  2. 39 6
      mainwindow.cpp
  3. 4 1
      mainwindow.h
  4. 222 0
      src/api/SoftBusAPI.cpp
  5. 80 0
      src/api/SoftBusAPI.h
  6. 56 0
      src/can_manager/can_manager.cpp
  7. 28 0
      src/can_manager/can_manager.h
  8. 12 14
      src/connect_signal/view_instance_manager.cpp
  9. 112 0
      src/core/CoreService.cpp
  10. 38 0
      src/core/CoreService.h
  11. 89 0
      src/daemon/daemon_client.cpp
  12. 29 0
      src/daemon/daemon_client.h
  13. 158 28
      src/manage_network/network_manager.cpp
  14. 36 0
      src/manage_network/network_manager.h
  15. 77 15
      src/manage_serial/serial_manager.cpp
  16. 30 0
      src/manage_serial/serial_manager.h
  17. 37 0
      src/my_dock_manager/mdockmanager.cpp
  18. 84 6
      src/soft_bus_core/soft_bus_core.cpp
  19. 8 3
      src/soft_bus_core/soft_bus_core.h
  20. 592 0
      src/task_manager/EventTaskExecutor.cpp
  21. 157 0
      src/task_manager/EventTaskExecutor.h
  22. 612 0
      src/task_manager/PollingTaskExecutor.cpp
  23. 113 0
      src/task_manager/PollingTaskExecutor.h
  24. 40 0
      src/task_manager/TaskExecutor.cpp
  25. 81 0
      src/task_manager/TaskExecutor.h
  26. 343 0
      src/task_manager/TaskManager.cpp
  27. 123 0
      src/task_manager/TaskManager.h
  28. 486 0
      src/task_manager/TaskScheduler.cpp
  29. 214 0
      src/task_manager/TaskScheduler.h
  30. 156 0
      src/task_manager/TransferTask.h
  31. 83 6
      src/view_device_config/device_tree_widget.cpp
  32. 154 0
      src/view_network/network_settings_widget.cpp
  33. 9 0
      src/view_network/network_settings_widget.h
  34. 52 0
      src/view_network/network_settings_widget.ui
  35. 580 0
      src/view_task/TaskConfigWidget.cpp
  36. 101 0
      src/view_task/TaskConfigWidget.h
  37. 557 0
      src/view_task/TaskManagementPage.cpp
  38. 86 0
      src/view_task/TaskManagementPage.h

+ 28 - 0
CMakeLists.txt

@@ -87,6 +87,8 @@ qt_add_executable(soft_bus
     src/view_network/network_data_widget.h src/view_network/network_data_widget.cpp src/view_network/network_data_widget.ui
     src/view_can/viewcan.h src/view_can/viewcan.cpp src/view_can/viewcan.ui
     src/view_can/can_data_widget.h src/view_can/can_data_widget.cpp src/view_can/can_data_widget.ui
+    src/view_task/TaskManagementPage.h src/view_task/TaskManagementPage.cpp
+    src/view_task/TaskConfigWidget.h src/view_task/TaskConfigWidget.cpp
     src/view_device_config/device_tree_widget.h src/view_device_config/device_tree_widget.cpp src/view_device_config/device_tree_widget.ui
     src/view_device_config/device_log_dialog.h src/view_device_config/device_log_dialog.cpp
     src/libmodbus/modbus_config_widget.h src/libmodbus/modbus_config_widget.cpp src/libmodbus/modbus_config_widget.ui
@@ -136,6 +138,19 @@ qt_add_executable(soft_bus
     src/core/CoreService.h
     src/core/CoreService.cpp
 
+    # 新增:任务管理器
+    src/task_manager/TransferTask.h
+    src/task_manager/TaskManager.h
+    src/task_manager/TaskManager.cpp
+    src/task_manager/TaskScheduler.h
+    src/task_manager/TaskScheduler.cpp
+    src/task_manager/TaskExecutor.h
+    src/task_manager/TaskExecutor.cpp
+    src/task_manager/PollingTaskExecutor.h
+    src/task_manager/PollingTaskExecutor.cpp
+    src/task_manager/EventTaskExecutor.h
+    src/task_manager/EventTaskExecutor.cpp
+
     # 新增:统一接口层 (API)
     src/api/SoftBusAPI.h
     src/api/SoftBusAPI.cpp
@@ -345,6 +360,19 @@ qt_add_executable(soft_bus_daemon
     src/protocol_plugin/ProtocolPluginManager.h
     src/protocol_plugin/ProtocolPluginManager.cpp
     src/protocol_plugin/IProtocolParser.h
+    
+    # 任务管理器(守护进程也需要)
+    src/task_manager/TransferTask.h
+    src/task_manager/TaskManager.h
+    src/task_manager/TaskManager.cpp
+    src/task_manager/TaskScheduler.h
+    src/task_manager/TaskScheduler.cpp
+    src/task_manager/TaskExecutor.h
+    src/task_manager/TaskExecutor.cpp
+    src/task_manager/PollingTaskExecutor.h
+    src/task_manager/PollingTaskExecutor.cpp
+    src/task_manager/EventTaskExecutor.h
+    src/task_manager/EventTaskExecutor.cpp
 )
 
 # 守护进程只需要 Qt Core 和 DBus,不需要 Widgets

+ 39 - 6
mainwindow.cpp

@@ -10,6 +10,7 @@
 #include "view_serial/serialdockpage.h"
 #include "view_network/networkmodule.h"
 #include "view_network/networkdockpage.h"
+#include "view_task/TaskManagementPage.h"
 #include "connect_signal/view_instance_manager.h"
 #include "view_device_config/device_tree_widget.h"
 #include "utils/logging.h"
@@ -71,6 +72,7 @@ void MainWindow::createUI() {
     createSerialToolbar();
     createNetworkToolbar();
     createDatabaseToolbar();
+    createTaskToolbar();
     createSettingsToolbar();
     createHelpToolbar();
 
@@ -98,6 +100,8 @@ void MainWindow::createMenuBar() {
         viewMenu->addAction(QIcon(":/qrc/icons/network.png"), "网络");
     QAction *databaseAction =
         viewMenu->addAction(QIcon(":/qrc/icons/grid_on.svg"), "数据库");
+    QAction *taskAction =
+        viewMenu->addAction(QIcon(":/qrc/icons/task.png"), "任务管理");
     QAction *settingsAction =
         viewMenu->addAction(QIcon(":/qrc/icons/settings.png"), "设置");
     QAction *helpAction =
@@ -110,9 +114,15 @@ void MainWindow::createMenuBar() {
             [this]() { switchToPage(2); });
     connect(databaseAction, &QAction::triggered, this,
             [this]() { switchToPage(3); });
+    connect(taskAction, &QAction::triggered, this,
+            [this]() { 
+                if (m_taskPageIndex >= 0) {
+                    switchToPage(m_taskPageIndex);
+                }
+            });
     connect(settingsAction, &QAction::triggered, this,
-            [this]() { switchToPage(4); });
-    connect(helpAction, &QAction::triggered, this, [this]() { switchToPage(4); });
+            [this]() { switchToPage(5); });
+    connect(helpAction, &QAction::triggered, this, [this]() { switchToPage(6); });
 
 
 
@@ -225,6 +235,22 @@ void MainWindow::createDatabaseToolbar() {
     }
 }
 
+void MainWindow::createTaskToolbar() {
+    // 创建任务管理页面
+    if (!m_taskPage) {
+        m_taskPage = new TaskManagementPage(this);
+    }
+
+    // 创建空工具栏以保持索引一致性(任务页面的工具栏已内置在页面中)
+    Toolbar *taskToolbar = new Toolbar("任务管理工具栏", this);
+    addToolBar(Qt::TopToolBarArea, taskToolbar);
+    taskToolbar->hide();
+    m_toolbars.append(taskToolbar);
+
+    // 添加任务页面到堆栈
+    m_taskPageIndex = m_pageStack->addWidget(m_taskPage);
+}
+
 void MainWindow::createSettingsToolbar() {
     // 创建设置界面工具栏
     Toolbar *settingsToolbar = new Toolbar("设置工具栏", this);
@@ -301,8 +327,9 @@ void MainWindow::setupShortcuts() {
     QShortcut *serialShortcut = new QShortcut(QKeySequence("Ctrl+2"), this);
     QShortcut *networkShortcut = new QShortcut(QKeySequence("Ctrl+3"), this);
     QShortcut *databaseShortcut = new QShortcut(QKeySequence("Ctrl+4"), this);
-    QShortcut *settingsShortcut = new QShortcut(QKeySequence("Ctrl+5"), this);
-    QShortcut *helpShortcut = new QShortcut(QKeySequence("Ctrl+6"), this);
+    QShortcut *taskShortcut = new QShortcut(QKeySequence("Ctrl+5"), this);
+    QShortcut *settingsShortcut = new QShortcut(QKeySequence("Ctrl+6"), this);
+    QShortcut *helpShortcut = new QShortcut(QKeySequence("Ctrl+7"), this);
 
     // 连接快捷键信号
     connect(homeShortcut, &QShortcut::activated, this,
@@ -313,10 +340,16 @@ void MainWindow::setupShortcuts() {
             [this]() { switchToPage(2); });
     connect(databaseShortcut, &QShortcut::activated, this,
             [this]() { switchToPage(3); });
+    connect(taskShortcut, &QShortcut::activated, this,
+            [this]() { 
+                if (m_taskPageIndex >= 0) {
+                    switchToPage(m_taskPageIndex);
+                }
+            });
     connect(settingsShortcut, &QShortcut::activated, this,
-            [this]() { switchToPage(4); });
-    connect(helpShortcut, &QShortcut::activated, this,
             [this]() { switchToPage(5); });
+    connect(helpShortcut, &QShortcut::activated, this,
+            [this]() { switchToPage(6); });
 }
 /*
 function:  链接信号槽

+ 4 - 1
mainwindow.h

@@ -8,6 +8,7 @@
 class DatabaseModule;
 class SerialModule;
 class NetworkModule;
+class TaskManagementPage;
 class Toolbar;
 class DaemonClient;
 class SettingsDialog;
@@ -34,7 +35,7 @@ private:
     void createSerialToolbar();
     void createNetworkToolbar();
     void createDatabaseToolbar();
-
+    void createTaskToolbar();
     void createSettingsToolbar();
     void createHelpToolbar();
     // motion-切换页面
@@ -63,9 +64,11 @@ private:
     SerialModule *m_serialModule = nullptr;
     NetworkModule *m_networkModule = nullptr;
     DatabaseModule *m_databaseModule = nullptr;
+    TaskManagementPage *m_taskPage = nullptr;
     int m_serialPageIndex = -1;
     int m_networkPageIndex = -1;
     int m_databasePageIndex = -1;
+    int m_taskPageIndex = -1;
     
     // 守护进程客户端和状态显示
     DaemonClient *m_daemonClient = nullptr;

+ 222 - 0
src/api/SoftBusAPI.cpp

@@ -7,6 +7,8 @@
 #include "manage_serial/serial_manager.h"
 #include "manage_network/network_manager.h"
 #include "soft_bus_core/soft_bus_core.h"
+#include "task_manager/TaskManager.h"
+#include "task_manager/TaskScheduler.h"
 #include "utils/logging.h"
 #ifndef SOFT_BUS_DAEMON_BUILD
 #include "daemon/daemon_client.h"
@@ -77,6 +79,17 @@ bool SoftBusAPI::initialize() {
     connect(dispatcher, &MessageDispatcher::topicUpdated,
             this, &SoftBusAPI::onTopicUpdated, Qt::QueuedConnection);
 
+    // 连接任务调度器的信号
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    if (taskScheduler) {
+        connect(taskScheduler, &TaskScheduler::taskStatusChanged,
+                this, [this](const QString &taskId, TaskStatus status) {
+                    emit taskStatusChanged(taskId, static_cast<int>(status));
+                }, Qt::QueuedConnection);
+        connect(taskScheduler, &TaskScheduler::taskError,
+                this, &SoftBusAPI::taskError, Qt::QueuedConnection);
+    }
+
     // 初始化设备管理器
     initializeManagers();
 
@@ -829,6 +842,16 @@ void SoftBusAPI::setDaemonClient(DaemonClient* daemonClient) {
     
     m_daemonClient = daemonClient;
     
+    // 设置 DaemonClient 到 TaskScheduler(用于任务启动)
+    CoreService* coreService = CoreService::instance();
+    if (coreService && coreService->isInitialized()) {
+        TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+        if (taskScheduler) {
+            taskScheduler->setDaemonClient(daemonClient);
+            LOG_INFO() << "DaemonClient set to TaskScheduler";
+        }
+    }
+    
     // 连接新的信号(使用队列连接确保线程安全)
     if (m_daemonClient) {
         // 连接硬件数据接收信号
@@ -881,3 +904,202 @@ bool SoftBusAPI::useDaemonMode() const {
 #endif
 }
 
+// ========== 任务管理接口实现 ==========
+
+bool SoftBusAPI::createTask(const TransferTask &task) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskManager* taskManager = coreService->getTaskManager();
+    if (!taskManager) {
+        LOG_ERROR() << "TaskManager not available";
+        return false;
+    }
+
+    return taskManager->createTask(task);
+}
+
+bool SoftBusAPI::updateTask(const QString &taskId, const TransferTask &task) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskManager* taskManager = coreService->getTaskManager();
+    if (!taskManager) {
+        LOG_ERROR() << "TaskManager not available";
+        return false;
+    }
+
+    return taskManager->updateTask(taskId, task);
+}
+
+bool SoftBusAPI::deleteTask(const QString &taskId) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskManager* taskManager = coreService->getTaskManager();
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    
+    if (!taskManager) {
+        LOG_ERROR() << "TaskManager not available";
+        return false;
+    }
+
+    // 先停止任务(如果正在运行)
+    if (taskScheduler) {
+        taskScheduler->stopTask(taskId);
+    }
+
+    // 然后删除任务
+    return taskManager->deleteTask(taskId);
+}
+
+TransferTask SoftBusAPI::getTask(const QString &taskId) const {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return TransferTask();
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return TransferTask();
+    }
+
+    TaskManager* taskManager = coreService->getTaskManager();
+    if (!taskManager) {
+        LOG_ERROR() << "TaskManager not available";
+        return TransferTask();
+    }
+
+    return taskManager->getTask(taskId);
+}
+
+QList<TransferTask> SoftBusAPI::getAllTasks() const {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return QList<TransferTask>();
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return QList<TransferTask>();
+    }
+
+    TaskManager* taskManager = coreService->getTaskManager();
+    if (!taskManager) {
+        LOG_ERROR() << "TaskManager not available";
+        return QList<TransferTask>();
+    }
+
+    return taskManager->getAllTasks();
+}
+
+bool SoftBusAPI::startTask(const QString &taskId) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    if (!taskScheduler) {
+        LOG_ERROR() << "TaskScheduler not available";
+        return false;
+    }
+
+    return taskScheduler->startTask(taskId);
+}
+
+bool SoftBusAPI::stopTask(const QString &taskId) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    if (!taskScheduler) {
+        LOG_ERROR() << "TaskScheduler not available";
+        return false;
+    }
+
+    return taskScheduler->stopTask(taskId);
+}
+
+bool SoftBusAPI::pauseTask(const QString &taskId) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    if (!taskScheduler) {
+        LOG_ERROR() << "TaskScheduler not available";
+        return false;
+    }
+
+    return taskScheduler->pauseTask(taskId);
+}
+
+bool SoftBusAPI::resumeTask(const QString &taskId) {
+    if (!m_initialized) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return false;
+    }
+
+    CoreService* coreService = CoreService::instance();
+    if (!coreService->isInitialized()) {
+        LOG_ERROR() << "CoreService not initialized";
+        return false;
+    }
+
+    TaskScheduler* taskScheduler = coreService->getTaskScheduler();
+    if (!taskScheduler) {
+        LOG_ERROR() << "TaskScheduler not available";
+        return false;
+    }
+
+    return taskScheduler->resumeTask(taskId);
+}
+

+ 80 - 0
src/api/SoftBusAPI.h

@@ -17,6 +17,7 @@
 #include "core/SoftBusCore.h"
 #include "common/dom/DomBase.h"
 #include "soft_bus_core/soft_bus_core.h"
+#include "task_manager/TransferTask.h"
 
 // 前向声明
 class CanManager;
@@ -350,6 +351,70 @@ public:
     QList<BusMessage> queryBusMessages(const QString &source, const QString &destination,
                                        qint64 startTime, qint64 endTime);
 
+    // ========== 任务管理接口 ==========
+    /**
+     * @brief 创建任务
+     * @param task 任务信息
+     * @return 成功返回true
+     */
+    bool createTask(const TransferTask &task);
+
+    /**
+     * @brief 更新任务
+     * @param taskId 任务ID
+     * @param task 任务信息
+     * @return 成功返回true
+     */
+    bool updateTask(const QString &taskId, const TransferTask &task);
+
+    /**
+     * @brief 删除任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool deleteTask(const QString &taskId);
+
+    /**
+     * @brief 获取任务
+     * @param taskId 任务ID
+     * @return 任务信息,如果不存在返回默认任务
+     */
+    TransferTask getTask(const QString &taskId) const;
+
+    /**
+     * @brief 获取所有任务
+     * @return 任务列表
+     */
+    QList<TransferTask> getAllTasks() const;
+
+    /**
+     * @brief 启动任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool startTask(const QString &taskId);
+
+    /**
+     * @brief 停止任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool stopTask(const QString &taskId);
+
+    /**
+     * @brief 暂停任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool pauseTask(const QString &taskId);
+
+    /**
+     * @brief 恢复任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool resumeTask(const QString &taskId);
+
 signals:
     /**
      * @brief 数据变化信号 - UI监听此信号来刷新界面
@@ -451,6 +516,21 @@ signals:
      */
     void busMessageStored(BusMessage message);
 
+    // ========== 任务管理信号 ==========
+    /**
+     * @brief 任务状态变化信号
+     * @param taskId 任务ID
+     * @param status 新状态
+     */
+    void taskStatusChanged(QString taskId, int status);
+
+    /**
+     * @brief 任务错误信号
+     * @param taskId 任务ID
+     * @param error 错误信息
+     */
+    void taskError(QString taskId, QString error);
+
 private:
     SoftBusAPI(QObject* parent = nullptr);
     ~SoftBusAPI();

+ 56 - 0
src/can_manager/can_manager.cpp

@@ -267,6 +267,62 @@ DeviceBusCore *CanManager::getBusCore() const
     return m_busCore;
 }
 
+bool CanManager::lockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    // 检查设备是否已被锁定
+    if (m_deviceLocks.contains(deviceId)) {
+        QString lockingTaskId = m_deviceLocks.value(deviceId);
+        if (lockingTaskId != taskId) {
+            LOG_WARNING() << "CAN device" << deviceId << "is already locked by task" << lockingTaskId;
+            return false;
+        }
+        // 如果是同一个任务,直接返回成功
+        return true;
+    }
+
+    // 锁定设备
+    m_deviceLocks.insert(deviceId, taskId);
+    LOG_DEBUG() << "CAN device locked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool CanManager::unlockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    if (!m_deviceLocks.contains(deviceId)) {
+        LOG_WARNING() << "CAN device" << deviceId << "is not locked";
+        return false;
+    }
+
+    QString lockingTaskId = m_deviceLocks.value(deviceId);
+    if (lockingTaskId != taskId) {
+        LOG_WARNING() << "CAN device" << deviceId << "is locked by different task:" 
+                     << lockingTaskId << "not" << taskId;
+        return false;
+    }
+
+    m_deviceLocks.remove(deviceId);
+    LOG_DEBUG() << "CAN device unlocked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool CanManager::isDeviceLocked(const QString &deviceId) const
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+    return m_deviceLocks.contains(deviceId);
+}
+
 QString CanManager::getDeviceName(int comPort) const
 {
     if (m_portToDeviceName.contains(comPort))

+ 28 - 0
src/can_manager/can_manager.h

@@ -122,6 +122,30 @@ public:
     // 获取设备名称(通过com_port)
     QString getDeviceName(int comPort) const;
 
+    // 设备资源锁定机制
+    /**
+     * @brief 锁定设备
+     * @param deviceId 设备ID(设备名称)
+     * @param taskId 任务ID
+     * @return 成功返回true,如果设备已被其他任务锁定返回false
+     */
+    bool lockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 解锁设备
+     * @param deviceId 设备ID(设备名称)
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool unlockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 检查设备是否被锁定
+     * @param deviceId 设备ID(设备名称)
+     * @return 被锁定返回true
+     */
+    bool isDeviceLocked(const QString &deviceId) const;
+
 signals:
     // 发现新设备时发出的信号
     void deviceDiscovered(const QString &deviceName, int comPort);
@@ -174,6 +198,10 @@ private:
     QSet<int> m_lastDiscoveredDevices;
     // 互斥锁(mutable允许在const成员函数中使用)
     mutable QMutex m_mutex;
+
+    // 设备锁定映射表:device_id -> task_id
+    QMap<QString, QString> m_deviceLocks;
+    mutable QMutex m_deviceLocksMutex; // 保护设备锁定映射的互斥锁
 };
 
 #endif // CAN_MANAGER_H

+ 12 - 14
src/connect_signal/view_instance_manager.cpp

@@ -251,21 +251,20 @@ SerialDockPage* ViewInstanceManager::createSerialDockPage(QWidget* pParent)
         return nullptr;
     }
 
-    // 确保共享组件已创建
+    // 确保共享组件已创建(使用 MainWindow 作为父对象,因为它们是共享的)
+    // 注意:共享组件必须在创建 DockPage 之前创建,因为 DockPage 的 createUI() 会使用它们
     if (!hasSharedComponents()) {
         createSharedComponents(pParent, pBusCore);
     }
 
-    // 创建串口特有组件(如果尚未创建)
-    if (!hasSerialComponents()) {
-        createSerialComponents(pParent, pBusCore);
-    }
-
-    // 创建 SerialDockPage
+    // 创建 SerialDockPage(组件的创建由 SerialDockPage::createUI() 负责)
     SerialDockPage* pSerialDockPage = new SerialDockPage(pParent);
     
     // 注册到管理器
     registerView(EViewType::ViewSerial, pSerialDockPage);
+    
+    // 注意:串口特有组件的创建由 SerialDockPage::createUI() 负责
+    // 组件会使用 SerialDockPage 作为父对象,确保所有权清晰
 
     // 在所有组件创建完成后,初始化组件间的信号连接
     // 采用扁平化管理模式:由 ViewInstanceManager 统一管理所有组件间的连接
@@ -392,21 +391,20 @@ NetworkDockPage* ViewInstanceManager::createNetworkDockPage(QWidget* pParent)
         return nullptr;
     }
 
-    // 确保共享组件已创建
+    // 确保共享组件已创建(使用 MainWindow 作为父对象,因为它们是共享的)
+    // 注意:共享组件必须在创建 DockPage 之前创建,因为 DockPage 的 createUI() 会使用它们
     if (!hasSharedComponents()) {
         createSharedComponents(pParent, pBusCore);
     }
 
-    // 创建网络特有组件(如果尚未创建)
-    if (!hasNetworkComponents()) {
-        createNetworkComponents(pParent, pBusCore);
-    }
-
-    // 创建 NetworkDockPage
+    // 创建 NetworkDockPage(组件的创建由 NetworkDockPage::createUI() 负责)
     NetworkDockPage* pNetworkDockPage = new NetworkDockPage(pParent);
     
     // 注册到管理器
     registerView(EViewType::ViewNetwork, pNetworkDockPage);
+    
+    // 注意:网络特有组件的创建由 NetworkDockPage::createUI() 负责
+    // 组件会使用 NetworkDockPage 作为父对象,确保所有权清晰
 
     // 在所有组件创建完成后,初始化组件间的信号连接
     // 采用扁平化管理模式:由 ViewInstanceManager 统一管理所有组件间的连接

+ 112 - 0
src/core/CoreService.cpp

@@ -1,4 +1,10 @@
 #include "CoreService.h"
+#include "task_manager/TaskManager.h"
+#include "task_manager/TaskScheduler.h"
+#include "manage_serial/serial_manager.h"
+#include "manage_network/network_manager.h"
+#include "can_manager/can_manager.h"
+#include "protocol_plugin/ProtocolPluginManager.h"
 #include "utils/logging.h"
 
 CoreService* CoreService::instance() {
@@ -14,6 +20,12 @@ CoreService::CoreService(QObject* parent)
     , m_softBusCore(nullptr)
     , m_deviceBusCore(nullptr)
     , m_initialized(false)
+    , m_taskManager(nullptr)
+    , m_taskScheduler(nullptr)
+    , m_serialManager(nullptr)
+    , m_networkManager(nullptr)
+    , m_canManager(nullptr)
+    , m_pluginManager(nullptr)
 {
 }
 
@@ -43,6 +55,12 @@ bool CoreService::initialize() {
         return false;
     }
 
+    // 初始化任务管理系统
+    if (!initializeTaskSystem()) {
+        LOG_WARNING() << "Failed to initialize task system, continuing without it";
+        // 不返回false,允许系统在没有任务系统的情况下运行
+    }
+
     m_initialized = true;
     LOG_DEBUG() << "CoreService initialized - core will continue running after UI closes";
     return true;
@@ -53,6 +71,9 @@ void CoreService::shutdown() {
 
     LOG_DEBUG() << "CoreService shutting down...";
 
+    // 清理任务管理系统
+    cleanupTaskSystem();
+
     // 关闭设备总线核心
     if (m_deviceBusCore) {
         m_deviceBusCore->closeDB();
@@ -71,3 +92,94 @@ void CoreService::shutdown() {
     LOG_DEBUG() << "CoreService shutdown complete";
 }
 
+bool CoreService::initializeTaskSystem() {
+    if (!m_deviceBusCore) {
+        LOG_ERROR() << "DeviceBusCore not initialized, cannot initialize task system";
+        return false;
+    }
+
+    // 创建协议插件管理器
+    m_pluginManager = new ProtocolPluginManager(this);
+    // TODO: 设置插件目录
+    // m_pluginManager->setPluginDir(QStringLiteral("plugins"));
+
+    // 创建设备管理器
+    m_serialManager = new SerialManager(m_deviceBusCore, this);
+    m_serialManager->setBusCore(m_deviceBusCore);
+    m_serialManager->setPluginManager(m_pluginManager);
+
+    m_networkManager = new NetworkManager(m_deviceBusCore, this);
+    m_networkManager->setBusCore(m_deviceBusCore);
+    m_networkManager->setPluginManager(m_pluginManager);
+
+    m_canManager = new CanManager(m_deviceBusCore, this);
+    m_canManager->setBusCore(m_deviceBusCore);
+
+    // 创建任务管理器
+    m_taskManager = new TaskManager(m_deviceBusCore, this);
+
+    // 创建任务调度器
+    m_taskScheduler = new TaskScheduler(m_taskManager,
+                                       m_deviceBusCore,
+                                       m_serialManager,
+                                       m_networkManager,
+                                       m_pluginManager,
+                                       this);
+
+    // 从数据库加载任务
+    if (!m_taskManager->loadFromDatabase()) {
+        LOG_WARNING() << "Failed to load tasks from database";
+        // 不返回false,允许系统在没有任务的情况下运行
+    }
+
+    // 启动所有启用的任务
+    int startedCount = m_taskScheduler->startAllEnabledTasks();
+    LOG_INFO() << "Started" << startedCount << "enabled tasks";
+
+    LOG_DEBUG() << "Task system initialized";
+    return true;
+}
+
+void CoreService::cleanupTaskSystem() {
+    // 停止所有任务
+    if (m_taskScheduler) {
+        m_taskScheduler->stopAllTasks();
+    }
+
+    // 清理管理器(按相反顺序)
+    if (m_taskScheduler) {
+        m_taskScheduler->deleteLater();
+        m_taskScheduler = nullptr;
+    }
+
+    if (m_taskManager) {
+        m_taskManager->deleteLater();
+        m_taskManager = nullptr;
+    }
+
+    if (m_canManager) {
+        m_canManager->closeAllDevices();
+        m_canManager->deleteLater();
+        m_canManager = nullptr;
+    }
+
+    if (m_networkManager) {
+        m_networkManager->closeAllConnections();
+        m_networkManager->deleteLater();
+        m_networkManager = nullptr;
+    }
+
+    if (m_serialManager) {
+        m_serialManager->closeAllPorts();
+        m_serialManager->deleteLater();
+        m_serialManager = nullptr;
+    }
+
+    if (m_pluginManager) {
+        m_pluginManager->deleteLater();
+        m_pluginManager = nullptr;
+    }
+
+    LOG_DEBUG() << "Task system cleaned up";
+}
+

+ 38 - 0
src/core/CoreService.h

@@ -14,6 +14,14 @@
 #include "soft_bus_core/soft_bus_core.h"
 #include <QObject>
 
+// 前向声明
+class TaskManager;
+class TaskScheduler;
+class SerialManager;
+class NetworkManager;
+class CanManager;
+class ProtocolPluginManager;
+
 class CoreService : public QObject {
     Q_OBJECT
 
@@ -46,15 +54,45 @@ public:
      */
     DeviceBusCore* getDeviceBusCore() const { return m_deviceBusCore; }
 
+    /**
+     * @brief 获取任务管理器
+     */
+    TaskManager* getTaskManager() const { return m_taskManager; }
+
+    /**
+     * @brief 获取任务调度器
+     */
+    TaskScheduler* getTaskScheduler() const { return m_taskScheduler; }
+
 private:
     CoreService(QObject* parent = nullptr);
     ~CoreService();
     CoreService(const CoreService&) = delete;
     CoreService& operator=(const CoreService&) = delete;
 
+    /**
+     * @brief 初始化任务管理系统
+     */
+    bool initializeTaskSystem();
+
+    /**
+     * @brief 清理任务管理系统
+     */
+    void cleanupTaskSystem();
+
 private:
     SoftBusCore* m_softBusCore;
     DeviceBusCore* m_deviceBusCore;
     bool m_initialized;
+
+    // 任务管理系统
+    TaskManager* m_taskManager;
+    TaskScheduler* m_taskScheduler;
+
+    // 设备管理器(用于任务系统)
+    SerialManager* m_serialManager;
+    NetworkManager* m_networkManager;
+    CanManager* m_canManager;
+    ProtocolPluginManager* m_pluginManager;
 };
 

+ 89 - 0
src/daemon/daemon_client.cpp

@@ -674,3 +674,92 @@ QString DaemonClient::findDaemonExecutable() const
     return QString();
 }
 
+// ========== 任务管理接口实现 ==========
+bool DaemonClient::startTask(const QString& taskId)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        LOG_WARNING() << "Daemon not connected, cannot start task:" << taskId;
+        return false;
+    }
+
+    QDBusReply<bool> reply = m_interface->call("startTask", taskId);
+    if (reply.isValid()) {
+        bool result = reply.value();
+        if (result) {
+            LOG_INFO() << "Task started via daemon:" << taskId;
+        } else {
+            LOG_WARNING() << "Failed to start task via daemon:" << taskId;
+        }
+        return result;
+    } else {
+        LOG_ERROR() << "D-Bus call failed for startTask:" << m_interface->lastError().message();
+        return false;
+    }
+}
+
+bool DaemonClient::stopTask(const QString& taskId)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        LOG_WARNING() << "Daemon not connected, cannot stop task:" << taskId;
+        return false;
+    }
+
+    QDBusReply<bool> reply = m_interface->call("stopTask", taskId);
+    if (reply.isValid()) {
+        bool result = reply.value();
+        if (result) {
+            LOG_INFO() << "Task stopped via daemon:" << taskId;
+        } else {
+            LOG_WARNING() << "Failed to stop task via daemon:" << taskId;
+        }
+        return result;
+    } else {
+        LOG_ERROR() << "D-Bus call failed for stopTask:" << m_interface->lastError().message();
+        return false;
+    }
+}
+
+bool DaemonClient::pauseTask(const QString& taskId)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        LOG_WARNING() << "Daemon not connected, cannot pause task:" << taskId;
+        return false;
+    }
+
+    QDBusReply<bool> reply = m_interface->call("pauseTask", taskId);
+    if (reply.isValid()) {
+        bool result = reply.value();
+        if (result) {
+            LOG_INFO() << "Task paused via daemon:" << taskId;
+        } else {
+            LOG_WARNING() << "Failed to pause task via daemon:" << taskId;
+        }
+        return result;
+    } else {
+        LOG_ERROR() << "D-Bus call failed for pauseTask:" << m_interface->lastError().message();
+        return false;
+    }
+}
+
+bool DaemonClient::resumeTask(const QString& taskId)
+{
+    if (!m_interface || !m_interface->isValid()) {
+        LOG_WARNING() << "Daemon not connected, cannot resume task:" << taskId;
+        return false;
+    }
+
+    QDBusReply<bool> reply = m_interface->call("resumeTask", taskId);
+    if (reply.isValid()) {
+        bool result = reply.value();
+        if (result) {
+            LOG_INFO() << "Task resumed via daemon:" << taskId;
+        } else {
+            LOG_WARNING() << "Failed to resume task via daemon:" << taskId;
+        }
+        return result;
+    } else {
+        LOG_ERROR() << "D-Bus call failed for resumeTask:" << m_interface->lastError().message();
+        return false;
+    }
+}
+

+ 29 - 0
src/daemon/daemon_client.h

@@ -154,6 +154,35 @@ public:
     bool sendCanData(const QString& deviceName, int canPort, unsigned int canId,
                      const QByteArray& data, bool isExtendedId = true);
 
+    // ========== 任务管理接口 ==========
+    /**
+     * @brief 启动任务(通过守护进程)
+     * @param taskId 任务ID
+     * @return 成功返回 true
+     */
+    bool startTask(const QString& taskId);
+    
+    /**
+     * @brief 停止任务(通过守护进程)
+     * @param taskId 任务ID
+     * @return 成功返回 true
+     */
+    bool stopTask(const QString& taskId);
+    
+    /**
+     * @brief 暂停任务(通过守护进程)
+     * @param taskId 任务ID
+     * @return 成功返回 true
+     */
+    bool pauseTask(const QString& taskId);
+    
+    /**
+     * @brief 恢复任务(通过守护进程)
+     * @param taskId 任务ID
+     * @return 成功返回 true
+     */
+    bool resumeTask(const QString& taskId);
+
 signals:
     /**
      * @brief 守护进程状态变化时发出(包含客户端ID)

+ 158 - 28
src/manage_network/network_manager.cpp

@@ -81,21 +81,10 @@ bool NetworkManager::openNetworkConnection(const QString &interfaceName, const C
         
         // 连接信号
         connect(socket, &QTcpSocket::readyRead, this, &NetworkManager::onTcpReadyRead);
-        connect(socket, &QAbstractSocket::errorOccurred,
-                this, [this, interfaceName, socket](QAbstractSocket::SocketError error) {
-                    Q_UNUSED(error);
-                    LOG_WARNING() << "TCP socket error for" << interfaceName << ":" << socket->errorString();
-                });
-        connect(socket, &QTcpSocket::connected, this, [this, interfaceName]() {
-            LOG_DEBUG() << "TCP connected for" << interfaceName;
-        });
-        connect(socket, &QTcpSocket::disconnected, this, [this, interfaceName]() {
-            LOG_DEBUG() << "TCP disconnected for" << interfaceName;
-            if (m_openedInterfaces.contains(interfaceName))
-            {
-                closeNetworkConnection(interfaceName);
-            }
-        });
+        connect(socket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::errorOccurred),
+                this, &NetworkManager::onTcpSocketError);
+        connect(socket, &QTcpSocket::connected, this, &NetworkManager::onTcpConnected);
+        connect(socket, &QTcpSocket::disconnected, this, &NetworkManager::onTcpDisconnected);
 
         // 尝试连接
         socket->connectToHost(config.remoteAddress, config.remotePort);
@@ -695,6 +684,103 @@ void NetworkManager::onNetworkDeviceRemoved(const devices::network::NetworkDevic
     emit interfaceRemoved(info.interfaceName);
 }
 
+void NetworkManager::onTcpSocketError(QAbstractSocket::SocketError error)
+{
+    Q_UNUSED(error);
+    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+    if (!socket)
+    {
+        return;
+    }
+    
+    // 找到对应的接口名
+    QString interfaceName;
+    for (auto it = m_tcpSockets.begin(); it != m_tcpSockets.end(); ++it)
+    {
+        if (it.value() == socket)
+        {
+            interfaceName = it.key();
+            break;
+        }
+    }
+    
+    if (!interfaceName.isEmpty())
+    {
+        LOG_WARNING() << "TCP socket error for" << interfaceName << ":" << socket->errorString();
+    }
+}
+
+void NetworkManager::onTcpConnected()
+{
+    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+    if (!socket)
+    {
+        return;
+    }
+    
+    // 找到对应的接口名
+    QString interfaceName;
+    for (auto it = m_tcpSockets.begin(); it != m_tcpSockets.end(); ++it)
+    {
+        if (it.value() == socket)
+        {
+            interfaceName = it.key();
+            break;
+        }
+    }
+    
+    if (!interfaceName.isEmpty())
+    {
+        LOG_DEBUG() << "TCP connected for" << interfaceName;
+    }
+}
+
+void NetworkManager::onTcpDisconnected()
+{
+    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+    if (!socket)
+    {
+        return;
+    }
+    
+    // 找到对应的接口名
+    QString interfaceName;
+    for (auto it = m_tcpSockets.begin(); it != m_tcpSockets.end(); ++it)
+    {
+        if (it.value() == socket)
+        {
+            interfaceName = it.key();
+            break;
+        }
+    }
+    
+    if (!interfaceName.isEmpty())
+    {
+        LOG_DEBUG() << "TCP disconnected for" << interfaceName;
+        if (m_openedInterfaces.contains(interfaceName))
+        {
+            closeNetworkConnection(interfaceName);
+        }
+    }
+}
+
+void NetworkManager::onRawDataStored(qint64 rawDataId, int deviceId, const QString &interfaceName, const QByteArray &data)
+{
+    Q_UNUSED(deviceId);
+    Q_UNUSED(data);
+    QMutexLocker locker(&m_rawDataIdsMutex);
+    if (!m_rawDataIds.contains(interfaceName))
+    {
+        m_rawDataIds[interfaceName] = QQueue<qint64>();
+    }
+    m_rawDataIds[interfaceName].enqueue(rawDataId);
+    // 限制队列大小,避免内存泄漏(保留最近1000条记录)
+    while (m_rawDataIds[interfaceName].size() > 1000)
+    {
+        m_rawDataIds[interfaceName].dequeue();
+    }
+}
+
 void NetworkManager::initThreads()
 {
     // 创建存储线程
@@ -703,19 +789,7 @@ void NetworkManager::initThreads()
         m_storageThread = new NetworkStorageThread(m_busCore, this);
         // 连接原始数据存储完成信号,记录原始数据 id
         connect(m_storageThread, &NetworkStorageThread::rawDataStored,
-                this, [this](qint64 rawDataId, int deviceId, const QString &interfaceName, const QByteArray &data) {
-                    QMutexLocker locker(&m_rawDataIdsMutex);
-                    if (!m_rawDataIds.contains(interfaceName))
-                    {
-                        m_rawDataIds[interfaceName] = QQueue<qint64>();
-                    }
-                    m_rawDataIds[interfaceName].enqueue(rawDataId);
-                    // 限制队列大小,避免内存泄漏(保留最近1000条记录)
-                    while (m_rawDataIds[interfaceName].size() > 1000)
-                    {
-                        m_rawDataIds[interfaceName].dequeue();
-                    }
-                });
+                this, &NetworkManager::onRawDataStored);
         m_storageThread->start();
         LOG_DEBUG() << "NetworkStorageThread created and started";
     }
@@ -785,6 +859,62 @@ void NetworkManager::setPluginManager(ProtocolPluginManager *pluginManager)
     }
 }
 
+bool NetworkManager::lockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    // 检查设备是否已被锁定
+    if (m_deviceLocks.contains(deviceId)) {
+        QString lockingTaskId = m_deviceLocks.value(deviceId);
+        if (lockingTaskId != taskId) {
+            LOG_WARNING() << "Network device" << deviceId << "is already locked by task" << lockingTaskId;
+            return false;
+        }
+        // 如果是同一个任务,直接返回成功
+        return true;
+    }
+
+    // 锁定设备
+    m_deviceLocks.insert(deviceId, taskId);
+    LOG_DEBUG() << "Network device locked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool NetworkManager::unlockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    if (!m_deviceLocks.contains(deviceId)) {
+        LOG_WARNING() << "Network device" << deviceId << "is not locked";
+        return false;
+    }
+
+    QString lockingTaskId = m_deviceLocks.value(deviceId);
+    if (lockingTaskId != taskId) {
+        LOG_WARNING() << "Network device" << deviceId << "is locked by different task:" 
+                     << lockingTaskId << "not" << taskId;
+        return false;
+    }
+
+    m_deviceLocks.remove(deviceId);
+    LOG_DEBUG() << "Network device unlocked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool NetworkManager::isDeviceLocked(const QString &deviceId) const
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+    return m_deviceLocks.contains(deviceId);
+}
+
 void NetworkManager::registerDiscoveredInterface(const devices::network::NetworkDeviceInfo &info)
 {
     if (!m_busCore)

+ 36 - 0
src/manage_network/network_manager.h

@@ -114,6 +114,30 @@ public:
     // 设置协议插件管理器
     void setPluginManager(class ProtocolPluginManager *pluginManager);
 
+    // 设备资源锁定机制
+    /**
+     * @brief 锁定设备
+     * @param deviceId 设备ID(网络接口名称)
+     * @param taskId 任务ID
+     * @return 成功返回true,如果设备已被其他任务锁定返回false
+     */
+    bool lockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 解锁设备
+     * @param deviceId 设备ID(网络接口名称)
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool unlockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 检查设备是否被锁定
+     * @param deviceId 设备ID(网络接口名称)
+     * @return 被锁定返回true
+     */
+    bool isDeviceLocked(const QString &deviceId) const;
+
 signals:
     // 发现新网络接口时发出的信号
     void interfaceDiscovered(const QString &interfaceName, const QString &description);
@@ -138,6 +162,14 @@ private slots:
     void onNetworkDeviceArrived(const devices::network::NetworkDeviceInfo &info);
     // 网络设备移除
     void onNetworkDeviceRemoved(const devices::network::NetworkDeviceInfo &info);
+    // TCP 连接错误处理
+    void onTcpSocketError(QAbstractSocket::SocketError error);
+    // TCP 连接成功处理
+    void onTcpConnected();
+    // TCP 断开连接处理
+    void onTcpDisconnected();
+    // 处理原始数据存储完成信号
+    void onRawDataStored(qint64 rawDataId, int deviceId, const QString &interfaceName, const QByteArray &data);
 
 private:
     // 初始化线程
@@ -182,6 +214,10 @@ private:
     // 原始数据 id 映射(按接口,用于关联解析结果和原始数据)
     QMap<QString, QQueue<qint64>> m_rawDataIds;
     QMutex m_rawDataIdsMutex; // 保护原始数据 id 映射的互斥锁
+
+    // 设备锁定映射表:device_id -> task_id
+    QMap<QString, QString> m_deviceLocks;
+    mutable QMutex m_deviceLocksMutex; // 保护设备锁定映射的互斥锁
 };
 
 #endif // NETWORK_MANAGER_H

+ 77 - 15
src/manage_serial/serial_manager.cpp

@@ -90,8 +90,9 @@ bool SerialManager::openSerialPort(const QSerialPortInfo &portInfo)
         }
 
         // 连接数据接收信号
-        connect(serialPort, &QSerialPort::readyRead, this, [this, portInfo]()
-                { onReadyRead(portInfo.portName()); });
+        QString portName = portInfo.portName();
+        connect(serialPort, &QSerialPort::readyRead, this, [this, portName]()
+                { onReadyRead(portName); });
 
         LOG_DEBUG() << "Opened serial port:" << portInfo.portName();
         return true;
@@ -385,19 +386,7 @@ void SerialManager::initThreads()
         m_storageThread = new SerialStorageThread(m_busCore, this);
         // 连接原始数据存储完成信号,记录原始数据 id
         connect(m_storageThread, &SerialStorageThread::rawDataStored,
-                this, [this](qint64 rawDataId, int deviceId, const QString &portName, const QByteArray &data) {
-                    QMutexLocker locker(&m_rawDataIdsMutex);
-                    if (!m_rawDataIds.contains(portName))
-                    {
-                        m_rawDataIds[portName] = QQueue<qint64>();
-                    }
-                    m_rawDataIds[portName].enqueue(rawDataId);
-                    // 限制队列大小,避免内存泄漏(保留最近1000条记录)
-                    while (m_rawDataIds[portName].size() > 1000)
-                    {
-                        m_rawDataIds[portName].dequeue();
-                    }
-                });
+                this, &SerialManager::onRawDataStored);
         m_storageThread->start();
         LOG_DEBUG() << "SerialStorageThread created and started";
     }
@@ -448,6 +437,79 @@ void SerialManager::setPluginManager(ProtocolPluginManager *pluginManager)
     }
 }
 
+bool SerialManager::lockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    // 检查设备是否已被锁定
+    if (m_deviceLocks.contains(deviceId)) {
+        QString lockingTaskId = m_deviceLocks.value(deviceId);
+        if (lockingTaskId != taskId) {
+            LOG_WARNING() << "Serial device" << deviceId << "is already locked by task" << lockingTaskId;
+            return false;
+        }
+        // 如果是同一个任务,直接返回成功
+        return true;
+    }
+
+    // 锁定设备
+    m_deviceLocks.insert(deviceId, taskId);
+    LOG_DEBUG() << "Serial device locked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool SerialManager::unlockDevice(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    if (!m_deviceLocks.contains(deviceId)) {
+        LOG_WARNING() << "Serial device" << deviceId << "is not locked";
+        return false;
+    }
+
+    QString lockingTaskId = m_deviceLocks.value(deviceId);
+    if (lockingTaskId != taskId) {
+        LOG_WARNING() << "Serial device" << deviceId << "is locked by different task:" 
+                     << lockingTaskId << "not" << taskId;
+        return false;
+    }
+
+    m_deviceLocks.remove(deviceId);
+    LOG_DEBUG() << "Serial device unlocked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool SerialManager::isDeviceLocked(const QString &deviceId) const
+{
+    QMutexLocker locker(&m_deviceLocksMutex);
+    return m_deviceLocks.contains(deviceId);
+}
+
+void SerialManager::onRawDataStored(qint64 rawDataId, int deviceId, const QString &portName, const QByteArray &data)
+{
+    Q_UNUSED(deviceId);
+    Q_UNUSED(data);
+    QMutexLocker locker(&m_rawDataIdsMutex);
+    if (!m_rawDataIds.contains(portName))
+    {
+        m_rawDataIds[portName] = QQueue<qint64>();
+    }
+    m_rawDataIds[portName].enqueue(rawDataId);
+    // 限制队列大小,避免内存泄漏(保留最近1000条记录)
+    while (m_rawDataIds[portName].size() > 1000)
+    {
+        m_rawDataIds[portName].dequeue();
+    }
+}
+
 void SerialManager::registerDiscoveredPort(const QSerialPortInfo &info)
 {
     if (!m_busCore)

+ 30 - 0
src/manage_serial/serial_manager.h

@@ -97,6 +97,30 @@ public:
     // 设置协议插件管理器
     void setPluginManager(class ProtocolPluginManager *pluginManager);
 
+    // 设备资源锁定机制
+    /**
+     * @brief 锁定设备
+     * @param deviceId 设备ID(串口名称)
+     * @param taskId 任务ID
+     * @return 成功返回true,如果设备已被其他任务锁定返回false
+     */
+    bool lockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 解锁设备
+     * @param deviceId 设备ID(串口名称)
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool unlockDevice(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 检查设备是否被锁定
+     * @param deviceId 设备ID(串口名称)
+     * @return 被锁定返回true
+     */
+    bool isDeviceLocked(const QString &deviceId) const;
+
 signals:
     // 发现新串口时发出的信号,包含串口名称和描述
     void portDiscovered(const QString &portName, const QString &description);
@@ -116,6 +140,8 @@ private slots:
     void discoverSerialPorts();
     // 当串口接收到数据时调用
     void onReadyRead(const QString &portName);
+    // 处理原始数据存储完成信号
+    void onRawDataStored(qint64 rawDataId, int deviceId, const QString &portName, const QByteArray &data);
 
 private:
     // 初始化线程
@@ -155,6 +181,10 @@ private:
     // 每个端口维护一个队列,记录最近接收的原始数据 id
     QMap<QString, QQueue<qint64>> m_rawDataIds;
     QMutex m_rawDataIdsMutex; // 保护原始数据 id 映射的互斥锁
+
+    // 设备锁定映射表:device_id -> task_id
+    QMap<QString, QString> m_deviceLocks;
+    mutable QMutex m_deviceLocksMutex; // 保护设备锁定映射的互斥锁
 };
 
 #endif // SERIAL_MANAGER_H

+ 37 - 0
src/my_dock_manager/mdockmanager.cpp

@@ -1,6 +1,9 @@
 #include "mdockmanager.h"
+#include "utils/logging.h"
+#include "DockWidget.h"
 #include <QDebug>
 #include <QStatusBar>
+#include <QLayout>
 #include <QVBoxLayout>
 #include <QWidget>
 
@@ -55,6 +58,40 @@ void MDockManager::addDockWidget(QWidget *widget, const QString &title, ads::Doc
 {
     if (!widget || !m_DockManager) return;
 
+    // 检查组件是否已经在另一个 DockWidget 中
+    // 如果是,先将其从旧的 DockWidget 中移除,避免所有权混乱
+    QWidget* parent = widget->parentWidget();
+    if (parent) {
+        // 向上查找 CDockWidget
+        QWidget* current = parent;
+        ads::CDockWidget* oldDockWidget = nullptr;
+        while (current) {
+            oldDockWidget = qobject_cast<ads::CDockWidget*>(current);
+            if (oldDockWidget) {
+                break;
+            }
+            current = current->parentWidget();
+        }
+        
+        // 如果找到了旧的 DockWidget,先移除组件
+        if (oldDockWidget) {
+            LOG_WARNING() << "MDockManager: Widget" << title 
+                         << "已存在于另一个 DockWidget 中,正在移除...";
+            QWidget* takenWidget = oldDockWidget->takeWidget();
+            if (takenWidget != widget) {
+                LOG_ERROR() << "MDockManager: takeWidget() 返回的组件与预期不符,可能存在多个 DockWidget 包含此组件";
+            }
+        } else {
+            // 如果父对象不是 DockWidget,但组件有父对象
+            // 检查父对象是否是当前 DockManager 的父对象(即 MainWindow)
+            // 如果是,移除父对象关系,让 DockWidget 接管所有权
+            if (parent != this && parent != m_DockManager) {
+                // 父对象不是当前 DockManager,移除父对象关系
+                widget->setParent(nullptr);
+            }
+        }
+    }
+
     // 创建停靠窗口
     ads::CDockWidget* dockWidget = new ads::CDockWidget(m_DockManager, title);
     dockWidget->setWidget(widget);

+ 84 - 6
src/soft_bus_core/soft_bus_core.cpp

@@ -53,7 +53,7 @@ bool DeviceBusCore::initDB(const QString &dbName) {
     m_databaseName = effectiveDbName;
 
     // 完成所有业务所需的基础结构初始化
-    if (!ensureRawTable() || !ensureBusTable()) {
+    if (!ensureRawTable() || !ensureBusTable() || !ensureTasksTable()) {
         closeDBInternal();
         return false;
     }
@@ -190,11 +190,25 @@ void DeviceBusCore::registerDevice(const DeviceInfo &device) {
     }
 
     if (existingDeviceId > 0) {
-        DeviceInfo mergedDevice = normalizedDevice;
-        mergedDevice.id = existingDeviceId;
-        locker.unlock(); // 释放锁,避免在updateDevice中死锁
-        updateDevice(mergedDevice);
-        return;
+        // 检查设备类型是否匹配
+        // 如果类型不同,说明是不同类型的设备使用了相同的portname(虽然不常见,但需要处理)
+        // 在这种情况下,应该创建新设备而不是更新现有设备
+        if (persistedDevice.type != normalizedDevice.type) {
+            LOG_WARNING() << "Device with portname" << normalizedDevice.portname 
+                         << "already exists with different type:" 
+                         << persistedDevice.type << "vs" << normalizedDevice.type
+                         << ". Creating new device.";
+            // 移除portname映射,允许创建新设备
+            m_portnameToId.remove(normalizedDevice.portname);
+            // 继续创建新设备
+        } else {
+            // 类型匹配,更新现有设备
+            DeviceInfo mergedDevice = normalizedDevice;
+            mergedDevice.id = existingDeviceId;
+            locker.unlock(); // 释放锁,避免在updateDevice中死锁
+            updateDevice(mergedDevice);
+            return;
+        }
     }
 
     m_devices.insert(normalizedDevice.id, normalizedDevice);
@@ -1522,6 +1536,70 @@ bool DeviceBusCore::ensureBusTable() {
     return true;
 }
 
+bool DeviceBusCore::ensureTasksTable() {
+    if (!m_db.isValid() || !m_db.isOpen()) {
+        return false;
+    }
+
+    QSqlQuery query(m_db);
+    const QString createTableSql =
+        QStringLiteral("CREATE TABLE IF NOT EXISTS tb_transmission_tasks ("
+                       "task_id TEXT PRIMARY KEY,"
+                       "task_name TEXT NOT NULL,"
+                       "is_enabled BOOLEAN NOT NULL DEFAULT FALSE,"
+                       "transport_type INTEGER NOT NULL,"
+                       "protocol_type INTEGER NOT NULL,"
+                       "device_bind TEXT,"
+                       "trigger_mode INTEGER NOT NULL,"
+                       "params_json JSONB,"
+                       "status INTEGER NOT NULL DEFAULT 0,"
+                       "created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),"
+                       "updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),"
+                       "last_comm_time TIMESTAMPTZ"
+                       ")");
+
+    if (!query.exec(createTableSql)) {
+        LOG_CRITICAL() << "Failed to create tb_transmission_tasks table:"
+                    << query.lastError().text();
+        return false;
+    }
+
+    // 创建索引以提高查询性能
+    if (!query.exec(QStringLiteral(
+            "CREATE INDEX IF NOT EXISTS idx_tasks_is_enabled "
+            "ON tb_transmission_tasks (is_enabled)"))) {
+        LOG_CRITICAL() << "Failed to create tasks is_enabled index:"
+                    << query.lastError().text();
+        return false;
+    }
+
+    if (!query.exec(QStringLiteral(
+            "CREATE INDEX IF NOT EXISTS idx_tasks_status "
+            "ON tb_transmission_tasks (status)"))) {
+        LOG_CRITICAL() << "Failed to create tasks status index:"
+                    << query.lastError().text();
+        return false;
+    }
+
+    if (!query.exec(QStringLiteral(
+            "CREATE INDEX IF NOT EXISTS idx_tasks_device_bind "
+            "ON tb_transmission_tasks (device_bind)"))) {
+        LOG_CRITICAL() << "Failed to create tasks device_bind index:"
+                    << query.lastError().text();
+        return false;
+    }
+
+    if (!query.exec(QStringLiteral(
+            "CREATE INDEX IF NOT EXISTS idx_tasks_created_at "
+            "ON tb_transmission_tasks (created_at)"))) {
+        LOG_CRITICAL() << "Failed to create tasks created_at index:"
+                    << query.lastError().text();
+        return false;
+    }
+
+    return true;
+}
+
 // 初始化数据库连接
 /* 
     参数:

+ 8 - 3
src/soft_bus_core/soft_bus_core.h

@@ -133,6 +133,13 @@ public:
   // 数据库操作
   void closeDB();
 
+  /**
+   * @brief 获取当前线程的数据库连接(用于任务管理等需要直接访问数据库的场景)
+   * @return 数据库连接指针,如果数据库未初始化返回 nullptr
+   * @note 调用者不应关闭或删除此连接,它由 DeviceBusCore 管理
+   */
+  QSqlDatabase* getThreadLocalConnection() const;
+
     /**
    * @brief 根据设备类型生成下一个可用的设备ID
    * 
@@ -169,12 +176,10 @@ private:
   QSet<int> m_createdRawTables;      // 已创建的原始数据表
   QSet<int> m_createdTransformedTables; // 已创建的转化数据表
   mutable QMutex m_tableCacheMutex;  // 保护缓存集合的互斥锁
-  
-  // 获取当前线程的数据库连接(如果不存在则创建)
-  QSqlDatabase* getThreadLocalConnection() const;
 
   bool ensureRawTable();
   bool ensureBusTable();
+  bool ensureTasksTable();
   bool initializeDatabase(QSqlDatabase &db, const QString &connectionName,
                           const QString &databaseName) const;
   bool reconnectDatabase();

+ 592 - 0
src/task_manager/EventTaskExecutor.cpp

@@ -0,0 +1,592 @@
+#include "EventTaskExecutor.h"
+#include "manage_serial/serial_manager.h"
+#include "manage_network/network_manager.h"
+#include "soft_bus_core/soft_bus_core.h"
+#include "protocol_plugin/ProtocolPluginManager.h"
+#include "protocol_plugin/IProtocolParser.h"
+#include "utils/logging.h"
+#include <QJsonObject>
+#include <QJsonDocument>
+#include <QHostAddress>
+#include <QSerialPortInfo>
+#include <QDateTime>
+
+EventTaskExecutor::EventTaskExecutor(const TransferTask &task,
+                                     SerialManager *serialManager,
+                                     NetworkManager *networkManager,
+                                     DeviceBusCore *busCore,
+                                     ProtocolPluginManager *pluginManager,
+                                     QObject *parent)
+    : TaskExecutor(task, parent)
+    , m_serialManager(serialManager)
+    , m_networkManager(networkManager)
+    , m_busCore(busCore)
+    , m_pluginManager(pluginManager)
+    , m_tcpServer(nullptr)
+    , m_udpSocket(nullptr)
+    , m_serialConnected(false)
+{
+}
+
+EventTaskExecutor::~EventTaskExecutor()
+{
+    stop();
+}
+
+bool EventTaskExecutor::start()
+{
+    if (m_isRunning) {
+        LOG_WARNING() << "EventTaskExecutor already running:" << m_task.task_id;
+        return false;
+    }
+
+    // 检查必要的管理器
+    if (!m_busCore) {
+        LOG_ERROR() << "DeviceBusCore not available for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("DeviceBusCore not available"));
+        return false;
+    }
+
+    bool success = false;
+
+    switch (m_task.transport_type) {
+    case TransportType::TCP_Server:
+        if (!m_networkManager) {
+            LOG_ERROR() << "NetworkManager not available for TCP Server task:" << m_task.task_id;
+            emit error(m_task.task_id, QStringLiteral("NetworkManager not available"));
+            return false;
+        }
+        success = startTcpServer();
+        break;
+
+    case TransportType::UDP_Server:
+        if (!m_networkManager) {
+            LOG_ERROR() << "NetworkManager not available for UDP Server task:" << m_task.task_id;
+            emit error(m_task.task_id, QStringLiteral("NetworkManager not available"));
+            return false;
+        }
+        success = startUdpServer();
+        break;
+
+    case TransportType::Serial:
+        if (!m_serialManager) {
+            LOG_ERROR() << "SerialManager not available for Serial Slave task:" << m_task.task_id;
+            emit error(m_task.task_id, QStringLiteral("SerialManager not available"));
+            return false;
+        }
+        success = startSerialSlave();
+        break;
+
+    default:
+        LOG_ERROR() << "Unsupported transport type for EventTaskExecutor:" 
+                    << static_cast<int>(m_task.transport_type);
+        emit error(m_task.task_id, QStringLiteral("Unsupported transport type for event task"));
+        return false;
+    }
+
+    if (success) {
+        m_isRunning = true;
+        m_isPaused = false;
+        LOG_DEBUG() << "EventTaskExecutor started:" << m_task.task_id 
+                    << "transport:" << static_cast<int>(m_task.transport_type);
+    }
+
+    return success;
+}
+
+void EventTaskExecutor::stop()
+{
+    if (!m_isRunning) {
+        return;
+    }
+
+    switch (m_task.transport_type) {
+    case TransportType::TCP_Server:
+        stopTcpServer();
+        break;
+    case TransportType::UDP_Server:
+        stopUdpServer();
+        break;
+    case TransportType::Serial:
+        stopSerialSlave();
+        break;
+    default:
+        break;
+    }
+
+    m_isRunning = false;
+    m_isPaused = false;
+
+    LOG_DEBUG() << "EventTaskExecutor stopped:" << m_task.task_id;
+}
+
+bool EventTaskExecutor::pause()
+{
+    if (!m_isRunning || m_isPaused) {
+        return false;
+    }
+
+    // 对于监听任务,暂停意味着停止接收新连接,但保持现有连接
+    // 这里我们简单地标记为暂停,实际可以根据需求实现更复杂的逻辑
+    m_isPaused = true;
+    LOG_DEBUG() << "EventTaskExecutor paused:" << m_task.task_id;
+    return true;
+}
+
+bool EventTaskExecutor::resume()
+{
+    if (!m_isRunning || !m_isPaused) {
+        return false;
+    }
+
+    m_isPaused = false;
+    LOG_DEBUG() << "EventTaskExecutor resumed:" << m_task.task_id;
+    return true;
+}
+
+bool EventTaskExecutor::startTcpServer()
+{
+    if (m_tcpServer) {
+        LOG_WARNING() << "TCP Server already started for task:" << m_task.task_id;
+        return false;
+    }
+
+    quint16 port = getListenPort();
+    if (port == 0) {
+        LOG_ERROR() << "Invalid listen port for TCP Server task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("Invalid listen port"));
+        return false;
+    }
+
+    m_tcpServer = new QTcpServer(this);
+    connect(m_tcpServer, &QTcpServer::newConnection, 
+            this, &EventTaskExecutor::onTcpNewConnection);
+
+    QHostAddress address = getListenAddress();
+    if (!m_tcpServer->listen(address, port)) {
+        QString errorMsg = QStringLiteral("Failed to listen on %1:%2: %3")
+                          .arg(address.toString())
+                          .arg(port)
+                          .arg(m_tcpServer->errorString());
+        LOG_ERROR() << errorMsg;
+        emit error(m_task.task_id, errorMsg);
+        delete m_tcpServer;
+        m_tcpServer = nullptr;
+        return false;
+    }
+
+    LOG_INFO() << "TCP Server started for task:" << m_task.task_id 
+               << "listening on" << address.toString() << ":" << port;
+    return true;
+}
+
+bool EventTaskExecutor::startUdpServer()
+{
+    if (m_udpSocket) {
+        LOG_WARNING() << "UDP Server already started for task:" << m_task.task_id;
+        return false;
+    }
+
+    quint16 port = getListenPort();
+    if (port == 0) {
+        LOG_ERROR() << "Invalid listen port for UDP Server task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("Invalid listen port"));
+        return false;
+    }
+
+    m_udpSocket = new QUdpSocket(this);
+    connect(m_udpSocket, &QUdpSocket::readyRead, 
+            this, &EventTaskExecutor::onUdpReadyRead);
+
+    QHostAddress address = getListenAddress();
+    if (!m_udpSocket->bind(address, port)) {
+        QString errorMsg = QStringLiteral("Failed to bind UDP on %1:%2: %3")
+                          .arg(address.toString())
+                          .arg(port)
+                          .arg(m_udpSocket->errorString());
+        LOG_ERROR() << errorMsg;
+        emit error(m_task.task_id, errorMsg);
+        delete m_udpSocket;
+        m_udpSocket = nullptr;
+        return false;
+    }
+
+    LOG_INFO() << "UDP Server started for task:" << m_task.task_id 
+               << "listening on" << address.toString() << ":" << port;
+    return true;
+}
+
+bool EventTaskExecutor::startSerialSlave()
+{
+    if (m_serialConnected) {
+        LOG_WARNING() << "Serial Slave already started for task:" << m_task.task_id;
+        return false;
+    }
+
+    if (m_task.device_bind.isEmpty()) {
+        LOG_ERROR() << "Device bind is empty for Serial Slave task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("Device bind is empty"));
+        return false;
+    }
+
+    // 查找串口
+    QList<QSerialPortInfo> ports = QSerialPortInfo::availablePorts();
+    QSerialPortInfo targetPort;
+    bool found = false;
+
+    for (const QSerialPortInfo &port : ports) {
+        if (port.portName() == m_task.device_bind || 
+            port.systemLocation() == m_task.device_bind) {
+            targetPort = port;
+            found = true;
+            break;
+        }
+    }
+
+    if (!found) {
+        LOG_ERROR() << "Serial port not found:" << m_task.device_bind 
+                    << "for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("Serial port not found: ") + m_task.device_bind);
+        return false;
+    }
+
+    // 打开串口(通过 SerialManager)
+    if (!m_serialManager->openSerialPort(targetPort)) {
+        LOG_ERROR() << "Failed to open serial port:" << m_task.device_bind 
+                    << "for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("Failed to open serial port"));
+        return false;
+    }
+
+    // 连接数据接收信号
+    connect(m_serialManager, &SerialManager::dataReceived,
+            this, &EventTaskExecutor::onSerialDataReceived, Qt::QueuedConnection);
+
+    m_serialPortName = targetPort.portName();
+    m_serialConnected = true;
+
+    LOG_INFO() << "Serial Slave started for task:" << m_task.task_id 
+               << "port:" << m_serialPortName;
+    return true;
+}
+
+void EventTaskExecutor::stopTcpServer()
+{
+    if (!m_tcpServer) {
+        return;
+    }
+
+    // 关闭所有客户端连接
+    for (auto it = m_tcpClients.begin(); it != m_tcpClients.end(); ++it) {
+        QTcpSocket *socket = it.key();
+        socket->disconnectFromHost();
+        socket->deleteLater();
+    }
+    m_tcpClients.clear();
+
+    m_tcpServer->close();
+    m_tcpServer->deleteLater();
+    m_tcpServer = nullptr;
+
+    LOG_DEBUG() << "TCP Server stopped for task:" << m_task.task_id;
+}
+
+void EventTaskExecutor::stopUdpServer()
+{
+    if (!m_udpSocket) {
+        return;
+    }
+
+    m_udpSocket->close();
+    m_udpSocket->deleteLater();
+    m_udpSocket = nullptr;
+
+    LOG_DEBUG() << "UDP Server stopped for task:" << m_task.task_id;
+}
+
+void EventTaskExecutor::stopSerialSlave()
+{
+    if (!m_serialConnected) {
+        return;
+    }
+
+    // 断开信号连接
+    if (m_serialManager) {
+        disconnect(m_serialManager, &SerialManager::dataReceived,
+                   this, &EventTaskExecutor::onSerialDataReceived);
+    }
+
+    // 关闭串口(通过 SerialManager)
+    if (!m_serialPortName.isEmpty() && m_serialManager) {
+        m_serialManager->closeSerialPort(m_serialPortName);
+    }
+
+    m_serialPortName.clear();
+    m_serialConnected = false;
+
+    LOG_DEBUG() << "Serial Slave stopped for task:" << m_task.task_id;
+}
+
+void EventTaskExecutor::onTcpNewConnection()
+{
+    if (m_isPaused) {
+        return;
+    }
+
+    QTcpSocket *clientSocket = m_tcpServer->nextPendingConnection();
+    if (!clientSocket) {
+        return;
+    }
+
+    QString clientInfo = QStringLiteral("%1:%2")
+                        .arg(clientSocket->peerAddress().toString())
+                        .arg(clientSocket->peerPort());
+
+    m_tcpClients[clientSocket] = clientInfo;
+
+    connect(clientSocket, &QTcpSocket::readyRead,
+            this, &EventTaskExecutor::onTcpClientReadyRead);
+    connect(clientSocket, &QTcpSocket::disconnected,
+            this, &EventTaskExecutor::onTcpClientDisconnected);
+
+    LOG_DEBUG() << "TCP client connected:" << clientInfo << "for task:" << m_task.task_id;
+}
+
+void EventTaskExecutor::onTcpClientDisconnected()
+{
+    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+    if (!socket) {
+        return;
+    }
+
+    QString clientInfo = m_tcpClients.value(socket);
+    m_tcpClients.remove(socket);
+    socket->deleteLater();
+
+    LOG_DEBUG() << "TCP client disconnected:" << clientInfo << "for task:" << m_task.task_id;
+}
+
+void EventTaskExecutor::onTcpClientReadyRead()
+{
+    if (m_isPaused) {
+        return;
+    }
+
+    QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+    if (!socket) {
+        return;
+    }
+
+    QByteArray data = socket->readAll();
+    if (data.isEmpty()) {
+        return;
+    }
+
+    QString clientInfo = m_tcpClients.value(socket);
+    processReceivedData(data, clientInfo);
+}
+
+void EventTaskExecutor::onUdpReadyRead()
+{
+    if (m_isPaused) {
+        return;
+    }
+
+    if (!m_udpSocket) {
+        return;
+    }
+
+    while (m_udpSocket->hasPendingDatagrams()) {
+        QByteArray datagram;
+        datagram.resize(m_udpSocket->pendingDatagramSize());
+        
+        QHostAddress senderAddress;
+        quint16 senderPort;
+        qint64 bytesRead = m_udpSocket->readDatagram(datagram.data(), datagram.size(),
+                                                      &senderAddress, &senderPort);
+        
+        if (bytesRead > 0) {
+            QString clientInfo = QStringLiteral("%1:%2")
+                                .arg(senderAddress.toString())
+                                .arg(senderPort);
+            processReceivedData(datagram, clientInfo);
+        }
+    }
+}
+
+void EventTaskExecutor::onSerialDataReceived(const QString &deviceId, const QByteArray &data)
+{
+    if (m_isPaused) {
+        return;
+    }
+
+    // 只处理绑定设备的数据
+    if (deviceId != m_task.device_bind && deviceId != m_serialPortName) {
+        return;
+    }
+
+    if (data.isEmpty()) {
+        return;
+    }
+
+    processReceivedData(data, deviceId);
+}
+
+void EventTaskExecutor::processReceivedData(const QByteArray &data, const QString &clientInfo)
+{
+    if (!m_busCore) {
+        return;
+    }
+
+    // 存储原始数据
+    // device_bind 通常是端口名,可以直接使用 storeRawData(portName, data)
+    QString portName = m_task.device_bind;
+    if (!clientInfo.isEmpty()) {
+        // 对于TCP/UDP Server,使用 clientInfo 作为端口标识的一部分
+        portName = QStringLiteral("%1_%2").arg(m_task.device_bind).arg(clientInfo);
+    }
+
+    qint64 rawDataId = m_busCore->storeRawData(portName, data);
+    if (rawDataId < 0) {
+        LOG_WARNING() << "Failed to store raw data for task:" << m_task.task_id;
+    }
+
+    // 解析响应数据
+    parseResponse(data);
+
+    // 更新最后通信时间
+    updateLastCommTime();
+
+    LOG_DEBUG() << "EventTaskExecutor received data for task:" << m_task.task_id 
+                << "size:" << data.size() << "bytes";
+}
+
+void EventTaskExecutor::parseResponse(const QByteArray &data)
+{
+    if (!m_pluginManager || !m_busCore) {
+        return;
+    }
+
+    // 原始数据模式,不解析
+    if (m_task.protocol_type == ProtocolType::Raw_Data) {
+        return;
+    }
+
+    // 根据协议类型获取协议名称
+    QString protocolName;
+    QString protocolDetail;
+    switch (m_task.protocol_type) {
+    case ProtocolType::Modbus_RTU:
+        protocolName = QStringLiteral("modbus");
+        protocolDetail = QStringLiteral("modbus-rtu");
+        break;
+    case ProtocolType::Modbus_TCP:
+        protocolName = QStringLiteral("modbus");
+        protocolDetail = QStringLiteral("modbus-tcp");
+        break;
+    case ProtocolType::CAN_Standard:
+        // CAN 协议暂不支持事件模式解析
+        return;
+    default:
+        LOG_DEBUG() << "Unsupported protocol type for parsing:" 
+                    << static_cast<int>(m_task.protocol_type);
+        return;
+    }
+
+    // 获取协议解析器
+    IProtocolParser *parser = m_pluginManager->getParser(protocolName);
+    if (!parser) {
+        LOG_DEBUG() << "No parser available for protocol:" << protocolName;
+        return;
+    }
+
+    // 提取完整帧(如果需要)
+    QByteArray frame;
+    if (!parser->extractFrame(data, frame)) {
+        // 如果提取失败,尝试直接使用原始数据
+        frame = data;
+    }
+
+    // 验证帧完整性
+    if (!parser->validateFrame(frame)) {
+        LOG_DEBUG() << "Invalid frame for protocol:" << protocolName;
+        return;
+    }
+
+    // 解析帧
+    QJsonObject parsedResult;
+    if (!parser->parseFrame(frame, parsedResult)) {
+        LOG_DEBUG() << "Failed to parse frame for protocol:" << protocolName;
+        return;
+    }
+
+    // 创建总线消息
+    BusMessage message;
+    message.id = QStringLiteral("%1_%2_%3")
+                 .arg(m_task.task_id)
+                 .arg(protocolName)
+                 .arg(QDateTime::currentMSecsSinceEpoch());
+    message.source = m_task.device_bind;
+    message.destination = QStringLiteral("data_processor");
+    message.timestamp = QDateTime::currentMSecsSinceEpoch();
+
+    // 设置payload
+    QJsonObject payload = parsedResult;
+    payload[QStringLiteral("protocol")] = protocolName;
+    if (!protocolDetail.isEmpty()) {
+        payload[QStringLiteral("protocol_detail")] = protocolDetail;
+    }
+    payload[QStringLiteral("raw_hex")] = QString::fromLatin1(frame.toHex());
+    payload[QStringLiteral("task_id")] = m_task.task_id;
+    message.payload = payload;
+
+    // 存储总线消息
+    m_busCore->storeBusMessage(message);
+
+    LOG_DEBUG() << "Data parsed and stored for task:" << m_task.task_id 
+                << "protocol:" << protocolName;
+}
+
+void EventTaskExecutor::updateLastCommTime()
+{
+    // 更新任务最后通信时间(通过 TaskManager,这里暂时不实现)
+    // 可以在 TaskScheduler 中监听数据接收事件来更新
+}
+
+quint16 EventTaskExecutor::getListenPort() const
+{
+    // 从 params_json 中获取端口号
+    QJsonValue portValue = m_task.params_json.value(QStringLiteral("listen_port"));
+    if (portValue.isDouble()) {
+        int port = portValue.toInt();
+        if (port > 0 && port <= 65535) {
+            return static_cast<quint16>(port);
+        }
+    }
+
+    // 默认端口
+    if (m_task.protocol_type == ProtocolType::Modbus_TCP) {
+        return 502; // Modbus TCP 默认端口
+    }
+
+    return 0; // 无效端口
+}
+
+QHostAddress EventTaskExecutor::getListenAddress() const
+{
+    // 从 params_json 中获取监听地址
+    QJsonValue addressValue = m_task.params_json.value(QStringLiteral("listen_address"));
+    if (addressValue.isString()) {
+        QString addressStr = addressValue.toString();
+        if (!addressStr.isEmpty()) {
+            QHostAddress address(addressStr);
+            if (!address.isNull()) {
+                return address;
+            }
+        }
+    }
+
+    // 默认监听所有地址
+    return QHostAddress::AnyIPv4;
+}
+

+ 157 - 0
src/task_manager/EventTaskExecutor.h

@@ -0,0 +1,157 @@
+/**
+ * @file EventTaskExecutor.h
+ * @brief 监听任务执行器 - 实现事件驱动的监听任务
+ * 
+ * 职责:
+ * - TCP Server: 启动 QTcpServer 监听端口
+ * - UDP Server: 启动 QUdpSocket 监听端口
+ * - Serial Slave: 打开串口,连接 readyRead 信号
+ * - 收到数据时根据协议解析,不符合协议则丢弃
+ * - 存储原始数据和解析后的消息
+ */
+
+#ifndef EVENT_TASK_EXECUTOR_H
+#define EVENT_TASK_EXECUTOR_H
+
+#include "TaskExecutor.h"
+#include <QTcpServer>
+#include <QTcpSocket>
+#include <QUdpSocket>
+#include <QByteArray>
+#include <QMap>
+
+// 前向声明
+class SerialManager;
+class NetworkManager;
+class DeviceBusCore;
+class ProtocolPluginManager;
+
+class EventTaskExecutor : public TaskExecutor {
+    Q_OBJECT
+
+public:
+    explicit EventTaskExecutor(const TransferTask &task,
+                               SerialManager *serialManager,
+                               NetworkManager *networkManager,
+                               DeviceBusCore *busCore,
+                               ProtocolPluginManager *pluginManager,
+                               QObject *parent = nullptr);
+    ~EventTaskExecutor() override;
+
+    bool start() override;
+    void stop() override;
+    bool pause() override;
+    bool resume() override;
+
+private slots:
+    /**
+     * @brief TCP Server: 新连接到达
+     */
+    void onTcpNewConnection();
+
+    /**
+     * @brief TCP Socket: 客户端断开连接
+     */
+    void onTcpClientDisconnected();
+
+    /**
+     * @brief TCP Socket: 接收到数据
+     */
+    void onTcpClientReadyRead();
+
+    /**
+     * @brief UDP Socket: 接收到数据
+     */
+    void onUdpReadyRead();
+
+    /**
+     * @brief Serial: 接收到数据
+     * @param deviceId 设备ID或接口名
+     * @param data 接收到的数据
+     */
+    void onSerialDataReceived(const QString &deviceId, const QByteArray &data);
+
+private:
+    /**
+     * @brief 启动 TCP Server
+     * @return 成功返回true
+     */
+    bool startTcpServer();
+
+    /**
+     * @brief 启动 UDP Server
+     * @return 成功返回true
+     */
+    bool startUdpServer();
+
+    /**
+     * @brief 启动 Serial Slave
+     * @return 成功返回true
+     */
+    bool startSerialSlave();
+
+    /**
+     * @brief 停止 TCP Server
+     */
+    void stopTcpServer();
+
+    /**
+     * @brief 停止 UDP Server
+     */
+    void stopUdpServer();
+
+    /**
+     * @brief 停止 Serial Slave
+     */
+    void stopSerialSlave();
+
+    /**
+     * @brief 处理接收到的数据
+     * @param data 接收到的数据
+     * @param clientInfo 客户端信息(用于TCP,UDP和Serial可以为空)
+     */
+    void processReceivedData(const QByteArray &data, const QString &clientInfo = QString());
+
+    /**
+     * @brief 解析响应数据
+     * @param data 响应数据
+     */
+    void parseResponse(const QByteArray &data);
+
+    /**
+     * @brief 更新最后通信时间
+     */
+    void updateLastCommTime();
+
+    /**
+     * @brief 获取监听端口(TCP/UDP Server)
+     * @return 端口号,失败返回0
+     */
+    quint16 getListenPort() const;
+
+    /**
+     * @brief 获取监听地址(TCP/UDP Server,可选)
+     * @return 监听地址,默认返回 AnyIPv4
+     */
+    QHostAddress getListenAddress() const;
+
+private:
+    SerialManager *m_serialManager;
+    NetworkManager *m_networkManager;
+    DeviceBusCore *m_busCore;
+    ProtocolPluginManager *m_pluginManager;
+
+    // TCP Server
+    QTcpServer *m_tcpServer;
+    QMap<QTcpSocket*, QString> m_tcpClients; // socket -> client info
+
+    // UDP Server
+    QUdpSocket *m_udpSocket;
+
+    // Serial Slave
+    QString m_serialPortName;
+    bool m_serialConnected;
+};
+
+#endif // EVENT_TASK_EXECUTOR_H
+

+ 612 - 0
src/task_manager/PollingTaskExecutor.cpp

@@ -0,0 +1,612 @@
+#include "PollingTaskExecutor.h"
+#include "manage_serial/serial_manager.h"
+#include "manage_network/network_manager.h"
+#include "soft_bus_core/soft_bus_core.h"
+#include "protocol_plugin/ProtocolPluginManager.h"
+#include "protocol_plugin/IProtocolParser.h"
+#include "libmodbus/src/modbus.h"
+#include "utils/logging.h"
+#include <QJsonObject>
+#include <QJsonDocument>
+#include <QDateTime>
+#include <cstdint>
+
+PollingTaskExecutor::PollingTaskExecutor(const TransferTask &task,
+                                         SerialManager *serialManager,
+                                         NetworkManager *networkManager,
+                                         DeviceBusCore *busCore,
+                                         ProtocolPluginManager *pluginManager,
+                                         QObject *parent)
+    : TaskExecutor(task, parent)
+    , m_serialManager(serialManager)
+    , m_networkManager(networkManager)
+    , m_busCore(busCore)
+    , m_pluginManager(pluginManager)
+    , m_pollTimer(new QTimer(this))
+    , m_responseTimer(new QTimer(this))
+    , m_waitingForResponse(false)
+    , m_consecutiveErrors(0)
+{
+    m_pollTimer->setSingleShot(false);
+    m_responseTimer->setSingleShot(true);
+
+    connect(m_pollTimer, &QTimer::timeout, this, &PollingTaskExecutor::onPollTimer);
+    connect(m_responseTimer, &QTimer::timeout, this, &PollingTaskExecutor::onResponseTimeout);
+}
+
+PollingTaskExecutor::~PollingTaskExecutor()
+{
+    stop();
+}
+
+bool PollingTaskExecutor::start()
+{
+    if (m_isRunning) {
+        LOG_WARNING() << "PollingTaskExecutor already running:" << m_task.task_id;
+        return false;
+    }
+
+    // 检查必要的管理器
+    if (m_task.transport_type == TransportType::Serial && !m_serialManager) {
+        LOG_ERROR() << "SerialManager not available for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("SerialManager not available"));
+        return false;
+    }
+
+    if ((m_task.transport_type == TransportType::TCP_Client || 
+         m_task.transport_type == TransportType::UDP_Client) && !m_networkManager) {
+        LOG_ERROR() << "NetworkManager not available for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("NetworkManager not available"));
+        return false;
+    }
+
+    if (!m_busCore) {
+        LOG_ERROR() << "DeviceBusCore not available for task:" << m_task.task_id;
+        emit error(m_task.task_id, QStringLiteral("DeviceBusCore not available"));
+        return false;
+    }
+
+    // 连接数据接收信号
+    if (m_serialManager) {
+        connect(m_serialManager, &SerialManager::dataReceived,
+                this, &PollingTaskExecutor::onDataReceived, Qt::QueuedConnection);
+    }
+
+    if (m_networkManager) {
+        connect(m_networkManager, &NetworkManager::dataReceived,
+                this, &PollingTaskExecutor::onDataReceived, Qt::QueuedConnection);
+    }
+
+    // 启动轮询定时器
+    int interval = getPollInterval();
+    m_pollTimer->start(interval);
+    m_isRunning = true;
+    m_isPaused = false;
+    m_consecutiveErrors = 0;
+
+    LOG_DEBUG() << "PollingTaskExecutor started:" << m_task.task_id 
+                << "interval:" << interval << "ms";
+    
+    // 立即执行一次轮询
+    QTimer::singleShot(0, this, &PollingTaskExecutor::onPollTimer);
+
+    return true;
+}
+
+void PollingTaskExecutor::stop()
+{
+    if (!m_isRunning) {
+        return;
+    }
+
+    m_pollTimer->stop();
+    m_responseTimer->stop();
+    m_waitingForResponse = false;
+
+    // 断开信号连接
+    if (m_serialManager) {
+        disconnect(m_serialManager, &SerialManager::dataReceived,
+                   this, &PollingTaskExecutor::onDataReceived);
+    }
+
+    if (m_networkManager) {
+        disconnect(m_networkManager, &NetworkManager::dataReceived,
+                   this, &PollingTaskExecutor::onDataReceived);
+    }
+
+    m_isRunning = false;
+    m_isPaused = false;
+    m_consecutiveErrors = 0;
+
+    LOG_DEBUG() << "PollingTaskExecutor stopped:" << m_task.task_id;
+}
+
+bool PollingTaskExecutor::pause()
+{
+    if (!TaskExecutor::pause()) {
+        return false;
+    }
+
+    m_pollTimer->stop();
+    m_responseTimer->stop();
+    m_waitingForResponse = false;
+
+    return true;
+}
+
+bool PollingTaskExecutor::resume()
+{
+    if (!TaskExecutor::resume()) {
+        return false;
+    }
+
+    // 重新启动轮询定时器
+    int interval = getPollInterval();
+    m_pollTimer->start(interval);
+
+    return true;
+}
+
+void PollingTaskExecutor::onPollTimer()
+{
+    if (m_isPaused || !m_isRunning) {
+        return;
+    }
+
+    // 如果正在等待响应,跳过本次轮询
+    if (m_waitingForResponse) {
+        LOG_WARNING() << "Still waiting for response, skipping poll:" << m_task.task_id;
+        return;
+    }
+
+    // 构建请求
+    QByteArray request = buildRequest();
+    if (request.isEmpty()) {
+        LOG_ERROR() << "Failed to build request for task:" << m_task.task_id;
+        m_consecutiveErrors++;
+        if (m_consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
+            emit error(m_task.task_id, QStringLiteral("Failed to build request"));
+            stop();
+        }
+        return;
+    }
+
+    // 发送请求
+    if (!sendRequest(request)) {
+        LOG_ERROR() << "Failed to send request for task:" << m_task.task_id;
+        m_consecutiveErrors++;
+        if (m_consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
+            emit error(m_task.task_id, QStringLiteral("Failed to send request"));
+            stop();
+        }
+        return;
+    }
+
+    // 保存请求并启动响应超时定时器
+    m_lastRequest = request;
+    m_waitingForResponse = true;
+    int timeout = getResponseTimeout();
+    m_responseTimer->start(timeout);
+
+    LOG_DEBUG() << "Poll request sent for task:" << m_task.task_id;
+}
+
+void PollingTaskExecutor::onDataReceived(const QString &deviceId, const QByteArray &data)
+{
+    // 检查是否是当前任务绑定的设备
+    if (deviceId != m_task.device_bind) {
+        return;
+    }
+
+    // 检查是否正在等待响应
+    if (!m_waitingForResponse) {
+        return;
+    }
+
+    // 停止超时定时器
+    m_responseTimer->stop();
+    m_waitingForResponse = false;
+
+    // 重置连续错误计数
+    m_consecutiveErrors = 0;
+
+    // 存储原始数据
+    if (m_busCore) {
+        qint64 rawDataId = m_busCore->storeRawData(deviceId, data);
+        if (rawDataId < 0) {
+            LOG_WARNING() << "Failed to store raw data for task:" << m_task.task_id;
+        }
+    }
+
+    // 解析响应
+    parseResponse(data);
+
+    // 更新最后通信时间
+    updateLastCommTime();
+
+    LOG_DEBUG() << "Response received for task:" << m_task.task_id 
+                << "size:" << data.size();
+}
+
+void PollingTaskExecutor::onResponseTimeout()
+{
+    if (!m_waitingForResponse) {
+        return;
+    }
+
+    m_waitingForResponse = false;
+    m_consecutiveErrors++;
+
+    LOG_WARNING() << "Response timeout for task:" << m_task.task_id 
+                  << "consecutive errors:" << m_consecutiveErrors;
+
+    if (m_consecutiveErrors >= MAX_CONSECUTIVE_ERRORS) {
+        emit error(m_task.task_id, QStringLiteral("Response timeout"));
+        stop();
+    }
+}
+
+/**
+ * @brief 计算 Modbus RTU CRC16
+ */
+static uint16_t calculateModbusCRC16(const QByteArray &data)
+{
+    uint16_t crc = 0xFFFF;
+    const uint8_t *bytes = reinterpret_cast<const uint8_t*>(data.constData());
+    int length = data.size();
+
+    for (int i = 0; i < length; i++) {
+        crc ^= bytes[i];
+        for (int j = 0; j < 8; j++) {
+            if (crc & 0x0001) {
+                crc = (crc >> 1) ^ 0xA001;
+            } else {
+                crc >>= 1;
+            }
+        }
+    }
+
+    return crc;
+}
+
+/**
+ * @brief 构建 Modbus RTU 请求帧
+ */
+static QByteArray buildModbusRTURequest(int slaveId, int functionCode, 
+                                        int startAddr, int quantity,
+                                        const QByteArray &additionalData = QByteArray())
+{
+    QByteArray request;
+    
+    // RTU 格式: [slave][function][addr_hi][addr_lo][nb_hi][nb_lo][...data...][crc_lo][crc_hi]
+    request.append(static_cast<char>(slaveId));
+    request.append(static_cast<char>(functionCode));
+    request.append(static_cast<char>((startAddr >> 8) & 0xFF));
+    request.append(static_cast<char>(startAddr & 0xFF));
+    request.append(static_cast<char>((quantity >> 8) & 0xFF));
+    request.append(static_cast<char>(quantity & 0xFF));
+    
+    // 添加额外数据(用于写操作)
+    if (!additionalData.isEmpty()) {
+        request.append(additionalData);
+    }
+    
+    // 计算并添加 CRC
+    uint16_t crc = calculateModbusCRC16(request);
+    request.append(static_cast<char>(crc & 0xFF));      // CRC low byte first
+    request.append(static_cast<char>((crc >> 8) & 0xFF)); // CRC high byte
+    
+    return request;
+}
+
+/**
+ * @brief 构建 Modbus TCP 请求帧
+ */
+static QByteArray buildModbusTCPRequest(int slaveId, int functionCode,
+                                         int startAddr, int quantity,
+                                         const QByteArray &additionalData = QByteArray())
+{
+    QByteArray request;
+    static uint16_t transactionId = 0;
+    transactionId++;
+    
+    // TCP 格式: [tid_hi][tid_lo][proto_hi][proto_lo][len_hi][len_lo][slave][function][addr_hi][addr_lo][nb_hi][nb_lo][...data...]
+    request.append(static_cast<char>((transactionId >> 8) & 0xFF));
+    request.append(static_cast<char>(transactionId & 0xFF));
+    request.append(static_cast<char>(0x00)); // Protocol ID high
+    request.append(static_cast<char>(0x00)); // Protocol ID low
+    // Length will be filled later
+    request.append(static_cast<char>(0x00));
+    request.append(static_cast<char>(0x00));
+    request.append(static_cast<char>(slaveId)); // Unit identifier
+    request.append(static_cast<char>(functionCode));
+    request.append(static_cast<char>((startAddr >> 8) & 0xFF));
+    request.append(static_cast<char>(startAddr & 0xFF));
+    request.append(static_cast<char>((quantity >> 8) & 0xFF));
+    request.append(static_cast<char>(quantity & 0xFF));
+    
+    // 添加额外数据(用于写操作)
+    if (!additionalData.isEmpty()) {
+        request.append(additionalData);
+    }
+    
+    // 更新长度字段(PDU length + unit identifier)
+    uint16_t length = request.size() - 6 + 1; // PDU length + unit identifier
+    request[4] = static_cast<char>((length >> 8) & 0xFF);
+    request[5] = static_cast<char>(length & 0xFF);
+    
+    return request;
+}
+
+QByteArray PollingTaskExecutor::buildRequest()
+{
+    // 根据协议类型构建请求
+    switch (m_task.protocol_type) {
+    case ProtocolType::Modbus_RTU:
+    case ProtocolType::Modbus_TCP:
+    {
+        // 从 params_json 中获取 Modbus 参数
+        QJsonObject params = m_task.params_json;
+        
+        // 获取必需参数
+        int slaveId = params.value(QStringLiteral("modbus_slave_id")).toInt(1);
+        int functionCode = params.value(QStringLiteral("modbus_function_code")).toInt(MODBUS_FC_READ_HOLDING_REGISTERS);
+        int startAddr = params.value(QStringLiteral("modbus_start_addr")).toInt(0);
+        int quantity = params.value(QStringLiteral("modbus_quantity")).toInt(1);
+        
+        // 验证参数
+        if (slaveId < 1 || slaveId > 247) {
+            LOG_WARNING() << "Invalid Modbus slave ID:" << slaveId << "for task:" << m_task.task_id;
+            return QByteArray();
+        }
+        
+        if (quantity < 1) {
+            LOG_WARNING() << "Invalid Modbus quantity:" << quantity << "for task:" << m_task.task_id;
+            return QByteArray();
+        }
+        
+        // 根据功能码构建请求
+        QByteArray additionalData;
+        
+        // 处理写操作的数据
+        if (functionCode == MODBUS_FC_WRITE_SINGLE_COIL) {
+            // 写单个线圈:需要值(0x0000 或 0xFF00)
+            int value = params.value(QStringLiteral("modbus_write_value")).toInt(0);
+            uint16_t coilValue = (value != 0) ? 0xFF00 : 0x0000;
+            additionalData.append(static_cast<char>((coilValue >> 8) & 0xFF));
+            additionalData.append(static_cast<char>(coilValue & 0xFF));
+            quantity = 1; // 写单个线圈时 quantity 固定为 1
+        } else if (functionCode == MODBUS_FC_WRITE_SINGLE_REGISTER) {
+            // 写单个寄存器:需要值
+            int value = params.value(QStringLiteral("modbus_write_value")).toInt(0);
+            additionalData.append(static_cast<char>((value >> 8) & 0xFF));
+            additionalData.append(static_cast<char>(value & 0xFF));
+            quantity = 1; // 写单个寄存器时 quantity 固定为 1
+        } else if (functionCode == MODBUS_FC_WRITE_MULTIPLE_COILS) {
+            // 写多个线圈:需要字节数和数据
+            int byteCount = (quantity + 7) / 8;
+            additionalData.append(static_cast<char>(byteCount));
+            // 从参数中获取线圈值(逗号分隔的字符串)
+            QString writeValue = params.value(QStringLiteral("modbus_write_value")).toString();
+            QStringList values = writeValue.split(',', Qt::SkipEmptyParts);
+            QByteArray coilBytes(byteCount, 0);
+            for (int i = 0; i < qMin(values.size(), quantity); i++) {
+                bool bitValue = values[i].trimmed().toUInt(nullptr, 0) != 0;
+                int byteIndex = i / 8;
+                int bitIndex = i % 8;
+                if (bitValue) {
+                    coilBytes[byteIndex] |= (1 << bitIndex);
+                }
+            }
+            additionalData.append(coilBytes);
+        } else if (functionCode == MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {
+            // 写多个寄存器:需要字节数和数据
+            int byteCount = quantity * 2;
+            additionalData.append(static_cast<char>(byteCount));
+            // 从参数中获取寄存器值(逗号分隔的字符串)
+            QString writeValue = params.value(QStringLiteral("modbus_write_value")).toString();
+            QStringList values = writeValue.split(',', Qt::SkipEmptyParts);
+            for (int i = 0; i < qMin(values.size(), quantity); i++) {
+                uint16_t regVal = values[i].trimmed().toUInt(nullptr, 0);
+                additionalData.append(static_cast<char>((regVal >> 8) & 0xFF));
+                additionalData.append(static_cast<char>(regVal & 0xFF));
+            }
+        } else if (functionCode == MODBUS_FC_MASK_WRITE_REGISTER) {
+            // 掩码写寄存器:需要 AND 掩码和 OR 掩码
+            int andMask = params.value(QStringLiteral("modbus_mask_and")).toInt(0xFFFF);
+            int orMask = params.value(QStringLiteral("modbus_mask_or")).toInt(0x0000);
+            additionalData.append(static_cast<char>((andMask >> 8) & 0xFF));
+            additionalData.append(static_cast<char>(andMask & 0xFF));
+            additionalData.append(static_cast<char>((orMask >> 8) & 0xFF));
+            additionalData.append(static_cast<char>(orMask & 0xFF));
+            quantity = 1; // 掩码写寄存器时 quantity 固定为 1
+        }
+        
+        // 根据协议类型构建请求帧
+        if (m_task.protocol_type == ProtocolType::Modbus_RTU) {
+            return buildModbusRTURequest(slaveId, functionCode, startAddr, quantity, additionalData);
+        } else {
+            return buildModbusTCPRequest(slaveId, functionCode, startAddr, quantity, additionalData);
+        }
+    }
+
+    case ProtocolType::Raw_Data:
+        // 原始数据模式,从 params_json 中获取数据
+        {
+            QJsonValue dataValue = m_task.params_json.value(QStringLiteral("request_data"));
+            if (dataValue.isString()) {
+                QString hexStr = dataValue.toString();
+                // 支持十六进制字符串格式
+                if (hexStr.startsWith(QStringLiteral("0x")) || 
+                    hexStr.startsWith(QStringLiteral("0X"))) {
+                    hexStr = hexStr.mid(2);
+                }
+                // 移除空格
+                hexStr = hexStr.remove(QChar(' '));
+                return QByteArray::fromHex(hexStr.toLatin1());
+            } else if (dataValue.isArray()) {
+                // 支持数组格式 [0x01, 0x02, 0x03]
+                QJsonArray arr = dataValue.toArray();
+                QByteArray data;
+                for (const QJsonValue &val : arr) {
+                    if (val.isDouble()) {
+                        data.append(static_cast<char>(val.toInt()));
+                    }
+                }
+                return data;
+            }
+        }
+        break;
+
+    case ProtocolType::CAN_Standard:
+        // CAN 协议暂不支持轮询模式
+        LOG_WARNING() << "CAN protocol not supported for polling";
+        return QByteArray();
+    }
+
+    return QByteArray();
+}
+
+bool PollingTaskExecutor::sendRequest(const QByteArray &request)
+{
+    if (request.isEmpty()) {
+        return false;
+    }
+
+    QString deviceId = m_task.device_bind;
+    if (deviceId.isEmpty()) {
+        LOG_ERROR() << "Device bind is empty for task:" << m_task.task_id;
+        return false;
+    }
+
+    switch (m_task.transport_type) {
+    case TransportType::Serial:
+        if (m_serialManager) {
+            return m_serialManager->writeData(deviceId, request);
+        }
+        break;
+
+    case TransportType::TCP_Client:
+    case TransportType::UDP_Client:
+        if (m_networkManager) {
+            return m_networkManager->writeData(deviceId, request);
+        }
+        break;
+
+    default:
+        LOG_WARNING() << "Unsupported transport type for polling:" 
+                     << static_cast<int>(m_task.transport_type);
+        return false;
+    }
+
+    return false;
+}
+
+void PollingTaskExecutor::parseResponse(const QByteArray &data)
+{
+    if (!m_busCore || !m_pluginManager) {
+        return;
+    }
+
+    // 原始数据模式,不解析
+    if (m_task.protocol_type == ProtocolType::Raw_Data) {
+        return;
+    }
+
+    // 根据协议类型获取协议名称
+    QString protocolName;
+    QString protocolDetail;
+    switch (m_task.protocol_type) {
+    case ProtocolType::Modbus_RTU:
+        protocolName = QStringLiteral("modbus");
+        protocolDetail = QStringLiteral("modbus-rtu");
+        break;
+    case ProtocolType::Modbus_TCP:
+        protocolName = QStringLiteral("modbus");
+        protocolDetail = QStringLiteral("modbus-tcp");
+        break;
+    case ProtocolType::CAN_Standard:
+        // CAN 协议暂不支持轮询模式解析
+        return;
+    default:
+        LOG_DEBUG() << "Unsupported protocol type for parsing:" 
+                    << static_cast<int>(m_task.protocol_type);
+        return;
+    }
+
+    // 获取协议解析器
+    IProtocolParser *parser = m_pluginManager->getParser(protocolName);
+    if (!parser) {
+        LOG_DEBUG() << "No parser available for protocol:" << protocolName;
+        return;
+    }
+
+    // 验证帧完整性
+    if (!parser->validateFrame(data)) {
+        LOG_DEBUG() << "Invalid frame for protocol:" << protocolName;
+        return;
+    }
+
+    // 解析帧
+    QJsonObject parsedResult;
+    if (!parser->parseFrame(data, parsedResult)) {
+        LOG_DEBUG() << "Failed to parse frame for protocol:" << protocolName;
+        return;
+    }
+
+    // 创建总线消息
+    BusMessage message;
+    message.id = QStringLiteral("%1_%2_%3")
+                 .arg(m_task.task_id)
+                 .arg(protocolName)
+                 .arg(QDateTime::currentMSecsSinceEpoch());
+    message.source = m_task.device_bind;
+    message.destination = QStringLiteral("data_processor");
+    message.timestamp = QDateTime::currentMSecsSinceEpoch();
+
+    // 设置payload
+    QJsonObject payload = parsedResult;
+    payload[QStringLiteral("protocol")] = protocolName;
+    if (!protocolDetail.isEmpty()) {
+        payload[QStringLiteral("protocol_detail")] = protocolDetail;
+    }
+    payload[QStringLiteral("raw_hex")] = QString::fromLatin1(data.toHex());
+    payload[QStringLiteral("task_id")] = m_task.task_id;
+    message.payload = payload;
+
+    // 存储总线消息
+    m_busCore->storeBusMessage(message);
+
+    LOG_DEBUG() << "Response parsed and stored for task:" << m_task.task_id 
+                << "protocol:" << protocolName;
+}
+
+void PollingTaskExecutor::updateLastCommTime()
+{
+    // 更新任务的最后通信时间
+    // 这个可以通过 TaskManager 更新,但为了减少依赖,暂时不实现
+    // 可以在 TaskScheduler 中统一管理
+}
+
+int PollingTaskExecutor::getPollInterval() const
+{
+    // 从 params_json 中获取轮询间隔,默认 1000ms
+    QJsonValue intervalValue = m_task.params_json.value(QStringLiteral("poll_interval_ms"));
+    if (intervalValue.isDouble()) {
+        int interval = intervalValue.toInt();
+        return qMax(100, interval); // 最小间隔 100ms
+    }
+    return 1000; // 默认 1 秒
+}
+
+int PollingTaskExecutor::getResponseTimeout() const
+{
+    // 从 params_json 中获取响应超时时间,默认 1000ms
+    QJsonValue timeoutValue = m_task.params_json.value(QStringLiteral("response_timeout_ms"));
+    if (timeoutValue.isDouble()) {
+        int timeout = timeoutValue.toInt();
+        return qMax(100, timeout); // 最小超时 100ms
+    }
+    return 1000; // 默认 1 秒
+}
+

+ 113 - 0
src/task_manager/PollingTaskExecutor.h

@@ -0,0 +1,113 @@
+/**
+ * @file PollingTaskExecutor.h
+ * @brief 轮询任务执行器 - 实现定时轮询任务
+ * 
+ * 职责:
+ * - 使用 QTimer 实现定时轮询
+ * - 构建请求帧(支持 Modbus RTU/TCP)
+ * - 发送请求并等待响应
+ * - 处理响应超时
+ * - 存储原始数据和解析后的消息
+ */
+
+#ifndef POLLING_TASK_EXECUTOR_H
+#define POLLING_TASK_EXECUTOR_H
+
+#include "TaskExecutor.h"
+#include <QTimer>
+#include <QByteArray>
+
+// 前向声明
+class SerialManager;
+class NetworkManager;
+class DeviceBusCore;
+class ProtocolPluginManager;
+
+class PollingTaskExecutor : public TaskExecutor {
+    Q_OBJECT
+
+public:
+    explicit PollingTaskExecutor(const TransferTask &task,
+                                 SerialManager *serialManager,
+                                 NetworkManager *networkManager,
+                                 DeviceBusCore *busCore,
+                                 ProtocolPluginManager *pluginManager,
+                                 QObject *parent = nullptr);
+    ~PollingTaskExecutor() override;
+
+    bool start() override;
+    void stop() override;
+    bool pause() override;
+    bool resume() override;
+
+private slots:
+    /**
+     * @brief 定时器触发,执行一次轮询
+     */
+    void onPollTimer();
+
+    /**
+     * @brief 处理接收到的数据
+     * @param deviceId 设备ID或接口名
+     * @param data 接收到的数据
+     */
+    void onDataReceived(const QString &deviceId, const QByteArray &data);
+
+    /**
+     * @brief 响应超时处理
+     */
+    void onResponseTimeout();
+
+private:
+    /**
+     * @brief 构建请求帧
+     * @return 请求数据,失败返回空 QByteArray
+     */
+    QByteArray buildRequest();
+
+    /**
+     * @brief 发送请求
+     * @param request 请求数据
+     * @return 成功返回true
+     */
+    bool sendRequest(const QByteArray &request);
+
+    /**
+     * @brief 解析响应数据
+     * @param data 响应数据
+     */
+    void parseResponse(const QByteArray &data);
+
+    /**
+     * @brief 更新最后通信时间
+     */
+    void updateLastCommTime();
+
+    /**
+     * @brief 获取轮询间隔(毫秒)
+     * @return 轮询间隔
+     */
+    int getPollInterval() const;
+
+    /**
+     * @brief 获取响应超时时间(毫秒)
+     * @return 超时时间
+     */
+    int getResponseTimeout() const;
+
+private:
+    SerialManager *m_serialManager;
+    NetworkManager *m_networkManager;
+    DeviceBusCore *m_busCore;
+    ProtocolPluginManager *m_pluginManager;
+
+    QTimer *m_pollTimer;          // 轮询定时器
+    QTimer *m_responseTimer;      // 响应超时定时器
+    bool m_waitingForResponse;    // 是否正在等待响应
+    QByteArray m_lastRequest;     // 最后一次发送的请求
+    int m_consecutiveErrors;       // 连续错误次数
+    static const int MAX_CONSECUTIVE_ERRORS = 3; // 最大连续错误次数
+};
+
+#endif // POLLING_TASK_EXECUTOR_H
+

+ 40 - 0
src/task_manager/TaskExecutor.cpp

@@ -0,0 +1,40 @@
+#include "TaskExecutor.h"
+#include "utils/logging.h"
+
+TaskExecutor::TaskExecutor(const TransferTask &task, QObject *parent)
+    : QObject(parent)
+    , m_task(task)
+    , m_isRunning(false)
+    , m_isPaused(false)
+{
+}
+
+TaskExecutor::~TaskExecutor()
+{
+    stop();
+}
+
+bool TaskExecutor::pause()
+{
+    if (!m_isRunning || m_isPaused) {
+        return false;
+    }
+    m_isPaused = true;
+    return true;
+}
+
+bool TaskExecutor::resume()
+{
+    if (!m_isRunning || !m_isPaused) {
+        return false;
+    }
+    m_isPaused = false;
+    return true;
+}
+
+void TaskExecutor::stop()
+{
+    m_isRunning = false;
+    m_isPaused = false;
+}
+

+ 81 - 0
src/task_manager/TaskExecutor.h

@@ -0,0 +1,81 @@
+/**
+ * @file TaskExecutor.h
+ * @brief 任务执行器基类 - 定义任务执行器的通用接口
+ * 
+ * 职责:
+ * - 定义任务执行器的通用接口
+ * - 管理任务执行的生命周期
+ * - 提供启动、停止、暂停、恢复等控制方法
+ */
+
+#ifndef TASK_EXECUTOR_H
+#define TASK_EXECUTOR_H
+
+#include "TransferTask.h"
+#include <QObject>
+#include <QString>
+
+class TaskExecutor : public QObject {
+    Q_OBJECT
+
+public:
+    explicit TaskExecutor(const TransferTask &task, QObject *parent = nullptr);
+    virtual ~TaskExecutor();
+
+    /**
+     * @brief 启动任务执行器
+     * @return 成功返回true
+     */
+    virtual bool start() = 0;
+
+    /**
+     * @brief 停止任务执行器
+     */
+    virtual void stop();
+
+    /**
+     * @brief 暂停任务执行器
+     * @return 成功返回true
+     */
+    virtual bool pause();
+
+    /**
+     * @brief 恢复任务执行器
+     * @return 成功返回true
+     */
+    virtual bool resume();
+
+    /**
+     * @brief 获取任务ID
+     * @return 任务ID
+     */
+    QString getTaskId() const { return m_task.task_id; }
+
+    /**
+     * @brief 获取任务信息
+     * @return 任务信息
+     */
+    const TransferTask& getTask() const { return m_task; }
+
+signals:
+    /**
+     * @brief 任务执行器完成信号
+     * @param taskId 任务ID
+     */
+    void finished(const QString &taskId);
+
+    /**
+     * @brief 任务执行器错误信号
+     * @param taskId 任务ID
+     * @param error 错误信息
+     */
+    void error(const QString &taskId, const QString &error);
+
+protected:
+    TransferTask m_task;
+    bool m_isRunning;
+    bool m_isPaused;
+};
+
+#endif // TASK_EXECUTOR_H
+

+ 343 - 0
src/task_manager/TaskManager.cpp

@@ -0,0 +1,343 @@
+#include "TaskManager.h"
+#include "utils/logging.h"
+#include <QSqlQuery>
+#include <QSqlError>
+#include <QSqlRecord>
+#include <QUuid>
+#include <QJsonDocument>
+#include <QDateTime>
+
+TaskManager::TaskManager(DeviceBusCore *busCore, QObject *parent)
+    : QObject(parent)
+    , m_busCore(busCore)
+{
+    if (!m_busCore) {
+        LOG_CRITICAL() << "TaskManager: DeviceBusCore is null";
+    }
+}
+
+TaskManager::~TaskManager()
+{
+    QMutexLocker locker(&m_mutex);
+    m_tasks.clear();
+}
+
+bool TaskManager::createTask(const TransferTask &task)
+{
+    QMutexLocker locker(&m_mutex);
+
+    // 创建任务副本以便修改
+    TransferTask newTask = task;
+
+    // 如果 task_id 为空,自动生成 UUID
+    if (newTask.task_id.isEmpty()) {
+        newTask.task_id = QUuid::createUuid().toString(QUuid::Id128);
+    }
+
+    // 检查任务是否已存在
+    if (m_tasks.contains(newTask.task_id)) {
+        LOG_WARNING() << "Task already exists:" << newTask.task_id;
+        return false;
+    }
+
+    // 设置创建和更新时间
+    QDateTime now = QDateTime::currentDateTimeUtc();
+    if (!newTask.created_at.isValid()) {
+        newTask.created_at = now;
+    }
+    newTask.updated_at = now;
+
+    // 保存到数据库
+    if (!saveToDatabase(newTask)) {
+        LOG_ERROR() << "Failed to save task to database:" << newTask.task_id;
+        return false;
+    }
+
+    // 添加到内存缓存
+    m_tasks.insert(newTask.task_id, newTask);
+
+    emit taskCreated(newTask);
+    LOG_DEBUG() << "Task created:" << newTask.task_id << newTask.task_name;
+    return true;
+}
+
+bool TaskManager::updateTask(const QString &taskId, const TransferTask &task)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty() || taskId != task.task_id) {
+        LOG_WARNING() << "Invalid task ID for update";
+        return false;
+    }
+
+    if (!m_tasks.contains(taskId)) {
+        LOG_WARNING() << "Task not found for update:" << taskId;
+        return false;
+    }
+
+    // 更新 updated_at 时间
+    TransferTask updatedTask = task;
+    updatedTask.updated_at = QDateTime::currentDateTimeUtc();
+
+    // 保存到数据库
+    if (!saveToDatabase(updatedTask)) {
+        LOG_ERROR() << "Failed to update task in database:" << taskId;
+        return false;
+    }
+
+    // 更新内存缓存
+    m_tasks[taskId] = updatedTask;
+
+    emit taskUpdated(updatedTask);
+    LOG_DEBUG() << "Task updated:" << taskId;
+    return true;
+}
+
+bool TaskManager::deleteTask(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty()) {
+        LOG_WARNING() << "Invalid task ID for deletion";
+        return false;
+    }
+
+    if (!m_tasks.contains(taskId)) {
+        LOG_WARNING() << "Task not found for deletion:" << taskId;
+        return false;
+    }
+
+    // 从数据库删除
+    if (!m_busCore) {
+        LOG_ERROR() << "DeviceBusCore is null, cannot delete task from database";
+        return false;
+    }
+
+    QSqlDatabase* db = m_busCore->getThreadLocalConnection();
+    if (!db || !db->isValid() || !db->isOpen()) {
+        LOG_ERROR() << "Database connection not available for deleting task";
+        return false;
+    }
+
+    QSqlQuery query(*db);
+    query.prepare(QStringLiteral("DELETE FROM tb_transmission_tasks WHERE task_id = :task_id"));
+    query.bindValue(QStringLiteral(":task_id"), taskId);
+
+    if (!query.exec()) {
+        LOG_ERROR() << "Failed to delete task from database:" << query.lastError().text();
+        return false;
+    }
+
+    // 从内存缓存删除
+    m_tasks.remove(taskId);
+
+    emit taskDeleted(taskId);
+    LOG_DEBUG() << "Task deleted:" << taskId;
+    return true;
+}
+
+TransferTask TaskManager::getTask(const QString &taskId) const
+{
+    QMutexLocker locker(&m_mutex);
+    return m_tasks.value(taskId, TransferTask());
+}
+
+QList<TransferTask> TaskManager::getAllTasks() const
+{
+    QMutexLocker locker(&m_mutex);
+    return m_tasks.values();
+}
+
+bool TaskManager::loadFromDatabase()
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (!m_busCore) {
+        LOG_ERROR() << "DeviceBusCore is null, cannot load tasks from database";
+        return false;
+    }
+
+    // 从数据库查询所有任务
+    QList<TransferTask> tasks = queryTasksFromDatabase();
+    
+    // 清空内存缓存
+    m_tasks.clear();
+    
+    // 加载到内存缓存
+    for (const TransferTask &task : tasks) {
+        m_tasks.insert(task.task_id, task);
+    }
+
+    LOG_DEBUG() << "Loaded" << m_tasks.size() << "tasks from database";
+    return true;
+}
+
+bool TaskManager::saveToDatabase(const TransferTask &task)
+{
+    if (!m_busCore) {
+        LOG_ERROR() << "DeviceBusCore is null, cannot save task to database";
+        return false;
+    }
+
+    QSqlDatabase* db = m_busCore->getThreadLocalConnection();
+    if (!db || !db->isValid() || !db->isOpen()) {
+        LOG_ERROR() << "Database connection not available for saving task";
+        return false;
+    }
+
+    // 将 params_json 转换为 JSON 字符串
+    QJsonDocument paramsDoc(task.params_json);
+    QString paramsJsonStr = QString::fromUtf8(paramsDoc.toJson(QJsonDocument::Compact));
+
+    QSqlQuery query(*db);
+    query.prepare(QStringLiteral(
+        "INSERT INTO tb_transmission_tasks (task_id, task_name, is_enabled, "
+        "transport_type, protocol_type, device_bind, trigger_mode, params_json, "
+        "status, created_at, updated_at, last_comm_time) "
+        "VALUES (:task_id, :task_name, :is_enabled, :transport_type, "
+        ":protocol_type, :device_bind, :trigger_mode, :params_json, :status, "
+        ":created_at, :updated_at, :last_comm_time) "
+        "ON CONFLICT (task_id) DO UPDATE SET "
+        "task_name = EXCLUDED.task_name, "
+        "is_enabled = EXCLUDED.is_enabled, "
+        "transport_type = EXCLUDED.transport_type, "
+        "protocol_type = EXCLUDED.protocol_type, "
+        "device_bind = EXCLUDED.device_bind, "
+        "trigger_mode = EXCLUDED.trigger_mode, "
+        "params_json = EXCLUDED.params_json, "
+        "status = EXCLUDED.status, "
+        "updated_at = EXCLUDED.updated_at, "
+        "last_comm_time = EXCLUDED.last_comm_time"));
+
+    query.bindValue(QStringLiteral(":task_id"), task.task_id);
+    query.bindValue(QStringLiteral(":task_name"), task.task_name);
+    query.bindValue(QStringLiteral(":is_enabled"), task.is_enabled);
+    query.bindValue(QStringLiteral(":transport_type"), static_cast<int>(task.transport_type));
+    query.bindValue(QStringLiteral(":protocol_type"), static_cast<int>(task.protocol_type));
+    query.bindValue(QStringLiteral(":device_bind"), task.device_bind);
+    query.bindValue(QStringLiteral(":trigger_mode"), static_cast<int>(task.trigger_mode));
+    
+    // 将 JSON 对象转换为 JSONB
+    QVariant paramsVariant;
+    if (!task.params_json.isEmpty()) {
+        paramsVariant = QVariant::fromValue(task.params_json);
+    } else {
+        paramsVariant = QVariant(QVariant::Map);
+    }
+    query.bindValue(QStringLiteral(":params_json"), paramsVariant);
+    
+    query.bindValue(QStringLiteral(":status"), static_cast<int>(task.status));
+    query.bindValue(QStringLiteral(":created_at"), task.created_at);
+    query.bindValue(QStringLiteral(":updated_at"), task.updated_at);
+    
+    if (task.last_comm_time.isValid()) {
+        query.bindValue(QStringLiteral(":last_comm_time"), task.last_comm_time);
+    } else {
+        query.bindValue(QStringLiteral(":last_comm_time"), QVariant(QVariant::DateTime));
+    }
+
+    if (!query.exec()) {
+        LOG_ERROR() << "Failed to save task to database:" << query.lastError().text();
+        return false;
+    }
+
+    return true;
+}
+
+bool TaskManager::taskExists(const QString &taskId) const
+{
+    QMutexLocker locker(&m_mutex);
+    return m_tasks.contains(taskId);
+}
+
+QList<TransferTask> TaskManager::queryTasksFromDatabase(const QString &taskId) const
+{
+    QList<TransferTask> tasks;
+    
+    if (!m_busCore) {
+        return tasks;
+    }
+
+    QSqlDatabase* db = m_busCore->getThreadLocalConnection();
+    if (!db || !db->isValid() || !db->isOpen()) {
+        LOG_WARNING() << "Database connection not available for querying tasks";
+        return tasks;
+    }
+
+    QSqlQuery query(*db);
+    if (taskId.isEmpty()) {
+        query.prepare(QStringLiteral(
+            "SELECT task_id, task_name, is_enabled, transport_type, protocol_type, "
+            "device_bind, trigger_mode, params_json, status, created_at, updated_at, "
+            "last_comm_time FROM tb_transmission_tasks ORDER BY created_at"));
+    } else {
+        query.prepare(QStringLiteral(
+            "SELECT task_id, task_name, is_enabled, transport_type, protocol_type, "
+            "device_bind, trigger_mode, params_json, status, created_at, updated_at, "
+            "last_comm_time FROM tb_transmission_tasks WHERE task_id = :task_id"));
+        query.bindValue(QStringLiteral(":task_id"), taskId);
+    }
+
+    if (!query.exec()) {
+        LOG_ERROR() << "Failed to query tasks from database:" << query.lastError().text();
+        return tasks;
+    }
+
+    while (query.next()) {
+        tasks.append(buildTaskFromQuery(query));
+    }
+
+    return tasks;
+}
+
+TransferTask TaskManager::buildTaskFromQuery(const QSqlQuery &query) const
+{
+    TransferTask task;
+    
+    task.task_id = query.value(0).toString();
+    task.task_name = query.value(1).toString();
+    task.is_enabled = query.value(2).toBool();
+    task.transport_type = static_cast<TransportType>(query.value(3).toInt());
+    task.protocol_type = static_cast<ProtocolType>(query.value(4).toInt());
+    task.device_bind = query.value(5).toString();
+    task.trigger_mode = static_cast<TriggerMode>(query.value(6).toInt());
+    
+    // 解析 params_json (JSONB 字段)
+    QVariant paramsVariant = query.value(7);
+    if (paramsVariant.isValid() && !paramsVariant.isNull()) {
+        if (paramsVariant.type() == QVariant::Map) {
+            // 如果是 Map,直接转换
+            QJsonObject obj = QJsonObject::fromVariantMap(paramsVariant.toMap());
+            task.params_json = obj;
+        } else if (paramsVariant.type() == QVariant::String) {
+            // 如果是字符串,解析 JSON
+            QString paramsJsonStr = paramsVariant.toString();
+            if (!paramsJsonStr.isEmpty()) {
+                QJsonDocument doc = QJsonDocument::fromJson(paramsJsonStr.toUtf8());
+                if (doc.isObject()) {
+                    task.params_json = doc.object();
+                }
+            }
+        } else {
+            // 尝试转换为 JSON
+            QJsonDocument doc = QJsonDocument::fromVariant(paramsVariant);
+            if (doc.isObject()) {
+                task.params_json = doc.object();
+            }
+        }
+    }
+    
+    task.status = static_cast<TaskStatus>(query.value(8).toInt());
+    task.created_at = query.value(9).toDateTime();
+    task.updated_at = query.value(10).toDateTime();
+    
+    if (query.record().count() > 11) {
+        QVariant lastCommTime = query.value(11);
+        if (lastCommTime.isValid() && !lastCommTime.isNull()) {
+            task.last_comm_time = lastCommTime.toDateTime();
+        }
+    }
+    
+    return task;
+}
+

+ 123 - 0
src/task_manager/TaskManager.h

@@ -0,0 +1,123 @@
+/**
+ * @file TaskManager.h
+ * @brief 任务管理器 - 管理传输任务的增删改查和数据库持久化
+ * 
+ * 职责:
+ * - 任务的增删改查操作
+ * - 数据库持久化
+ * - 任务数据的内存缓存
+ */
+
+#ifndef TASK_MANAGER_H
+#define TASK_MANAGER_H
+
+#include "TransferTask.h"
+#include "soft_bus_core/soft_bus_core.h"
+#include <QObject>
+#include <QMap>
+#include <QMutex>
+#include <QList>
+
+class TaskManager : public QObject {
+    Q_OBJECT
+
+public:
+    explicit TaskManager(DeviceBusCore *busCore, QObject *parent = nullptr);
+    ~TaskManager();
+
+    /**
+     * @brief 创建任务
+     * @param task 任务信息(task_id 如果为空则自动生成UUID)
+     * @return 成功返回true
+     */
+    bool createTask(const TransferTask &task);
+
+    /**
+     * @brief 更新任务
+     * @param taskId 任务ID
+     * @param task 任务信息
+     * @return 成功返回true
+     */
+    bool updateTask(const QString &taskId, const TransferTask &task);
+
+    /**
+     * @brief 删除任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool deleteTask(const QString &taskId);
+
+    /**
+     * @brief 获取任务
+     * @param taskId 任务ID
+     * @return 任务信息,如果不存在返回默认构造的任务
+     */
+    TransferTask getTask(const QString &taskId) const;
+
+    /**
+     * @brief 获取所有任务
+     * @return 任务列表
+     */
+    QList<TransferTask> getAllTasks() const;
+
+    /**
+     * @brief 从数据库加载所有任务到内存
+     * @return 成功返回true
+     */
+    bool loadFromDatabase();
+
+    /**
+     * @brief 保存任务到数据库
+     * @param task 任务信息
+     * @return 成功返回true
+     */
+    bool saveToDatabase(const TransferTask &task);
+
+    /**
+     * @brief 检查任务是否存在
+     * @param taskId 任务ID
+     * @return 存在返回true
+     */
+    bool taskExists(const QString &taskId) const;
+
+signals:
+    /**
+     * @brief 任务创建信号
+     * @param task 任务信息
+     */
+    void taskCreated(const TransferTask &task);
+
+    /**
+     * @brief 任务更新信号
+     * @param task 任务信息
+     */
+    void taskUpdated(const TransferTask &task);
+
+    /**
+     * @brief 任务删除信号
+     * @param taskId 任务ID
+     */
+    void taskDeleted(const QString &taskId);
+
+private:
+    DeviceBusCore *m_busCore;
+    mutable QMutex m_mutex;
+    QMap<QString, TransferTask> m_tasks;  // 内存缓存:task_id -> TransferTask
+
+    /**
+     * @brief 从数据库查询任务
+     * @param taskId 任务ID(如果为空则查询所有任务)
+     * @return 任务列表
+     */
+    QList<TransferTask> queryTasksFromDatabase(const QString &taskId = QString()) const;
+
+    /**
+     * @brief 从数据库记录构建任务对象
+     * @param query 数据库查询结果
+     * @return 任务对象
+     */
+    TransferTask buildTaskFromQuery(const QSqlQuery &query) const;
+};
+
+#endif // TASK_MANAGER_H
+

+ 486 - 0
src/task_manager/TaskScheduler.cpp

@@ -0,0 +1,486 @@
+#include "TaskScheduler.h"
+#include "TaskExecutor.h"
+#include "PollingTaskExecutor.h"
+#include "EventTaskExecutor.h"
+#include "utils/logging.h"
+#include <QMutexLocker>
+#ifndef SOFT_BUS_DAEMON_BUILD
+#include "daemon/daemon_client.h"
+#endif
+
+TaskScheduler::TaskScheduler(TaskManager *taskManager, 
+                             DeviceBusCore *busCore,
+                             SerialManager *serialManager,
+                             NetworkManager *networkManager,
+                             ProtocolPluginManager *pluginManager,
+                             QObject *parent)
+    : QObject(parent)
+    , m_taskManager(taskManager)
+    , m_busCore(busCore)
+    , m_serialManager(serialManager)
+    , m_networkManager(networkManager)
+    , m_pluginManager(pluginManager)
+#ifndef SOFT_BUS_DAEMON_BUILD
+    , m_daemonClient(nullptr)
+#endif
+{
+    if (!m_taskManager) {
+        LOG_CRITICAL() << "TaskScheduler: TaskManager is null";
+    }
+    if (!m_busCore) {
+        LOG_CRITICAL() << "TaskScheduler: DeviceBusCore is null";
+    }
+}
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+void TaskScheduler::setDaemonClient(DaemonClient* daemonClient)
+{
+    m_daemonClient = daemonClient;
+}
+#endif
+
+TaskScheduler::~TaskScheduler()
+{
+    stopAllTasks();
+}
+
+bool TaskScheduler::startTask(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty()) {
+        LOG_WARNING() << "Invalid task ID for starting task";
+        return false;
+    }
+
+    // 检查任务是否已存在执行器
+    if (m_executors.contains(taskId)) {
+        LOG_WARNING() << "Task already running:" << taskId;
+        return false;
+    }
+
+    // 获取任务信息
+    TransferTask task = m_taskManager->getTask(taskId);
+    if (task.task_id.isEmpty()) {
+        LOG_WARNING() << "Task not found:" << taskId;
+        return false;
+    }
+
+    // 如果任务未启用,不启动
+    if (!task.is_enabled) {
+        LOG_DEBUG() << "Task is disabled, not starting:" << taskId;
+        return false;
+    }
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 通过守护进程启动任务(任务执行由守护进程负责)
+    if (m_daemonClient) {
+        if (m_daemonClient->startTask(taskId)) {
+            // 更新任务状态为运行中(实际状态由守护进程管理)
+            updateTaskStatus(taskId, TaskStatus::Running);
+            LOG_DEBUG() << "Task start request sent to daemon:" << taskId;
+            return true;
+        } else {
+            LOG_ERROR() << "Failed to start task via daemon:" << taskId;
+            updateTaskStatus(taskId, TaskStatus::Error);
+            emit taskError(taskId, QStringLiteral("Failed to start task via daemon"));
+            return false;
+        }
+    } else {
+        LOG_WARNING() << "DaemonClient not set, cannot start task:" << taskId;
+        updateTaskStatus(taskId, TaskStatus::Error);
+        emit taskError(taskId, QStringLiteral("Daemon not connected"));
+        return false;
+    }
+#else
+    // 守护进程模式:直接创建执行器(守护进程内部使用)
+    // 申请设备资源锁定(使用内部方法,因为已经持有锁)
+    if (!task.device_bind.isEmpty()) {
+        if (!requestDeviceLockInternal(task.device_bind, taskId)) {
+            LOG_WARNING() << "Failed to lock device for task:" << taskId 
+                         << "device:" << task.device_bind;
+            updateTaskStatus(taskId, TaskStatus::Error);
+            emit taskError(taskId, QStringLiteral("Device is locked by another task"));
+            return false;
+        }
+    }
+
+    // 创建任务执行器
+    TaskExecutor* executor = createExecutor(task);
+    if (!executor) {
+        LOG_ERROR() << "Failed to create executor for task:" << taskId;
+        if (!task.device_bind.isEmpty()) {
+            releaseDeviceLockInternal(task.device_bind, taskId);
+        }
+        updateTaskStatus(taskId, TaskStatus::Error);
+        emit taskError(taskId, QStringLiteral("Failed to create executor"));
+        return false;
+    }
+
+    // 连接执行器信号
+    connect(executor, &TaskExecutor::finished, this, 
+            [this, taskId]() { onTaskExecutorFinished(taskId); });
+    connect(executor, &TaskExecutor::error, this,
+            [this, taskId](const QString &error) { onTaskExecutorError(taskId, error); });
+
+    // 启动执行器
+    if (!executor->start()) {
+        LOG_ERROR() << "Failed to start executor for task:" << taskId;
+        destroyExecutor(taskId);
+        if (!task.device_bind.isEmpty()) {
+            releaseDeviceLockInternal(task.device_bind, taskId);
+        }
+        updateTaskStatus(taskId, TaskStatus::Error);
+        emit taskError(taskId, QStringLiteral("Failed to start executor"));
+        return false;
+    }
+
+    // 保存执行器
+    m_executors.insert(taskId, executor);
+
+    // 更新任务状态
+    updateTaskStatus(taskId, TaskStatus::Running);
+
+    LOG_DEBUG() << "Task started:" << taskId;
+    return true;
+#endif
+}
+
+bool TaskScheduler::stopTask(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty()) {
+        LOG_WARNING() << "Invalid task ID for stopping task";
+        return false;
+    }
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 通过守护进程停止任务
+    if (m_daemonClient) {
+        if (m_daemonClient->stopTask(taskId)) {
+            updateTaskStatus(taskId, TaskStatus::Stopped);
+            LOG_DEBUG() << "Task stop request sent to daemon:" << taskId;
+            return true;
+        } else {
+            LOG_ERROR() << "Failed to stop task via daemon:" << taskId;
+            return false;
+        }
+    } else {
+        LOG_WARNING() << "DaemonClient not set, cannot stop task:" << taskId;
+        return false;
+    }
+#else
+    // 守护进程模式:直接停止执行器
+    if (!m_executors.contains(taskId)) {
+        LOG_WARNING() << "Task not running:" << taskId;
+        return false;
+    }
+
+    // 获取任务信息以释放设备锁定
+    TransferTask task = m_taskManager->getTask(taskId);
+    
+    // 停止执行器
+    TaskExecutor* executor = m_executors.value(taskId);
+    if (executor) {
+        executor->stop();
+    }
+
+    // 销毁执行器
+    destroyExecutor(taskId);
+
+    // 释放设备锁定(使用内部方法,因为已经持有锁)
+    if (!task.device_bind.isEmpty()) {
+        releaseDeviceLockInternal(task.device_bind, taskId);
+    }
+
+    // 更新任务状态
+    updateTaskStatus(taskId, TaskStatus::Stopped);
+
+    LOG_DEBUG() << "Task stopped:" << taskId;
+    return true;
+#endif
+}
+
+bool TaskScheduler::pauseTask(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty()) {
+        LOG_WARNING() << "Invalid task ID for pausing task";
+        return false;
+    }
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 通过守护进程暂停任务
+    if (m_daemonClient) {
+        if (m_daemonClient->pauseTask(taskId)) {
+            updateTaskStatus(taskId, TaskStatus::Paused);
+            LOG_DEBUG() << "Task pause request sent to daemon:" << taskId;
+            return true;
+        } else {
+            LOG_ERROR() << "Failed to pause task via daemon:" << taskId;
+            return false;
+        }
+    } else {
+        LOG_WARNING() << "DaemonClient not set, cannot pause task:" << taskId;
+        return false;
+    }
+#else
+    // 守护进程模式:直接暂停执行器
+    if (!m_executors.contains(taskId)) {
+        LOG_WARNING() << "Task not running:" << taskId;
+        return false;
+    }
+
+    TaskExecutor* executor = m_executors.value(taskId);
+    if (executor && executor->pause()) {
+        updateTaskStatus(taskId, TaskStatus::Paused);
+        LOG_DEBUG() << "Task paused:" << taskId;
+        return true;
+    }
+
+    return false;
+#endif
+}
+
+bool TaskScheduler::resumeTask(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (taskId.isEmpty()) {
+        LOG_WARNING() << "Invalid task ID for resuming task";
+        return false;
+    }
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+    // 通过守护进程恢复任务
+    if (m_daemonClient) {
+        if (m_daemonClient->resumeTask(taskId)) {
+            updateTaskStatus(taskId, TaskStatus::Running);
+            LOG_DEBUG() << "Task resume request sent to daemon:" << taskId;
+            return true;
+        } else {
+            LOG_ERROR() << "Failed to resume task via daemon:" << taskId;
+            return false;
+        }
+    } else {
+        LOG_WARNING() << "DaemonClient not set, cannot resume task:" << taskId;
+        return false;
+    }
+#else
+    // 守护进程模式:直接恢复执行器
+    if (!m_executors.contains(taskId)) {
+        LOG_WARNING() << "Task not running:" << taskId;
+        return false;
+    }
+
+    TaskExecutor* executor = m_executors.value(taskId);
+    if (executor && executor->resume()) {
+        updateTaskStatus(taskId, TaskStatus::Running);
+        LOG_DEBUG() << "Task resumed:" << taskId;
+        return true;
+    }
+
+    return false;
+#endif
+}
+
+bool TaskScheduler::requestDeviceLock(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+    return requestDeviceLockInternal(deviceId, taskId);
+}
+
+bool TaskScheduler::requestDeviceLockInternal(const QString &deviceId, const QString &taskId)
+{
+    // 注意:此方法假设调用者已经持有 m_mutex 锁
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    // 检查设备是否已被锁定
+    if (m_deviceLocks.contains(deviceId)) {
+        QString lockingTaskId = m_deviceLocks.value(deviceId);
+        if (lockingTaskId != taskId) {
+            LOG_WARNING() << "Device" << deviceId << "is already locked by task" << lockingTaskId;
+            return false;
+        }
+        // 如果是同一个任务,直接返回成功
+        return true;
+    }
+
+    // 锁定设备
+    m_deviceLocks.insert(deviceId, taskId);
+    LOG_DEBUG() << "Device locked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool TaskScheduler::releaseDeviceLock(const QString &deviceId, const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+    return releaseDeviceLockInternal(deviceId, taskId);
+}
+
+bool TaskScheduler::releaseDeviceLockInternal(const QString &deviceId, const QString &taskId)
+{
+    // 注意:此方法假设调用者已经持有 m_mutex 锁
+    if (deviceId.isEmpty() || taskId.isEmpty()) {
+        return false;
+    }
+
+    if (!m_deviceLocks.contains(deviceId)) {
+        LOG_WARNING() << "Device" << deviceId << "is not locked";
+        return false;
+    }
+
+    QString lockingTaskId = m_deviceLocks.value(deviceId);
+    if (lockingTaskId != taskId) {
+        LOG_WARNING() << "Device" << deviceId << "is locked by different task:" 
+                     << lockingTaskId << "not" << taskId;
+        return false;
+    }
+
+    m_deviceLocks.remove(deviceId);
+    LOG_DEBUG() << "Device unlocked:" << deviceId << "by task:" << taskId;
+    return true;
+}
+
+bool TaskScheduler::isDeviceLocked(const QString &deviceId) const
+{
+    QMutexLocker locker(&m_mutex);
+    return m_deviceLocks.contains(deviceId);
+}
+
+QString TaskScheduler::getLockingTaskId(const QString &deviceId) const
+{
+    QMutexLocker locker(&m_mutex);
+    return m_deviceLocks.value(deviceId, QString());
+}
+
+int TaskScheduler::startAllEnabledTasks()
+{
+    QList<TransferTask> allTasks = m_taskManager->getAllTasks();
+    int startedCount = 0;
+
+    for (const TransferTask &task : allTasks) {
+        if (task.is_enabled && task.status != TaskStatus::Running) {
+            if (startTask(task.task_id)) {
+                startedCount++;
+            }
+        }
+    }
+
+    LOG_DEBUG() << "Started" << startedCount << "enabled tasks";
+    return startedCount;
+}
+
+void TaskScheduler::stopAllTasks()
+{
+    QMutexLocker locker(&m_mutex);
+
+    QStringList taskIds = m_executors.keys();
+    locker.unlock(); // 释放锁,避免在 stopTask 中死锁
+
+    for (const QString &taskId : taskIds) {
+        stopTask(taskId);
+    }
+
+    locker.relock();
+    m_executors.clear();
+    m_deviceLocks.clear();
+}
+
+TaskStatus TaskScheduler::getTaskStatus(const QString &taskId) const
+{
+    TransferTask task = m_taskManager->getTask(taskId);
+    return task.status;
+}
+
+void TaskScheduler::updateTaskStatus(const QString &taskId, TaskStatus status)
+{
+    TransferTask task = m_taskManager->getTask(taskId);
+    if (task.task_id.isEmpty()) {
+        return;
+    }
+
+    task.status = status;
+    task.updated_at = QDateTime::currentDateTimeUtc();
+    
+    m_taskManager->updateTask(taskId, task);
+    
+    emit taskStatusChanged(taskId, status);
+}
+
+TaskExecutor* TaskScheduler::createExecutor(const TransferTask &task)
+{
+    // 根据触发模式创建不同的执行器
+    if (task.trigger_mode == TriggerMode::Polling) {
+        // 创建轮询任务执行器
+        return new PollingTaskExecutor(task,
+                                      m_serialManager,
+                                      m_networkManager,
+                                      m_busCore,
+                                      m_pluginManager,
+                                      this);
+    } else if (task.trigger_mode == TriggerMode::Event) {
+        // 创建监听任务执行器(EventTaskExecutor)
+        return new EventTaskExecutor(task,
+                                    m_serialManager,
+                                    m_networkManager,
+                                    m_busCore,
+                                    m_pluginManager,
+                                    this);
+    }
+
+    LOG_ERROR() << "Unknown trigger mode for task:" << task.task_id;
+    return nullptr;
+}
+
+void TaskScheduler::destroyExecutor(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (!m_executors.contains(taskId)) {
+        return;
+    }
+
+    TaskExecutor* executor = m_executors.take(taskId);
+    if (executor) {
+        executor->deleteLater();
+    }
+}
+
+void TaskScheduler::onTaskExecutorFinished(const QString &taskId)
+{
+    QMutexLocker locker(&m_mutex);
+
+    if (!m_executors.contains(taskId)) {
+        return;
+    }
+
+    // 获取任务信息以释放设备锁定
+    TransferTask task = m_taskManager->getTask(taskId);
+    
+    // 销毁执行器
+    destroyExecutor(taskId);
+
+    // 释放设备锁定(使用内部方法,因为已经持有锁)
+    if (!task.device_bind.isEmpty()) {
+        releaseDeviceLockInternal(task.device_bind, taskId);
+    }
+
+    // 更新任务状态
+    updateTaskStatus(taskId, TaskStatus::Stopped);
+}
+
+void TaskScheduler::onTaskExecutorError(const QString &taskId, const QString &error)
+{
+    LOG_ERROR() << "Task executor error:" << taskId << error;
+    
+    // 更新任务状态为错误
+    updateTaskStatus(taskId, TaskStatus::Error);
+    
+    emit taskError(taskId, error);
+}
+

+ 214 - 0
src/task_manager/TaskScheduler.h

@@ -0,0 +1,214 @@
+/**
+ * @file TaskScheduler.h
+ * @brief 任务调度器 - 管理任务的调度、资源管理和状态管理
+ * 
+ * 职责:
+ * - 任务启动、停止、暂停、恢复
+ * - 设备资源锁定管理
+ * - 任务状态管理
+ * - 任务执行器生命周期管理
+ */
+
+#ifndef TASK_SCHEDULER_H
+#define TASK_SCHEDULER_H
+
+#include "TransferTask.h"
+#include "TaskManager.h"
+#include <QObject>
+#include <QMap>
+#include <QMutex>
+#include <QString>
+
+// 前向声明
+class TaskExecutor;
+class SerialManager;
+class NetworkManager;
+class ProtocolPluginManager;
+#ifndef SOFT_BUS_DAEMON_BUILD
+class DaemonClient;
+#endif
+#include "soft_bus_core/soft_bus_core.h"
+
+class TaskScheduler : public QObject {
+    Q_OBJECT
+
+public:
+    explicit TaskScheduler(TaskManager *taskManager, 
+                          DeviceBusCore *busCore,
+                          SerialManager *serialManager = nullptr,
+                          NetworkManager *networkManager = nullptr,
+                          ProtocolPluginManager *pluginManager = nullptr,
+                          QObject *parent = nullptr);
+    ~TaskScheduler();
+
+#ifndef SOFT_BUS_DAEMON_BUILD
+    /**
+     * @brief 设置守护进程客户端(用于任务启动)
+     * @param daemonClient 守护进程客户端指针
+     */
+    void setDaemonClient(DaemonClient* daemonClient);
+#endif
+
+    /**
+     * @brief 启动任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool startTask(const QString &taskId);
+
+    /**
+     * @brief 停止任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool stopTask(const QString &taskId);
+
+    /**
+     * @brief 暂停任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool pauseTask(const QString &taskId);
+
+    /**
+     * @brief 恢复任务
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool resumeTask(const QString &taskId);
+
+    /**
+     * @brief 申请设备资源锁定
+     * @param deviceId 设备ID
+     * @param taskId 任务ID
+     * @return 成功返回true,如果设备已被其他任务锁定返回false
+     */
+    bool requestDeviceLock(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 释放设备资源
+     * @param deviceId 设备ID
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool releaseDeviceLock(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 检查设备是否被锁定
+     * @param deviceId 设备ID
+     * @return 被锁定返回true
+     */
+    bool isDeviceLocked(const QString &deviceId) const;
+
+    /**
+     * @brief 获取锁定设备的任务ID
+     * @param deviceId 设备ID
+     * @return 任务ID,如果未锁定返回空字符串
+     */
+    QString getLockingTaskId(const QString &deviceId) const;
+
+    /**
+     * @brief 启动所有启用的任务
+     * @return 成功启动的任务数量
+     */
+    int startAllEnabledTasks();
+
+    /**
+     * @brief 停止所有任务
+     */
+    void stopAllTasks();
+
+    /**
+     * @brief 获取任务状态
+     * @param taskId 任务ID
+     * @return 任务状态
+     */
+    TaskStatus getTaskStatus(const QString &taskId) const;
+
+signals:
+    /**
+     * @brief 任务状态变化信号
+     * @param taskId 任务ID
+     * @param status 新状态
+     */
+    void taskStatusChanged(const QString &taskId, TaskStatus status);
+
+    /**
+     * @brief 任务错误信号
+     * @param taskId 任务ID
+     * @param error 错误信息
+     */
+    void taskError(const QString &taskId, const QString &error);
+
+private slots:
+    /**
+     * @brief 处理任务执行器完成
+     * @param taskId 任务ID
+     */
+    void onTaskExecutorFinished(const QString &taskId);
+
+    /**
+     * @brief 处理任务执行器错误
+     * @param taskId 任务ID
+     * @param error 错误信息
+     */
+    void onTaskExecutorError(const QString &taskId, const QString &error);
+
+private:
+    TaskManager *m_taskManager;
+    DeviceBusCore *m_busCore;
+    SerialManager *m_serialManager;
+    NetworkManager *m_networkManager;
+    ProtocolPluginManager *m_pluginManager;
+#ifndef SOFT_BUS_DAEMON_BUILD
+    DaemonClient *m_daemonClient;
+#endif
+    mutable QMutex m_mutex;
+    
+    // 任务执行器映射:task_id -> TaskExecutor*
+    // 注意:在守护进程模式下,任务执行器由守护进程管理,这里不再使用
+    QMap<QString, TaskExecutor*> m_executors;
+    
+    // 设备锁定映射:device_id -> task_id
+    // 注意:在守护进程模式下,设备锁定由守护进程管理,这里不再使用
+    QMap<QString, QString> m_deviceLocks;
+
+    /**
+     * @brief 更新任务状态
+     * @param taskId 任务ID
+     * @param status 新状态
+     */
+    void updateTaskStatus(const QString &taskId, TaskStatus status);
+
+    /**
+     * @brief 创建任务执行器
+     * @param task 任务信息
+     * @return 任务执行器指针,失败返回 nullptr
+     */
+    TaskExecutor* createExecutor(const TransferTask &task);
+
+    /**
+     * @brief 销毁任务执行器
+     * @param taskId 任务ID
+     */
+    void destroyExecutor(const QString &taskId);
+
+    /**
+     * @brief 申请设备资源锁定(内部方法,假设调用者已持有锁)
+     * @param deviceId 设备ID
+     * @param taskId 任务ID
+     * @return 成功返回true,如果设备已被其他任务锁定返回false
+     */
+    bool requestDeviceLockInternal(const QString &deviceId, const QString &taskId);
+
+    /**
+     * @brief 释放设备资源(内部方法,假设调用者已持有锁)
+     * @param deviceId 设备ID
+     * @param taskId 任务ID
+     * @return 成功返回true
+     */
+    bool releaseDeviceLockInternal(const QString &deviceId, const QString &taskId);
+};
+
+#endif // TASK_SCHEDULER_H
+

+ 156 - 0
src/task_manager/TransferTask.h

@@ -0,0 +1,156 @@
+/**
+ * @file TransferTask.h
+ * @brief 传输任务数据结构定义
+ * 
+ * 定义了传输任务系统的核心数据结构:
+ * - 传输类型枚举(TransportType)
+ * - 协议类型枚举(ProtocolType)
+ * - 触发模式枚举(TriggerMode)
+ * - 任务状态枚举(TaskStatus)
+ * - 传输任务结构(TransferTask)
+ */
+
+#ifndef TRANSFER_TASK_H
+#define TRANSFER_TASK_H
+
+#include <QString>
+#include <QDateTime>
+#include <QJsonObject>
+#include <QJsonDocument>
+
+/**
+ * @brief 传输类型枚举
+ */
+enum class TransportType {
+    Serial,        // 串口
+    TCP_Server,    // TCP服务器
+    TCP_Client,    // TCP客户端
+    UDP_Server,    // UDP服务器
+    UDP_Client     // UDP客户端
+};
+
+/**
+ * @brief 协议类型枚举
+ */
+enum class ProtocolType {
+    Modbus_RTU,    // Modbus RTU
+    Modbus_TCP,    // Modbus TCP
+    CAN_Standard,  // CAN标准帧
+    Raw_Data       // 原始数据
+};
+
+/**
+ * @brief 触发模式枚举
+ */
+enum class TriggerMode {
+    Polling,       // 轮询模式
+    Event          // 监听模式
+};
+
+/**
+ * @brief 任务状态枚举
+ */
+enum class TaskStatus {
+    Stopped,       // 已停止
+    Running,       // 运行中
+    Error,         // 错误
+    Paused,        // 已暂停
+    Waiting        // 等待中
+};
+
+/**
+ * @brief 传输任务结构
+ */
+struct TransferTask {
+    QString task_id;              // 任务ID(UUID)
+    QString task_name;            // 任务名称
+    bool is_enabled;              // 是否启用
+    TransportType transport_type; // 传输类型
+    ProtocolType protocol_type;   // 协议类型
+    QString device_bind;           // 绑定的物理设备ID
+    TriggerMode trigger_mode;      // 触发模式
+    QJsonObject params_json;       // 差异化配置参数(JSON格式)
+    TaskStatus status;             // 任务状态
+    QDateTime created_at;          // 创建时间
+    QDateTime updated_at;           // 更新时间
+    QDateTime last_comm_time;      // 最后通信时间(可选,用于统计)
+
+    TransferTask()
+        : is_enabled(false)
+        , transport_type(TransportType::Serial)
+        , protocol_type(ProtocolType::Modbus_RTU)
+        , trigger_mode(TriggerMode::Polling)
+        , status(TaskStatus::Stopped)
+    {
+        task_id = QString();
+        task_name = QString();
+        device_bind = QString();
+        params_json = QJsonObject();
+        created_at = QDateTime::currentDateTimeUtc();
+        updated_at = QDateTime::currentDateTimeUtc();
+        last_comm_time = QDateTime();
+    }
+
+    /**
+     * @brief 将任务转换为JSON字符串
+     */
+    QString toJson() const {
+        QJsonObject obj;
+        obj[QStringLiteral("task_id")] = task_id;
+        obj[QStringLiteral("task_name")] = task_name;
+        obj[QStringLiteral("is_enabled")] = is_enabled;
+        obj[QStringLiteral("transport_type")] = static_cast<int>(transport_type);
+        obj[QStringLiteral("protocol_type")] = static_cast<int>(protocol_type);
+        obj[QStringLiteral("device_bind")] = device_bind;
+        obj[QStringLiteral("trigger_mode")] = static_cast<int>(trigger_mode);
+        obj[QStringLiteral("params_json")] = params_json;
+        obj[QStringLiteral("status")] = static_cast<int>(status);
+        if (created_at.isValid()) {
+            obj[QStringLiteral("created_at")] = created_at.toString(Qt::ISODate);
+        }
+        if (updated_at.isValid()) {
+            obj[QStringLiteral("updated_at")] = updated_at.toString(Qt::ISODate);
+        }
+        if (last_comm_time.isValid()) {
+            obj[QStringLiteral("last_comm_time")] = last_comm_time.toString(Qt::ISODate);
+        }
+        QJsonDocument doc(obj);
+        return QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
+    }
+
+    /**
+     * @brief 从JSON字符串创建任务
+     */
+    static TransferTask fromJson(const QString &jsonStr) {
+        TransferTask task;
+        QJsonDocument doc = QJsonDocument::fromJson(jsonStr.toUtf8());
+        if (doc.isObject()) {
+            QJsonObject obj = doc.object();
+            task.task_id = obj[QStringLiteral("task_id")].toString();
+            task.task_name = obj[QStringLiteral("task_name")].toString();
+            task.is_enabled = obj[QStringLiteral("is_enabled")].toBool();
+            task.transport_type = static_cast<TransportType>(obj[QStringLiteral("transport_type")].toInt());
+            task.protocol_type = static_cast<ProtocolType>(obj[QStringLiteral("protocol_type")].toInt());
+            task.device_bind = obj[QStringLiteral("device_bind")].toString();
+            task.trigger_mode = static_cast<TriggerMode>(obj[QStringLiteral("trigger_mode")].toInt());
+            task.params_json = obj[QStringLiteral("params_json")].toObject();
+            task.status = static_cast<TaskStatus>(obj[QStringLiteral("status")].toInt());
+            QString createdStr = obj[QStringLiteral("created_at")].toString();
+            if (!createdStr.isEmpty()) {
+                task.created_at = QDateTime::fromString(createdStr, Qt::ISODate);
+            }
+            QString updatedStr = obj[QStringLiteral("updated_at")].toString();
+            if (!updatedStr.isEmpty()) {
+                task.updated_at = QDateTime::fromString(updatedStr, Qt::ISODate);
+            }
+            QString lastCommStr = obj[QStringLiteral("last_comm_time")].toString();
+            if (!lastCommStr.isEmpty()) {
+                task.last_comm_time = QDateTime::fromString(lastCommStr, Qt::ISODate);
+            }
+        }
+        return task;
+    }
+};
+
+#endif // TRANSFER_TASK_H
+

+ 83 - 6
src/view_device_config/device_tree_widget.cpp

@@ -574,13 +574,90 @@ void DeviceTreeWidget::updateCanDevices()
 
 void DeviceTreeWidget::updateEthernetDevices()
 {
-    // TODO: 实现网口设备发现
-    // 这里可以添加网口设备的发现逻辑
-    // 例如:扫描网络接口、读取已配置的网络设备等
+    LOG_DEBUG() << "开始更新网口设备";
+    
+    if (!m_api) {
+        LOG_WARNING() << "API 为空,无法更新网口设备";
+        return;
+    }
+
+    LOG_DEBUG() << "API 已初始化:" << m_api->isInitialized();
+
+    // 从API获取所有可用的网络接口
+    LOG_DEBUG() << "调用 m_api->getAvailableNetworkInterfaces()";
+    QStringList availableInterfaces = m_api->getAvailableNetworkInterfaces();
+    LOG_INFO() << "找到" << availableInterfaces.size() << "个网络接口";
+    
+    if (availableInterfaces.isEmpty()) {
+        LOG_WARNING() << "未找到任何网络接口";
+    } else {
+        LOG_DEBUG() << "网络接口列表:" << availableInterfaces.join(", ");
+    }
+    
+    // 获取所有已注册的设备信息,用于判断在线状态和显示IP地址
+    LOG_DEBUG() << "调用 m_api->getAllDevices()";
+    QList<DeviceInfo> allDevices = m_api->getAllDevices();
+    LOG_DEBUG() << "已注册设备数:" << allDevices.size();
+    
+    QMap<QString, DeviceInfo> deviceMap;
+    for (const DeviceInfo &device : allDevices) {
+        // 只处理以太网设备
+        if (device.type == "ethernet" && !device.portname.isEmpty()) {
+            deviceMap[device.portname] = device;
+            LOG_DEBUG() << "已注册网口设备: portname=" << device.portname 
+                        << ", name=" << device.name
+                        << ", status=" << device.status << ", isActive=" << device.isActive;
+        }
+    }
+    
+    int addedCount = 0;
+    foreach (const QString &interfaceName, availableInterfaces)
+    {
+        QString displayName = interfaceName;
+        
+        // 如果设备已注册,尝试获取更友好的显示名称和IP地址
+        if (deviceMap.contains(interfaceName)) {
+            const DeviceInfo &device = deviceMap[interfaceName];
+            if (!device.name.isEmpty() && device.name != interfaceName) {
+                displayName = device.name;
+            }
+            
+            // 尝试从properties中获取IP地址
+            if (device.properties.contains("ipv4Address")) {
+                QString ip = device.properties["ipv4Address"].toString();
+                if (!ip.isEmpty()) {
+                    displayName += QString(" (%1)").arg(ip);
+                }
+            }
+        }
+        
+        QStandardItem *item = createDeviceItem("ethernet", interfaceName, displayName);
+        
+        // 根据设备状态设置颜色
+        if (deviceMap.contains(interfaceName)) {
+            const DeviceInfo &device = deviceMap[interfaceName];
+            bool isOnline = device.status == "online" || (device.status.isEmpty() && device.isActive);
+            
+            if (isOnline) {
+                // 在线设备:绿色
+                item->setForeground(QBrush(QColor(0, 150, 0)));
+                LOG_DEBUG() << "添加在线网口设备:" << interfaceName;
+            } else {
+                // 离线设备:灰色
+                item->setForeground(QBrush(QColor(128, 128, 128)));
+                LOG_DEBUG() << "添加离线网口设备:" << interfaceName;
+            }
+        } else {
+            // 未注册的设备:默认颜色(黑色)
+            item->setForeground(QBrush(QColor(0, 0, 0)));
+            LOG_DEBUG() << "添加未注册网口设备:" << interfaceName;
+        }
+        
+        m_ethernetNode->appendRow(item);
+        addedCount++;
+    }
     
-    // 示例:添加一个占位设备(实际应该从网络管理器获取)
-    // QStandardItem *item = createDeviceItem("ethernet", "eth0", "192.168.1.100:502");
-    // m_ethernetNode->appendRow(item);
+    LOG_INFO() << "完成,共添加" << addedCount << "个网口设备到树";
 }
 
 QStandardItem* DeviceTreeWidget::createDeviceItem(const QString &deviceType, const QString &deviceId, const QString &displayName)

+ 154 - 0
src/view_network/network_settings_widget.cpp

@@ -8,21 +8,37 @@
 #include <QRegularExpression>
 #include <QNetworkInterface>
 #include <QAbstractSocket>
+#include <QProcess>
+#include <QRegularExpressionMatch>
 
 NetworkSettingsWidget::NetworkSettingsWidget(QWidget *parent)
     : QWidget(parent)
     , ui(new Ui::NetworkSettingsWidget)
     , m_api(nullptr)
     , m_currentInterface("")
+    , m_pingProcess(nullptr)
 {
     ui->setupUi(this);
     
+    // 创建 ping 进程 (todo: 需要改成可以选择目标电脑,分布式配置)
+    m_pingProcess = new QProcess(this);
+    connect(m_pingProcess, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+            this, &NetworkSettingsWidget::onPingFinished);
+    connect(m_pingProcess, &QProcess::readyReadStandardOutput,
+            this, &NetworkSettingsWidget::onPingOutputReady);
+    connect(m_pingProcess, &QProcess::readyReadStandardError,
+            this, &NetworkSettingsWidget::onPingOutputReady);
+    
     // 连接信号槽
     connect(ui->btnApply, &QPushButton::clicked, this, &NetworkSettingsWidget::onApplyConfig);
     connect(ui->btnReset, &QPushButton::clicked, this, &NetworkSettingsWidget::onResetToDefaults);
     connect(ui->btnRefresh, &QPushButton::clicked, this, &NetworkSettingsWidget::onRefreshInterfaces);
     connect(ui->comboInterface, QOverload<int>::of(&QComboBox::currentIndexChanged),
             this, &NetworkSettingsWidget::onInterfaceChanged);
+    connect(ui->btnPing, &QPushButton::clicked, this, &NetworkSettingsWidget::onPingClicked);
+    
+    // 初始化ping结果显示
+    ui->labelPingResult->setText("等待测试...");
     
     // 刷新接口列表
     onRefreshInterfaces();
@@ -268,3 +284,141 @@ bool NetworkSettingsWidget::validatePort(int port) const
     return port > 0 && port <= 65535;
 }
 
+void NetworkSettingsWidget::onPingClicked()
+{
+    QString address = ui->lineEditPingAddress->text().trimmed();
+    
+    if (address.isEmpty()) {
+        QMessageBox::warning(this, "错误", "请输入要测试的目标地址");
+        return;
+    }
+    
+    // 如果ping正在进行,先停止
+    if (m_pingProcess->state() == QProcess::Running) {
+        m_pingProcess->kill();
+        m_pingProcess->waitForFinished(1000);
+    }
+    
+    // 清空之前的输出
+    m_pingOutput.clear();
+    ui->labelPingResult->setText("正在测试...");
+    ui->btnPing->setEnabled(false);
+    
+    // 准备ping命令
+    // Linux使用ping -c 4(发送4个包),Windows使用ping -n 4
+    QStringList arguments;
+#ifdef Q_OS_WIN
+    arguments << "-n" << "4" << address;
+#else
+    arguments << "-c" << "4" << address;
+#endif
+    
+    // 启动ping进程
+    m_pingProcess->start("ping", arguments);
+    
+    if (!m_pingProcess->waitForStarted(3000)) {
+        ui->labelPingResult->setText("错误: 无法启动ping命令");
+        ui->btnPing->setEnabled(true);
+        LOG_ERROR() << "Failed to start ping process";
+    }
+}
+
+void NetworkSettingsWidget::onPingFinished(int exitCode, QProcess::ExitStatus exitStatus)
+{
+    ui->btnPing->setEnabled(true);
+    
+    QString resultText;
+    bool success = false;
+    double avgTime = -1.0;
+    int packetsSent = 0;
+    int packetsReceived = 0;
+    
+    // 解析ping输出
+    QString output = m_pingOutput;
+    
+    if (exitStatus == QProcess::CrashExit) {
+        resultText = "错误: Ping进程异常退出";
+    } else if (exitCode == 0) {
+        // Ping成功
+        success = true;
+        
+        // 尝试解析延迟时间(Linux格式)
+        // 例如: rtt min/avg/max/mdev = 0.123/0.456/0.789/0.123 ms
+        QRegularExpression linuxRttRegex(QStringLiteral("rtt min/avg/max/mdev = [\\d.]+/([\\d.]+)/[\\d.]+/[\\d.]+ ms"));
+        QRegularExpressionMatch linuxMatch = linuxRttRegex.match(output);
+        if (linuxMatch.hasMatch()) {
+            avgTime = linuxMatch.captured(1).toDouble();
+        }
+        
+        // Windows格式: 平均 = 123ms
+        QRegularExpression winAvgRegex(QStringLiteral("平均 = ([\\d]+)ms"));
+        QRegularExpressionMatch winMatch = winAvgRegex.match(output);
+        if (winMatch.hasMatch()) {
+            avgTime = winMatch.captured(1).toDouble();
+        }
+        
+        // 解析包统计(Linux格式)
+        // 例如: 4 packets transmitted, 4 received, 0% packet loss
+        QRegularExpression packetRegex(QStringLiteral("(\\d+) packets transmitted, (\\d+) received"));
+        QRegularExpressionMatch packetMatch = packetRegex.match(output);
+        if (packetMatch.hasMatch()) {
+            packetsSent = packetMatch.captured(1).toInt();
+            packetsReceived = packetMatch.captured(2).toInt();
+        }
+        
+        // Windows格式: 已发送 = 4,已接收 = 4
+        QRegularExpression winPacketRegex(QStringLiteral("已发送 = (\\d+),已接收 = (\\d+)"));
+        QRegularExpressionMatch winPacketMatch = winPacketRegex.match(output);
+        if (winPacketMatch.hasMatch()) {
+            packetsSent = winPacketMatch.captured(1).toInt();
+            packetsReceived = winPacketMatch.captured(2).toInt();
+        }
+        
+        resultText = QString("✓ 连通成功\n");
+        if (avgTime >= 0) {
+            resultText += QString("平均延迟: %1 ms\n").arg(QString::number(avgTime, 'f', 2));
+        }
+        if (packetsSent > 0) {
+            resultText += QString("发送: %1, 接收: %2\n").arg(packetsSent).arg(packetsReceived);
+            int loss = ((packetsSent - packetsReceived) * 100) / packetsSent;
+            resultText += QString("丢包率: %1%").arg(loss);
+        }
+        
+        ui->labelPingResult->setStyleSheet(
+            "QLabel { background-color: #d4edda; border: 1px solid #c3e6cb; border-radius: 3px; padding: 5px; color: #155724; }"
+        );
+    } else {
+        // Ping失败
+        resultText = "✗ 连通失败\n";
+        resultText += "无法到达目标地址";
+        
+        // 尝试提取错误信息
+        QRegularExpression errorRegex(QStringLiteral("(无法|unreachable|timeout|timed out|请求超时)"), QRegularExpression::CaseInsensitiveOption);
+        QRegularExpressionMatch errorMatch = errorRegex.match(output);
+        if (errorMatch.hasMatch()) {
+            resultText += "\n" + errorMatch.captured(0);
+        }
+        
+        ui->labelPingResult->setStyleSheet(
+            "QLabel { background-color: #f8d7da; border: 1px solid #f5c6cb; border-radius: 3px; padding: 5px; color: #721c24; }"
+        );
+    }
+    
+    ui->labelPingResult->setText(resultText);
+    LOG_INFO() << "Ping finished: exitCode=" << exitCode << ", success=" << success;
+}
+
+void NetworkSettingsWidget::onPingOutputReady()
+{
+    // 读取标准输出和标准错误
+    QByteArray output = m_pingProcess->readAllStandardOutput();
+    QByteArray error = m_pingProcess->readAllStandardError();
+    
+    if (!output.isEmpty()) {
+        m_pingOutput += QString::fromLocal8Bit(output);
+    }
+    if (!error.isEmpty()) {
+        m_pingOutput += QString::fromLocal8Bit(error);
+    }
+}
+

+ 9 - 0
src/view_network/network_settings_widget.h

@@ -12,6 +12,7 @@
 #define NETWORK_SETTINGS_WIDGET_H
 
 #include <QWidget>
+#include <QProcess>
 #include "manage_network/network_manager.h"
 
 class SoftBusAPI;
@@ -61,6 +62,12 @@ private slots:
     void onRefreshInterfaces();
     // 接口选择改变
     void onInterfaceChanged(int index);
+    // Ping测试
+    void onPingClicked();
+    // Ping完成
+    void onPingFinished(int exitCode, QProcess::ExitStatus exitStatus);
+    // Ping输出读取
+    void onPingOutputReady();
 
 private:
     // 更新接口信息显示
@@ -74,6 +81,8 @@ private:
     Ui::NetworkSettingsWidget *ui;
     SoftBusAPI *m_api;
     QString m_currentInterface;
+    QProcess *m_pingProcess;
+    QString m_pingOutput;
 };
 
 #endif // NETWORK_SETTINGS_WIDGET_H

+ 52 - 0
src/view_network/network_settings_widget.ui

@@ -14,6 +14,58 @@
    <string>网络设置</string>
   </property>
   <layout class="QVBoxLayout" name="verticalLayout">
+   <item>
+    <widget class="QGroupBox" name="groupBoxPing">
+     <property name="title">
+      <string>网络连通性测试</string>
+     </property>
+     <layout class="QVBoxLayout" name="verticalLayout_Ping">
+      <item>
+       <layout class="QHBoxLayout" name="horizontalLayout_Ping">
+        <item>
+         <widget class="QLabel" name="labelPingAddress">
+          <property name="text">
+           <string>目标地址:</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QLineEdit" name="lineEditPingAddress">
+          <property name="placeholderText">
+           <string>例如: 192.168.1.1 或 www.baidu.com</string>
+          </property>
+         </widget>
+        </item>
+        <item>
+         <widget class="QPushButton" name="btnPing">
+          <property name="text">
+           <string>Ping</string>
+          </property>
+         </widget>
+        </item>
+       </layout>
+      </item>
+      <item>
+       <widget class="QLabel" name="labelPingResult">
+        <property name="text">
+         <string>等待测试...</string>
+        </property>
+        <property name="wordWrap">
+         <bool>true</bool>
+        </property>
+        <property name="styleSheet">
+         <string>QLabel {
+    background-color: #f0f0f0;
+    border: 1px solid #ccc;
+    border-radius: 3px;
+    padding: 5px;
+}</string>
+        </property>
+       </widget>
+      </item>
+     </layout>
+    </widget>
+   </item>
    <item>
     <widget class="QGroupBox" name="groupBoxInterface">
      <property name="title">

+ 580 - 0
src/view_task/TaskConfigWidget.cpp

@@ -0,0 +1,580 @@
+#include "TaskConfigWidget.h"
+#include "api/SoftBusAPI.h"
+#include "utils/logging.h"
+#include <QFormLayout>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QLabel>
+#include <QMap>
+#include <QLineEdit>
+#include <QCheckBox>
+#include <QComboBox>
+#include <QSpinBox>
+#include <QDoubleSpinBox>
+#include <QTextEdit>
+#include <QGroupBox>
+#include <QDateTime>
+
+TaskConfigWidget::TaskConfigWidget(QWidget *parent)
+    : QWidget(parent)
+    , m_taskIdEdit(nullptr)
+    , m_taskNameEdit(nullptr)
+    , m_enabledCheckBox(nullptr)
+    , m_transportTypeCombo(nullptr)
+    , m_protocolTypeCombo(nullptr)
+    , m_deviceBindCombo(nullptr)
+    , m_triggerModeCombo(nullptr)
+    , m_parameterGroup(nullptr)
+    , m_parameterLayout(nullptr)
+    , m_statusLabel(nullptr)
+    , m_lastCommTimeLabel(nullptr)
+{
+    createUI();
+}
+
+TaskConfigWidget::~TaskConfigWidget() = default;
+
+void TaskConfigWidget::createUI()
+{
+    QVBoxLayout *mainLayout = new QVBoxLayout(this);
+
+    // 基本信息组
+    QGroupBox *basicGroup = new QGroupBox(tr("基本信息"), this);
+    QFormLayout *basicLayout = new QFormLayout(basicGroup);
+    
+    m_taskIdEdit = new QLineEdit(this);
+    m_taskIdEdit->setPlaceholderText(tr("自动生成UUID"));
+    basicLayout->addRow(tr("任务ID:"), m_taskIdEdit);
+    
+    m_taskNameEdit = new QLineEdit(this);
+    m_taskNameEdit->setPlaceholderText(tr("输入任务名称"));
+    basicLayout->addRow(tr("任务名称:"), m_taskNameEdit);
+    
+    m_enabledCheckBox = new QCheckBox(tr("启用任务"), this);
+    basicLayout->addRow(tr(""), m_enabledCheckBox);
+    
+    basicGroup->setLayout(basicLayout);
+    mainLayout->addWidget(basicGroup);
+
+    // 传输配置组
+    QGroupBox *transportGroup = new QGroupBox(tr("传输配置"), this);
+    QFormLayout *transportLayout = new QFormLayout(transportGroup);
+    
+    m_transportTypeCombo = new QComboBox(this);
+    m_transportTypeCombo->addItem(tr("串口"), static_cast<int>(TransportType::Serial));
+    m_transportTypeCombo->addItem(tr("TCP服务器"), static_cast<int>(TransportType::TCP_Server));
+    m_transportTypeCombo->addItem(tr("TCP客户端"), static_cast<int>(TransportType::TCP_Client));
+    m_transportTypeCombo->addItem(tr("UDP服务器"), static_cast<int>(TransportType::UDP_Server));
+    m_transportTypeCombo->addItem(tr("UDP客户端"), static_cast<int>(TransportType::UDP_Client));
+    connect(m_transportTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+            this, &TaskConfigWidget::onTransportTypeChanged);
+    transportLayout->addRow(tr("传输类型:"), m_transportTypeCombo);
+    
+    m_protocolTypeCombo = new QComboBox(this);
+    m_protocolTypeCombo->addItem(tr("Modbus RTU"), static_cast<int>(ProtocolType::Modbus_RTU));
+    m_protocolTypeCombo->addItem(tr("Modbus TCP"), static_cast<int>(ProtocolType::Modbus_TCP));
+    m_protocolTypeCombo->addItem(tr("CAN标准帧"), static_cast<int>(ProtocolType::CAN_Standard));
+    m_protocolTypeCombo->addItem(tr("原始数据"), static_cast<int>(ProtocolType::Raw_Data));
+    connect(m_protocolTypeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+            this, &TaskConfigWidget::onProtocolTypeChanged);
+    transportLayout->addRow(tr("协议类型:"), m_protocolTypeCombo);
+    
+    m_deviceBindCombo = new QComboBox(this);
+    m_deviceBindCombo->setEditable(true);
+    m_deviceBindCombo->setPlaceholderText(tr("选择或输入设备ID"));
+    transportLayout->addRow(tr("绑定设备:"), m_deviceBindCombo);
+    
+    m_triggerModeCombo = new QComboBox(this);
+    m_triggerModeCombo->addItem(tr("轮询"), static_cast<int>(TriggerMode::Polling));
+    m_triggerModeCombo->addItem(tr("监听"), static_cast<int>(TriggerMode::Event));
+    connect(m_triggerModeCombo, QOverload<int>::of(&QComboBox::currentIndexChanged),
+            this, &TaskConfigWidget::onTriggerModeChanged);
+    transportLayout->addRow(tr("触发模式:"), m_triggerModeCombo);
+    
+    transportGroup->setLayout(transportLayout);
+    mainLayout->addWidget(transportGroup);
+
+    // 参数配置组(动态显示)
+    m_parameterGroup = new QGroupBox(tr("参数配置"), this);
+    m_parameterLayout = new QFormLayout(m_parameterGroup);
+    m_parameterGroup->setLayout(m_parameterLayout);
+    mainLayout->addWidget(m_parameterGroup);
+
+    // 状态信息组
+    QGroupBox *statusGroup = new QGroupBox(tr("状态信息"), this);
+    QFormLayout *statusLayout = new QFormLayout(statusGroup);
+    
+    m_statusLabel = new QLabel(tr("已停止"), this);
+    statusLayout->addRow(tr("状态:"), m_statusLabel);
+    
+    m_lastCommTimeLabel = new QLabel(tr("无"), this);
+    statusLayout->addRow(tr("最后通信时间:"), m_lastCommTimeLabel);
+    
+    statusGroup->setLayout(statusLayout);
+    mainLayout->addWidget(statusGroup);
+
+    mainLayout->addStretch();
+    setLayout(mainLayout);
+
+    // 初始化参数控件
+    createParameterWidgets();
+    updateParameterWidgetsVisibility();
+
+    // 刷新设备列表
+    refreshDeviceList();
+}
+
+void TaskConfigWidget::createParameterWidgets()
+{
+    // Modbus RTU/TCP 参数
+    QSpinBox *slaveIdSpin = new QSpinBox(this);
+    slaveIdSpin->setRange(1, 247);
+    slaveIdSpin->setValue(1);
+    m_parameterWidgets["modbus_slave_id"] = slaveIdSpin;
+
+    QSpinBox *startAddrSpin = new QSpinBox(this);
+    startAddrSpin->setRange(0, 65535);
+    startAddrSpin->setValue(0);
+    m_parameterWidgets["modbus_start_addr"] = startAddrSpin;
+
+    QSpinBox *quantitySpin = new QSpinBox(this);
+    quantitySpin->setRange(1, 125);
+    quantitySpin->setValue(10);
+    m_parameterWidgets["modbus_quantity"] = quantitySpin;
+
+    QComboBox *functionCodeCombo = new QComboBox(this);
+    functionCodeCombo->addItem(tr("读取保持寄存器 (03)"), 3);
+    functionCodeCombo->addItem(tr("读取输入寄存器 (04)"), 4);
+    functionCodeCombo->addItem(tr("读取线圈状态 (01)"), 1);
+    functionCodeCombo->addItem(tr("读取输入状态 (02)"), 2);
+    m_parameterWidgets["modbus_function_code"] = functionCodeCombo;
+
+    // 轮询间隔(毫秒)
+    QSpinBox *pollIntervalSpin = new QSpinBox(this);
+    pollIntervalSpin->setRange(100, 60000);
+    pollIntervalSpin->setValue(1000);
+    pollIntervalSpin->setSuffix(tr(" ms"));
+    m_parameterWidgets["poll_interval"] = pollIntervalSpin;
+
+    // TCP/UDP 端口
+    QSpinBox *portSpin = new QSpinBox(this);
+    portSpin->setRange(1, 65535);
+    portSpin->setValue(502);
+    m_parameterWidgets["port"] = portSpin;
+
+    // TCP/UDP 地址
+    QLineEdit *addressEdit = new QLineEdit(this);
+    addressEdit->setPlaceholderText(tr("127.0.0.1"));
+    addressEdit->setText(tr("127.0.0.1"));
+    m_parameterWidgets["address"] = addressEdit;
+
+    // 超时时间(毫秒)
+    QSpinBox *timeoutSpin = new QSpinBox(this);
+    timeoutSpin->setRange(100, 30000);
+    timeoutSpin->setValue(1000);
+    timeoutSpin->setSuffix(tr(" ms"));
+    m_parameterWidgets["timeout"] = timeoutSpin;
+}
+
+void TaskConfigWidget::updateParameterWidgetsVisibility()
+{
+    // 清除所有控件
+    QLayoutItem *item;
+    while ((item = m_parameterLayout->takeAt(0)) != nullptr) {
+        if (item->widget()) {
+            item->widget()->hide();
+        }
+        delete item;
+    }
+
+    if (!m_protocolTypeCombo || !m_transportTypeCombo || !m_triggerModeCombo) {
+        return;
+    }
+
+    ProtocolType protocolType = static_cast<ProtocolType>(
+        m_protocolTypeCombo->currentData().toInt());
+    TransportType transportType = static_cast<TransportType>(
+        m_transportTypeCombo->currentData().toInt());
+    TriggerMode triggerMode = static_cast<TriggerMode>(
+        m_triggerModeCombo->currentData().toInt());
+
+    // Modbus 参数
+    if (protocolType == ProtocolType::Modbus_RTU || protocolType == ProtocolType::Modbus_TCP) {
+        if (m_parameterWidgets.contains("modbus_slave_id")) {
+            m_parameterLayout->addRow(tr("从站地址:"), m_parameterWidgets["modbus_slave_id"]);
+            m_parameterWidgets["modbus_slave_id"]->show();
+        }
+        if (triggerMode == TriggerMode::Polling) {
+            if (m_parameterWidgets.contains("modbus_function_code")) {
+                m_parameterLayout->addRow(tr("功能码:"), m_parameterWidgets["modbus_function_code"]);
+                m_parameterWidgets["modbus_function_code"]->show();
+            }
+            if (m_parameterWidgets.contains("modbus_start_addr")) {
+                m_parameterLayout->addRow(tr("起始地址:"), m_parameterWidgets["modbus_start_addr"]);
+                m_parameterWidgets["modbus_start_addr"]->show();
+            }
+            if (m_parameterWidgets.contains("modbus_quantity")) {
+                m_parameterLayout->addRow(tr("数量:"), m_parameterWidgets["modbus_quantity"]);
+                m_parameterWidgets["modbus_quantity"]->show();
+            }
+        }
+    }
+
+    // 轮询间隔(轮询模式)
+    if (triggerMode == TriggerMode::Polling) {
+        if (m_parameterWidgets.contains("poll_interval")) {
+            m_parameterLayout->addRow(tr("轮询间隔:"), m_parameterWidgets["poll_interval"]);
+            m_parameterWidgets["poll_interval"]->show();
+        }
+    }
+
+    // 网络参数(TCP/UDP)
+    if (transportType == TransportType::TCP_Server || transportType == TransportType::TCP_Client ||
+        transportType == TransportType::UDP_Server || transportType == TransportType::UDP_Client) {
+        if (transportType == TransportType::TCP_Server || transportType == TransportType::UDP_Server) {
+            if (m_parameterWidgets.contains("port")) {
+                m_parameterLayout->addRow(tr("监听端口:"), m_parameterWidgets["port"]);
+                m_parameterWidgets["port"]->show();
+            }
+        } else {
+            if (m_parameterWidgets.contains("address")) {
+                m_parameterLayout->addRow(tr("服务器地址:"), m_parameterWidgets["address"]);
+                m_parameterWidgets["address"]->show();
+            }
+            if (m_parameterWidgets.contains("port")) {
+                m_parameterLayout->addRow(tr("服务器端口:"), m_parameterWidgets["port"]);
+                m_parameterWidgets["port"]->show();
+            }
+        }
+    }
+
+    // 超时时间
+    if (m_parameterWidgets.contains("timeout")) {
+        m_parameterLayout->addRow(tr("超时时间:"), m_parameterWidgets["timeout"]);
+        m_parameterWidgets["timeout"]->show();
+    }
+}
+
+void TaskConfigWidget::refreshDeviceList()
+{
+    if (!m_deviceBindCombo) {
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        return;
+    }
+
+    m_deviceBindCombo->clear();
+    QList<DeviceInfo> devices = api->getAllDevices();
+    for (const DeviceInfo &device : devices) {
+        QString displayText = QString("%1 (%2)").arg(device.portname).arg(device.type);
+        m_deviceBindCombo->addItem(displayText, device.portname);
+    }
+}
+
+void TaskConfigWidget::loadTask(const TransferTask &task)
+{
+    if (m_taskIdEdit) {
+        m_taskIdEdit->setText(task.task_id);
+    }
+    if (m_taskNameEdit) {
+        m_taskNameEdit->setText(task.task_name);
+    }
+    if (m_enabledCheckBox) {
+        m_enabledCheckBox->setChecked(task.is_enabled);
+    }
+    if (m_transportTypeCombo) {
+        int index = m_transportTypeCombo->findData(static_cast<int>(task.transport_type));
+        if (index >= 0) {
+            m_transportTypeCombo->setCurrentIndex(index);
+        }
+    }
+    if (m_protocolTypeCombo) {
+        int index = m_protocolTypeCombo->findData(static_cast<int>(task.protocol_type));
+        if (index >= 0) {
+            m_protocolTypeCombo->setCurrentIndex(index);
+        }
+    }
+    if (m_deviceBindCombo) {
+        int index = m_deviceBindCombo->findData(task.device_bind);
+        if (index >= 0) {
+            m_deviceBindCombo->setCurrentIndex(index);
+        } else {
+            m_deviceBindCombo->setCurrentText(task.device_bind);
+        }
+    }
+    if (m_triggerModeCombo) {
+        int index = m_triggerModeCombo->findData(static_cast<int>(task.trigger_mode));
+        if (index >= 0) {
+            m_triggerModeCombo->setCurrentIndex(index);
+        }
+    }
+
+    // 加载参数
+    QJsonObject params = task.params_json;
+    if (m_parameterWidgets.contains("modbus_slave_id") && params.contains("modbus_slave_id")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_slave_id"]);
+        if (spin) {
+            spin->setValue(params["modbus_slave_id"].toInt());
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_function_code") && params.contains("modbus_function_code")) {
+        QComboBox *combo = qobject_cast<QComboBox*>(m_parameterWidgets["modbus_function_code"]);
+        if (combo) {
+            int index = combo->findData(params["modbus_function_code"].toInt());
+            if (index >= 0) {
+                combo->setCurrentIndex(index);
+            }
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_start_addr") && params.contains("modbus_start_addr")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_start_addr"]);
+        if (spin) {
+            spin->setValue(params["modbus_start_addr"].toInt());
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_quantity") && params.contains("modbus_quantity")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_quantity"]);
+        if (spin) {
+            spin->setValue(params["modbus_quantity"].toInt());
+        }
+    }
+    if (m_parameterWidgets.contains("poll_interval") && params.contains("poll_interval")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["poll_interval"]);
+        if (spin) {
+            spin->setValue(params["poll_interval"].toInt());
+        }
+    }
+    if (m_parameterWidgets.contains("port") && params.contains("port")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["port"]);
+        if (spin) {
+            spin->setValue(params["port"].toInt());
+        }
+    }
+    if (m_parameterWidgets.contains("address") && params.contains("address")) {
+        QLineEdit *edit = qobject_cast<QLineEdit*>(m_parameterWidgets["address"]);
+        if (edit) {
+            edit->setText(params["address"].toString());
+        }
+    }
+    if (m_parameterWidgets.contains("timeout") && params.contains("timeout")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["timeout"]);
+        if (spin) {
+            spin->setValue(params["timeout"].toInt());
+        }
+    }
+
+    // 更新状态显示
+    if (m_statusLabel) {
+        QString statusText;
+        switch (task.status) {
+        case TaskStatus::Stopped:
+            statusText = tr("已停止");
+            break;
+        case TaskStatus::Running:
+            statusText = tr("运行中");
+            break;
+        case TaskStatus::Error:
+            statusText = tr("错误");
+            break;
+        case TaskStatus::Paused:
+            statusText = tr("已暂停");
+            break;
+        case TaskStatus::Waiting:
+            statusText = tr("等待中");
+            break;
+        }
+        m_statusLabel->setText(statusText);
+    }
+    if (m_lastCommTimeLabel) {
+        if (task.last_comm_time.isValid()) {
+            m_lastCommTimeLabel->setText(task.last_comm_time.toString(Qt::ISODate));
+        } else {
+            m_lastCommTimeLabel->setText(tr("无"));
+        }
+    }
+
+    updateParameterWidgetsVisibility();
+    emit configChanged();
+}
+
+TransferTask TaskConfigWidget::getTask() const
+{
+    TransferTask task;
+
+    if (m_taskIdEdit) {
+        task.task_id = m_taskIdEdit->text().trimmed();
+    }
+    if (m_taskNameEdit) {
+        task.task_name = m_taskNameEdit->text().trimmed();
+    }
+    if (m_enabledCheckBox) {
+        task.is_enabled = m_enabledCheckBox->isChecked();
+    }
+    if (m_transportTypeCombo) {
+        task.transport_type = static_cast<TransportType>(m_transportTypeCombo->currentData().toInt());
+    }
+    if (m_protocolTypeCombo) {
+        task.protocol_type = static_cast<ProtocolType>(m_protocolTypeCombo->currentData().toInt());
+    }
+    if (m_deviceBindCombo) {
+        task.device_bind = m_deviceBindCombo->currentData().toString();
+        if (task.device_bind.isEmpty()) {
+            task.device_bind = m_deviceBindCombo->currentText().trimmed();
+        }
+    }
+    if (m_triggerModeCombo) {
+        task.trigger_mode = static_cast<TriggerMode>(m_triggerModeCombo->currentData().toInt());
+    }
+
+    // 收集参数
+    QJsonObject params;
+    if (m_parameterWidgets.contains("modbus_slave_id")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_slave_id"]);
+        if (spin && spin->isVisible()) {
+            params["modbus_slave_id"] = spin->value();
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_function_code")) {
+        QComboBox *combo = qobject_cast<QComboBox*>(m_parameterWidgets["modbus_function_code"]);
+        if (combo && combo->isVisible()) {
+            params["modbus_function_code"] = combo->currentData().toInt();
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_start_addr")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_start_addr"]);
+        if (spin && spin->isVisible()) {
+            params["modbus_start_addr"] = spin->value();
+        }
+    }
+    if (m_parameterWidgets.contains("modbus_quantity")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["modbus_quantity"]);
+        if (spin && spin->isVisible()) {
+            params["modbus_quantity"] = spin->value();
+        }
+    }
+    if (m_parameterWidgets.contains("poll_interval")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["poll_interval"]);
+        if (spin && spin->isVisible()) {
+            params["poll_interval"] = spin->value();
+        }
+    }
+    if (m_parameterWidgets.contains("port")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["port"]);
+        if (spin && spin->isVisible()) {
+            params["port"] = spin->value();
+        }
+    }
+    if (m_parameterWidgets.contains("address")) {
+        QLineEdit *edit = qobject_cast<QLineEdit*>(m_parameterWidgets["address"]);
+        if (edit && edit->isVisible()) {
+            params["address"] = edit->text().trimmed();
+        }
+    }
+    if (m_parameterWidgets.contains("timeout")) {
+        QSpinBox *spin = qobject_cast<QSpinBox*>(m_parameterWidgets["timeout"]);
+        if (spin && spin->isVisible()) {
+            params["timeout"] = spin->value();
+        }
+    }
+    task.params_json = params;
+
+    task.updated_at = QDateTime::currentDateTimeUtc();
+    if (task.task_id.isEmpty()) {
+        task.created_at = QDateTime::currentDateTimeUtc();
+    }
+
+    return task;
+}
+
+void TaskConfigWidget::clear()
+{
+    if (m_taskIdEdit) {
+        m_taskIdEdit->clear();
+    }
+    if (m_taskNameEdit) {
+        m_taskNameEdit->clear();
+    }
+    if (m_enabledCheckBox) {
+        m_enabledCheckBox->setChecked(false);
+    }
+    if (m_transportTypeCombo) {
+        m_transportTypeCombo->setCurrentIndex(0);
+    }
+    if (m_protocolTypeCombo) {
+        m_protocolTypeCombo->setCurrentIndex(0);
+    }
+    if (m_deviceBindCombo) {
+        m_deviceBindCombo->setCurrentIndex(-1);
+    }
+    if (m_triggerModeCombo) {
+        m_triggerModeCombo->setCurrentIndex(0);
+    }
+
+    // 重置参数控件
+    for (auto it = m_parameterWidgets.begin(); it != m_parameterWidgets.end(); ++it) {
+        if (QSpinBox *spin = qobject_cast<QSpinBox*>(it.value())) {
+            spin->setValue(spin->minimum());
+        } else if (QLineEdit *edit = qobject_cast<QLineEdit*>(it.value())) {
+            edit->clear();
+        } else if (QComboBox *combo = qobject_cast<QComboBox*>(it.value())) {
+            combo->setCurrentIndex(0);
+        }
+    }
+
+    if (m_statusLabel) {
+        m_statusLabel->setText(tr("已停止"));
+    }
+    if (m_lastCommTimeLabel) {
+        m_lastCommTimeLabel->setText(tr("无"));
+    }
+
+    updateParameterWidgetsVisibility();
+}
+
+bool TaskConfigWidget::isValid() const
+{
+    if (!m_taskNameEdit || m_taskNameEdit->text().trimmed().isEmpty()) {
+        return false;
+    }
+    if (!m_deviceBindCombo || m_deviceBindCombo->currentText().trimmed().isEmpty()) {
+        return false;
+    }
+    return true;
+}
+
+void TaskConfigWidget::setTaskId(const QString &taskId)
+{
+    if (m_taskIdEdit) {
+        m_taskIdEdit->setText(taskId);
+    }
+}
+
+void TaskConfigWidget::onTransportTypeChanged(int index)
+{
+    Q_UNUSED(index);
+    updateParameterWidgetsVisibility();
+    emit configChanged();
+}
+
+void TaskConfigWidget::onProtocolTypeChanged(int index)
+{
+    Q_UNUSED(index);
+    updateParameterWidgetsVisibility();
+    emit configChanged();
+}
+
+void TaskConfigWidget::onTriggerModeChanged(int index)
+{
+    Q_UNUSED(index);
+    updateParameterWidgetsVisibility();
+    emit configChanged();
+}
+
+void TaskConfigWidget::updateParameterWidgets()
+{
+    updateParameterWidgetsVisibility();
+}
+

+ 101 - 0
src/view_task/TaskConfigWidget.h

@@ -0,0 +1,101 @@
+/**
+ * @file TaskConfigWidget.h
+ * @brief 任务配置组件
+ * 
+ * 用于编辑传输任务的属性配置
+ */
+
+#ifndef TASK_CONFIG_WIDGET_H
+#define TASK_CONFIG_WIDGET_H
+
+#include <QWidget>
+#include <QJsonObject>
+#include "task_manager/TransferTask.h"
+
+class QLineEdit;
+class QCheckBox;
+class QComboBox;
+class QSpinBox;
+class QTextEdit;
+class QGroupBox;
+class QFormLayout;
+class QLabel;
+
+class TaskConfigWidget : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit TaskConfigWidget(QWidget *parent = nullptr);
+    ~TaskConfigWidget() override;
+
+    /**
+     * @brief 加载任务配置
+     * @param task 任务对象
+     */
+    void loadTask(const TransferTask &task);
+
+    /**
+     * @brief 获取当前配置的任务
+     * @return 任务对象
+     */
+    TransferTask getTask() const;
+
+    /**
+     * @brief 清空配置
+     */
+    void clear();
+
+    /**
+     * @brief 检查配置是否有效
+     * @return 有效返回true
+     */
+    bool isValid() const;
+
+    /**
+     * @brief 设置任务ID
+     * @param taskId 任务ID
+     */
+    void setTaskId(const QString &taskId);
+
+signals:
+    /**
+     * @brief 配置变化信号
+     */
+    void configChanged();
+
+private slots:
+    void onTransportTypeChanged(int index);
+    void onProtocolTypeChanged(int index);
+    void onTriggerModeChanged(int index);
+    void updateParameterWidgets();
+
+private:
+    void createUI();
+    void createParameterWidgets();
+    void updateParameterWidgetsVisibility();
+    void refreshDeviceList();
+
+    // 基本信息
+    QLineEdit *m_taskIdEdit;
+    QLineEdit *m_taskNameEdit;
+    QCheckBox *m_enabledCheckBox;
+
+    // 传输配置
+    QComboBox *m_transportTypeCombo;
+    QComboBox *m_protocolTypeCombo;
+    QComboBox *m_deviceBindCombo;
+    QComboBox *m_triggerModeCombo;
+
+    // 参数配置(根据协议类型动态显示)
+    QGroupBox *m_parameterGroup;
+    QFormLayout *m_parameterLayout;
+    QMap<QString, QWidget*> m_parameterWidgets;
+
+    // 状态显示
+    QLabel *m_statusLabel;
+    QLabel *m_lastCommTimeLabel;
+};
+
+#endif // TASK_CONFIG_WIDGET_H
+

+ 557 - 0
src/view_task/TaskManagementPage.cpp

@@ -0,0 +1,557 @@
+#include "TaskManagementPage.h"
+#include "TaskConfigWidget.h"
+#include "api/SoftBusAPI.h"
+#include "utils/logging.h"
+#include <QVBoxLayout>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QTableWidget>
+#include <QTableWidgetItem>
+#include <QSplitter>
+#include <QGroupBox>
+#include <QHeaderView>
+#include <QMessageBox>
+#include <QUuid>
+#include <QDateTime>
+
+TaskManagementPage::TaskManagementPage(QWidget *parent)
+    : QWidget(parent)
+    , m_taskTable(nullptr)
+    , m_configWidget(nullptr)
+    , m_configWrapper(nullptr)
+    , m_splitter(nullptr)
+    , m_newButton(nullptr)
+    , m_deleteButton(nullptr)
+    , m_startButton(nullptr)
+    , m_stopButton(nullptr)
+    , m_pauseButton(nullptr)
+    , m_resumeButton(nullptr)
+    , m_saveButton(nullptr)
+    , m_currentTaskId()
+    , m_isEditing(false)
+{
+    createUI();
+    connectSignals();
+    refreshTaskList();
+}
+
+TaskManagementPage::~TaskManagementPage() = default;
+
+void TaskManagementPage::createUI()
+{
+    QVBoxLayout *mainLayout = new QVBoxLayout(this);
+
+    // 创建工具栏
+    QWidget *toolbar = createToolbar();
+    mainLayout->addWidget(toolbar);
+
+    // 创建分割器
+    m_splitter = new QSplitter(Qt::Horizontal, this);
+    
+    // 创建任务列表
+    createTaskTable();
+    m_splitter->addWidget(m_taskTable);
+    
+    // 创建配置区域
+    createConfigArea();
+    if (m_configWrapper) {
+        m_splitter->addWidget(m_configWrapper);
+    }
+    
+    // 设置分割比例(左侧60%,右侧40%)
+    m_splitter->setStretchFactor(0, 6);
+    m_splitter->setStretchFactor(1, 4);
+    m_splitter->setSizes({600, 400});
+    
+    mainLayout->addWidget(m_splitter);
+    setLayout(mainLayout);
+}
+
+QWidget* TaskManagementPage::createToolbar()
+{
+    QWidget *toolbar = new QWidget(this);
+    QHBoxLayout *layout = new QHBoxLayout(toolbar);
+    layout->setContentsMargins(5, 5, 5, 5);
+
+    m_newButton = new QPushButton(tr("新建"), this);
+    m_newButton->setIcon(QIcon(":/qrc/icons/add.png"));
+    layout->addWidget(m_newButton);
+
+    m_deleteButton = new QPushButton(tr("删除"), this);
+    m_deleteButton->setIcon(QIcon(":/qrc/icons/delete.png"));
+    layout->addWidget(m_deleteButton);
+
+    layout->addSpacing(10);
+
+    m_startButton = new QPushButton(tr("启动"), this);
+    m_startButton->setIcon(QIcon(":/qrc/icons/play.png"));
+    layout->addWidget(m_startButton);
+
+    m_stopButton = new QPushButton(tr("停止"), this);
+    m_stopButton->setIcon(QIcon(":/qrc/icons/stop.png"));
+    layout->addWidget(m_stopButton);
+
+    m_pauseButton = new QPushButton(tr("暂停"), this);
+    m_pauseButton->setIcon(QIcon(":/qrc/icons/pause.png"));
+    layout->addWidget(m_pauseButton);
+
+    m_resumeButton = new QPushButton(tr("恢复"), this);
+    m_resumeButton->setIcon(QIcon(":/qrc/icons/resume.png"));
+    layout->addWidget(m_resumeButton);
+
+    layout->addSpacing(10);
+
+    m_saveButton = new QPushButton(tr("保存"), this);
+    m_saveButton->setIcon(QIcon(":/qrc/icons/save.png"));
+    layout->addWidget(m_saveButton);
+
+    layout->addStretch();
+
+    updateButtonStates();
+    return toolbar;
+}
+
+void TaskManagementPage::createTaskTable()
+{
+    m_taskTable = new QTableWidget(this);
+    m_taskTable->setColumnCount(7);
+    m_taskTable->setHorizontalHeaderLabels({
+        tr("任务ID"),
+        tr("任务名称"),
+        tr("协议"),
+        tr("设备"),
+        tr("状态"),
+        tr("最后通信时间"),
+        tr("启用")
+    });
+    
+    m_taskTable->setSelectionBehavior(QAbstractItemView::SelectRows);
+    m_taskTable->setSelectionMode(QAbstractItemView::SingleSelection);
+    m_taskTable->setEditTriggers(QAbstractItemView::NoEditTriggers);
+    m_taskTable->setAlternatingRowColors(true);
+    m_taskTable->verticalHeader()->setVisible(false);
+    m_taskTable->horizontalHeader()->setStretchLastSection(true);
+    m_taskTable->setColumnWidth(0, 200);
+    m_taskTable->setColumnWidth(1, 150);
+    m_taskTable->setColumnWidth(2, 100);
+    m_taskTable->setColumnWidth(3, 150);
+    m_taskTable->setColumnWidth(4, 80);
+    m_taskTable->setColumnWidth(5, 150);
+    m_taskTable->setColumnWidth(6, 60);
+}
+
+void TaskManagementPage::createConfigArea()
+{
+    QGroupBox *configGroup = new QGroupBox(tr("任务配置"), this);
+    QVBoxLayout *layout = new QVBoxLayout(configGroup);
+    
+    m_configWidget = new TaskConfigWidget(this);
+    layout->addWidget(m_configWidget);
+    
+    configGroup->setLayout(layout);
+    
+    // 将GroupBox包装为widget以便添加到splitter
+    m_configWrapper = new QWidget(this);
+    QVBoxLayout *wrapperLayout = new QVBoxLayout(m_configWrapper);
+    wrapperLayout->setContentsMargins(0, 0, 0, 0);
+    wrapperLayout->addWidget(configGroup);
+    m_configWrapper->setLayout(wrapperLayout);
+}
+
+void TaskManagementPage::connectSignals()
+{
+    connect(m_newButton, &QPushButton::clicked, this, &TaskManagementPage::onNewTask);
+    connect(m_deleteButton, &QPushButton::clicked, this, &TaskManagementPage::onDeleteTask);
+    connect(m_startButton, &QPushButton::clicked, this, &TaskManagementPage::onStartTask);
+    connect(m_stopButton, &QPushButton::clicked, this, &TaskManagementPage::onStopTask);
+    connect(m_pauseButton, &QPushButton::clicked, this, &TaskManagementPage::onPauseTask);
+    connect(m_resumeButton, &QPushButton::clicked, this, &TaskManagementPage::onResumeTask);
+    connect(m_saveButton, &QPushButton::clicked, this, &TaskManagementPage::onSaveTask);
+    
+    connect(m_taskTable, &QTableWidget::cellClicked, this, &TaskManagementPage::onTaskSelected);
+    connect(m_configWidget, &TaskConfigWidget::configChanged, this, &TaskManagementPage::onConfigChanged);
+    
+    // 连接API信号
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (api) {
+        connect(api, &SoftBusAPI::taskStatusChanged, this, &TaskManagementPage::onTaskStatusChanged);
+        connect(api, &SoftBusAPI::taskError, this, &TaskManagementPage::onTaskError);
+    }
+}
+
+void TaskManagementPage::refreshTaskList()
+{
+    if (!m_taskTable) {
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        LOG_WARNING() << "SoftBusAPI not initialized";
+        return;
+    }
+
+    QList<TransferTask> tasks = api->getAllTasks();
+    
+    m_taskTable->setRowCount(tasks.size());
+    
+    for (int i = 0; i < tasks.size(); ++i) {
+        const TransferTask &task = tasks[i];
+        
+        m_taskTable->setItem(i, 0, new QTableWidgetItem(task.task_id));
+        m_taskTable->setItem(i, 1, new QTableWidgetItem(task.task_name));
+        m_taskTable->setItem(i, 2, new QTableWidgetItem(getProtocolTypeText(task.protocol_type)));
+        m_taskTable->setItem(i, 3, new QTableWidgetItem(task.device_bind));
+        m_taskTable->setItem(i, 4, new QTableWidgetItem(getStatusText(task.status)));
+        if (task.last_comm_time.isValid()) {
+            m_taskTable->setItem(i, 5, new QTableWidgetItem(
+                task.last_comm_time.toString(Qt::ISODate)));
+        } else {
+            m_taskTable->setItem(i, 5, new QTableWidgetItem(tr("无")));
+        }
+        m_taskTable->setItem(i, 6, new QTableWidgetItem(task.is_enabled ? tr("是") : tr("否")));
+    }
+    
+    updateButtonStates();
+}
+
+void TaskManagementPage::selectTask(const QString &taskId)
+{
+    if (!m_taskTable) {
+        return;
+    }
+
+    for (int i = 0; i < m_taskTable->rowCount(); ++i) {
+        QTableWidgetItem *item = m_taskTable->item(i, 0);
+        if (item && item->text() == taskId) {
+            m_taskTable->selectRow(i);
+            onTaskSelected(i, 0);
+            break;
+        }
+    }
+}
+
+void TaskManagementPage::onNewTask()
+{
+    m_currentTaskId.clear();
+    m_isEditing = true;
+    m_configWidget->clear();
+    
+    // 生成新的任务ID
+    QString newId = generateTaskId();
+    m_configWidget->setTaskId(newId);
+    
+    updateButtonStates();
+}
+
+void TaskManagementPage::onDeleteTask()
+{
+    if (m_currentTaskId.isEmpty()) {
+        QMessageBox::warning(this, tr("警告"), tr("请先选择要删除的任务"));
+        return;
+    }
+
+    int ret = QMessageBox::question(this, tr("确认删除"), 
+        tr("确定要删除任务 \"%1\" 吗?").arg(m_currentTaskId),
+        QMessageBox::Yes | QMessageBox::No);
+    
+    if (ret != QMessageBox::Yes) {
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    if (api->deleteTask(m_currentTaskId)) {
+        QMessageBox::information(this, tr("成功"), tr("任务已删除"));
+        m_currentTaskId.clear();
+        m_configWidget->clear();
+        refreshTaskList();
+        updateButtonStates();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("删除任务失败"));
+    }
+}
+
+void TaskManagementPage::onStartTask()
+{
+    if (m_currentTaskId.isEmpty()) {
+        QMessageBox::warning(this, tr("警告"), tr("请先选择要启动的任务"));
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    if (api->startTask(m_currentTaskId)) {
+        refreshTaskList();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("启动任务失败"));
+    }
+}
+
+void TaskManagementPage::onStopTask()
+{
+    if (m_currentTaskId.isEmpty()) {
+        QMessageBox::warning(this, tr("警告"), tr("请先选择要停止的任务"));
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    if (api->stopTask(m_currentTaskId)) {
+        refreshTaskList();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("停止任务失败"));
+    }
+}
+
+void TaskManagementPage::onPauseTask()
+{
+    if (m_currentTaskId.isEmpty()) {
+        QMessageBox::warning(this, tr("警告"), tr("请先选择要暂停的任务"));
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    if (api->pauseTask(m_currentTaskId)) {
+        refreshTaskList();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("暂停任务失败"));
+    }
+}
+
+void TaskManagementPage::onResumeTask()
+{
+    if (m_currentTaskId.isEmpty()) {
+        QMessageBox::warning(this, tr("警告"), tr("请先选择要恢复的任务"));
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    if (api->resumeTask(m_currentTaskId)) {
+        refreshTaskList();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("恢复任务失败"));
+    }
+}
+
+void TaskManagementPage::onTaskSelected(int row, int column)
+{
+    Q_UNUSED(column);
+    
+    if (row < 0 || row >= m_taskTable->rowCount()) {
+        return;
+    }
+
+    QTableWidgetItem *idItem = m_taskTable->item(row, 0);
+    if (!idItem) {
+        return;
+    }
+
+    QString taskId = idItem->text();
+    if (taskId == m_currentTaskId) {
+        return;
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        return;
+    }
+
+    TransferTask task = api->getTask(taskId);
+    if (task.task_id.isEmpty()) {
+        return;
+    }
+
+    m_currentTaskId = taskId;
+    m_isEditing = false;
+    loadTaskToConfig(task);
+    updateButtonStates();
+}
+
+void TaskManagementPage::onTaskStatusChanged(const QString &taskId, int status)
+{
+    Q_UNUSED(status);
+    // 刷新任务列表以更新状态显示
+    if (taskId == m_currentTaskId) {
+        refreshTaskList();
+        // 重新加载当前任务
+        SoftBusAPI *api = SoftBusAPI::instance();
+        if (api && api->isInitialized()) {
+            TransferTask task = api->getTask(taskId);
+            if (!task.task_id.isEmpty()) {
+                loadTaskToConfig(task);
+            }
+        }
+    } else {
+        refreshTaskList();
+    }
+    updateButtonStates();
+}
+
+void TaskManagementPage::onTaskError(const QString &taskId, const QString &error)
+{
+    QMessageBox::warning(this, tr("任务错误"), 
+        tr("任务 \"%1\" 发生错误:%2").arg(taskId, error));
+    refreshTaskList();
+}
+
+void TaskManagementPage::onConfigChanged()
+{
+    // 配置变化时更新按钮状态
+    updateButtonStates();
+}
+
+void TaskManagementPage::onSaveTask()
+{
+    if (!m_configWidget->isValid()) {
+        QMessageBox::warning(this, tr("警告"), tr("请填写完整的任务配置"));
+        return;
+    }
+
+    TransferTask task = m_configWidget->getTask();
+    
+    // 如果任务ID为空,生成新的
+    if (task.task_id.isEmpty()) {
+        task.task_id = generateTaskId();
+    }
+
+    SoftBusAPI *api = SoftBusAPI::instance();
+    if (!api || !api->isInitialized()) {
+        QMessageBox::critical(this, tr("错误"), tr("API未初始化"));
+        return;
+    }
+
+    bool success = false;
+    if (m_currentTaskId.isEmpty() || m_currentTaskId != task.task_id) {
+        // 新建任务
+        success = api->createTask(task);
+        if (success) {
+            QMessageBox::information(this, tr("成功"), tr("任务已创建"));
+        }
+    } else {
+        // 更新任务
+        success = api->updateTask(m_currentTaskId, task);
+        if (success) {
+            QMessageBox::information(this, tr("成功"), tr("任务已更新"));
+        }
+    }
+
+    if (success) {
+        m_currentTaskId = task.task_id;
+        m_isEditing = false;
+        refreshTaskList();
+        selectTask(task.task_id);
+        updateButtonStates();
+    } else {
+        QMessageBox::critical(this, tr("错误"), tr("保存任务失败"));
+    }
+}
+
+void TaskManagementPage::updateButtonStates()
+{
+    bool hasSelection = !m_currentTaskId.isEmpty();
+    bool isEditing = m_isEditing || (hasSelection && m_configWidget && m_configWidget->isValid());
+
+    if (m_deleteButton) {
+        m_deleteButton->setEnabled(hasSelection && !m_isEditing);
+    }
+    if (m_startButton) {
+        m_startButton->setEnabled(hasSelection && !m_isEditing);
+    }
+    if (m_stopButton) {
+        m_stopButton->setEnabled(hasSelection && !m_isEditing);
+    }
+    if (m_pauseButton) {
+        m_pauseButton->setEnabled(hasSelection && !m_isEditing);
+    }
+    if (m_resumeButton) {
+        m_resumeButton->setEnabled(hasSelection && !m_isEditing);
+    }
+    if (m_saveButton) {
+        m_saveButton->setEnabled(isEditing);
+    }
+}
+
+void TaskManagementPage::loadTaskToConfig(const TransferTask &task)
+{
+    if (m_configWidget) {
+        m_configWidget->loadTask(task);
+    }
+}
+
+QString TaskManagementPage::getStatusText(TaskStatus status) const
+{
+    switch (status) {
+    case TaskStatus::Stopped:
+        return tr("已停止");
+    case TaskStatus::Running:
+        return tr("运行中");
+    case TaskStatus::Error:
+        return tr("错误");
+    case TaskStatus::Paused:
+        return tr("已暂停");
+    case TaskStatus::Waiting:
+        return tr("等待中");
+    }
+    return tr("未知");
+}
+
+QString TaskManagementPage::getTransportTypeText(TransportType type) const
+{
+    switch (type) {
+    case TransportType::Serial:
+        return tr("串口");
+    case TransportType::TCP_Server:
+        return tr("TCP服务器");
+    case TransportType::TCP_Client:
+        return tr("TCP客户端");
+    case TransportType::UDP_Server:
+        return tr("UDP服务器");
+    case TransportType::UDP_Client:
+        return tr("UDP客户端");
+    }
+    return tr("未知");
+}
+
+QString TaskManagementPage::getProtocolTypeText(ProtocolType type) const
+{
+    switch (type) {
+    case ProtocolType::Modbus_RTU:
+        return tr("Modbus RTU");
+    case ProtocolType::Modbus_TCP:
+        return tr("Modbus TCP");
+    case ProtocolType::CAN_Standard:
+        return tr("CAN标准帧");
+    case ProtocolType::Raw_Data:
+        return tr("原始数据");
+    }
+    return tr("未知");
+}
+
+QString TaskManagementPage::generateTaskId() const
+{
+    return QUuid::createUuid().toString(QUuid::WithoutBraces);
+}
+

+ 86 - 0
src/view_task/TaskManagementPage.h

@@ -0,0 +1,86 @@
+/**
+ * @file TaskManagementPage.h
+ * @brief 任务管理页面
+ * 
+ * 提供任务列表显示和配置编辑功能
+ */
+
+#ifndef TASK_MANAGEMENT_PAGE_H
+#define TASK_MANAGEMENT_PAGE_H
+
+#include <QWidget>
+#include <QTableWidget>
+#include "task_manager/TransferTask.h"
+
+class TaskConfigWidget;
+class QPushButton;
+class QSplitter;
+class QGroupBox;
+
+class TaskManagementPage : public QWidget
+{
+    Q_OBJECT
+
+public:
+    explicit TaskManagementPage(QWidget *parent = nullptr);
+    ~TaskManagementPage() override;
+
+    /**
+     * @brief 刷新任务列表
+     */
+    void refreshTaskList();
+
+    /**
+     * @brief 选择任务
+     * @param taskId 任务ID
+     */
+    void selectTask(const QString &taskId);
+
+private slots:
+    void onNewTask();
+    void onDeleteTask();
+    void onStartTask();
+    void onStopTask();
+    void onPauseTask();
+    void onResumeTask();
+    void onTaskSelected(int row, int column);
+    void onTaskStatusChanged(const QString &taskId, int status);
+    void onTaskError(const QString &taskId, const QString &error);
+    void onConfigChanged();
+    void onSaveTask();
+
+private:
+    void createUI();
+    QWidget* createToolbar();
+    void createTaskTable();
+    void createConfigArea();
+    void connectSignals();
+    void updateButtonStates();
+    void loadTaskToConfig(const TransferTask &task);
+    QString getStatusText(TaskStatus status) const;
+    QString getTransportTypeText(TransportType type) const;
+    QString getProtocolTypeText(ProtocolType type) const;
+    QString generateTaskId() const;
+
+    // UI组件
+    QTableWidget *m_taskTable;
+    TaskConfigWidget *m_configWidget;
+    QWidget *m_configWrapper;
+    QSplitter *m_splitter;
+    
+    // 工具栏按钮
+    QPushButton *m_newButton;
+    QPushButton *m_deleteButton;
+    QPushButton *m_startButton;
+    QPushButton *m_stopButton;
+    QPushButton *m_pauseButton;
+    QPushButton *m_resumeButton;
+    QPushButton *m_saveButton;
+    
+    // 当前选中的任务
+    QString m_currentTaskId;
+    bool m_isEditing;
+};
+
+#endif // TASK_MANAGEMENT_PAGE_H
+