This commit is contained in:
coco
2026-07-03 16:05:30 +08:00
commit df489d5640
1101 changed files with 779140 additions and 0 deletions
@@ -0,0 +1,283 @@
# 循环任务上传
<cite>
**本文档引用的文件**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp)
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h)
- [NetRequestDialog.cpp](file://cpp/socket/NetRequestDialog.cpp)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h)
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp)
- [CDragListCtrl.h](file://cpp/ctrl/CDragListCtrl.h)
</cite>
## 目录
1. [简介](#简介)
2. [核心组件](#核心组件)
3. [网络通信架构](#网络通信架构)
4. [数据封装与上传流程](#数据封装与上传流程)
5. [拖拽排序功能实现](#拖拽排序功能实现)
6. [设备ID与PLC ID的作用](#设备id与plc-id的作用)
7. [消息响应处理](#消息响应处理)
## 简介
本文档全面文档化循环任务上传功能的技术实现,重点聚焦于`DialUploadLoopTask`类的设计。该功能允许用户创建并上传循环测量任务到GD10设备,支持通过拖拽方式对子任务进行排序,并通过网络通信协议将任务信息发送到目标设备。系统通过继承`CNetRequestDialog`类构建了完整的网络请求-响应架构,实现了从用户界面交互到数据传输的完整流程。
## 核心组件
`DialUploadLoopTask`类是循环任务上传功能的核心实现,继承自`CNetRequestDialog`,负责管理用户界面、数据封装和网络通信。该类通过`CDragListCtrl`控件实现任务列表的拖拽排序功能,使用`STTaskListItem`结构体存储任务信息,并通过`PostNetRequest`方法发起网络请求与GD10设备通信。
**本节来源**
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L10-L65)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L22-L30)
## 网络通信架构
### 继承关系与架构设计
`DialUploadLoopTask`类继承自`CNetRequestDialog`,后者提供了基础的网络通信能力。这种设计模式实现了网络通信功能的复用和封装,形成了清晰的职责分离:`CNetRequestDialog`处理底层网络通信机制,而`DialUploadLoopTask`专注于业务逻辑和用户界面。
```mermaid
classDiagram
class CNetRequestDialog {
+CNetRequestDialog(UINT nIDTemplate, CWnd* pParent)
+~CNetRequestDialog()
+PostNetRequest(BYTE cmd, HWND hwnd, char* pData, WORD dataLen)
-PreNetResponse(WPARAM wParam, LPARAM lParam)
-DoDataExchange(CDataExchange* pDX)
}
class DialUploadLoopTask {
+DialUploadLoopTask(CWnd* pParent)
+~DialUploadLoopTask()
+SetDeviceID(DWORD dwDeviceID)
+SetPLCID(DWORD dwPLCID)
+OnInitDialog()
+OnBnClickedUploadLoop()
+OnBnClickedExitUpload()
+OnCbnSelchangeTimerTypeCombo()
+DragMoveItem(WPARAM wParam, LPARAM lParam)
-PreNetResponse(WPARAM wParam, LPARAM lParam)
-DoDataExchange(CDataExchange* pDX)
-m_CListCtrlTask CDragListCtrl
-m_TaskList CList<STTaskListItem>
-m_dwDeviceSN DWORD
-m_dwPLCID DWORD
}
DialUploadLoopTask --|> CNetRequestDialog : 继承
```
**图表来源**
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L10)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h#L8)
**本节来源**
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L10)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h#L8)
## 数据封装与上传流程
### 任务信息结构体
循环任务上传的数据封装基于`STLoopTaskInfo`结构体,该结构体包含了任务的所有必要信息:
```mermaid
classDiagram
class STLoopTaskInfo {
+char ucTaskID[MAX_NAME_LEN]
+char ucTaskName[MAX_NAME_LEN]
+UINT32 uiGD10Id
+UINT32 uiPlcId
+UINT8 ucContrlType
+UINT8 ucTimerType
+UINT64 uiLoopNum
+UINT8 ucLoopType
+UINT8 ucTimerAgsNum
+UINT8 ucTimerTimeAgs
+UINT32 uiStartTime
+UINT32 uiEndTime
+UINT32 uiStartMin
+UINT32 uiTaskSpace
+UINT32 uiSubTaskNum
}
```
### 上传流程实现
上传流程在`OnBnClickedUploadLoop`方法中实现,主要包括以下步骤:
1. **参数验证**:检查子任务数量、任务名称、循环次数等输入参数的有效性
2. **数据填充**:从界面控件获取数据并填充到`STLoopTaskInfo`结构体中
3. **字节序转换**:使用`htonl``htons`函数将主机字节序转换为网络字节序
4. **任务列表序列化**:将`STTaskListItem`列表中的任务ID按顺序序列化到发送缓冲区
5. **网络请求发起**:调用`PostNetRequest`方法发送数据
```mermaid
flowchart TD
Start([开始上传]) --> ValidateInput["验证输入参数"]
ValidateInput --> InputValid{"参数有效?"}
InputValid --> |否| ShowError["显示错误信息"]
InputValid --> |是| FillData["填充STLoopTaskInfo结构体"]
FillData --> ConvertByteOrder["转换为网络字节序"]
ConvertByteOrder --> SerializeTasks["序列化任务列表"]
SerializeTasks --> SuspendThread["暂停网络线程"]
SuspendThread --> SendRequest["调用PostNetRequest发送请求"]
SendRequest --> ResumeThread["恢复网络线程"]
ResumeThread --> End([上传完成])
ShowError --> End
```
**图表来源**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L180-L377)
**本节来源**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L180-L377)
## 拖拽排序功能实现
### CDragListCtrl控件应用
`CDragListCtrl`控件是实现任务拖拽排序的关键组件,它继承自`CListCtrl`并扩展了拖拽功能。该控件通过Windows消息机制处理拖拽操作,实现了直观的任务重新排序体验。
```mermaid
classDiagram
class CListCtrl {
+GetItemCount()
+GetItemText(int nItem, int nSubItem)
+SetItemText(int nItem, int nSubItem, LPCTSTR lpszText)
+InsertItem(int nItem, LPCTSTR lpszItem)
}
class CDragListCtrl {
+OnLvnBegindrag(NMHDR *pNMHDR, LRESULT *pResult)
+OnMouseMove(UINT nFlags, CPoint point)
+OnLButtonUp(UINT nFlags, CPoint point)
-m_nSelItem int
-m_pDragImageList CImageList*
-m_bDragging BOOL
}
CDragListCtrl --|> CListCtrl : 继承
```
### 拖拽事件处理流程
拖拽排序功能通过以下三个关键事件处理:
1. **开始拖拽**`OnLvnBegindrag`):当用户开始拖拽时创建拖拽图像并进入拖拽模式
2. **鼠标移动**`OnMouseMove`):在拖拽过程中更新拖拽图像位置
3. **释放鼠标**`OnLButtonUp`):完成拖拽操作,更新列表项位置
```mermaid
sequenceDiagram
participant User as 用户
participant CDragListCtrl as CDragListCtrl控件
participant DialUploadLoopTask as DialUploadLoopTask对话框
User->>CDragListCtrl : 开始拖拽操作
CDragListCtrl->>CDragListCtrl : OnLvnBegindrag事件
CDragListCtrl->>CDragListCtrl : 创建拖拽图像
CDragListCtrl->>CDragListCtrl : 进入拖拽模式
loop 拖拽过程中
User->>CDragListCtrl : 移动鼠标
CDragListCtrl->>CDragListCtrl : OnMouseMove事件
CDragListCtrl->>CDragListCtrl : 更新拖拽图像位置
end
User->>CDragListCtrl : 释放鼠标按钮
CDragListCtrl->>CDragListCtrl : OnLButtonUp事件
CDragListCtrl->>CDragListCtrl : 结束拖拽操作
CDragListCtrl->>DialUploadLoopTask : 发送WM_MOVEITEM消息
DialUploadLoopTask->>DialUploadLoopTask : DragMoveItem处理
DialUploadLoopTask->>DialUploadLoopTask : 重新排列列表项
```
**图表来源**
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L93-L178)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L57-L58)
**本节来源**
- [CDragListCtrl.cpp](file://cpp/ctrl/CDragListCtrl.cpp#L93-L178)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L481-L532)
## 设备ID与PLC ID的作用
### 设备标识符管理
`DialUploadLoopTask`类通过两个关键成员变量管理设备标识:
- `m_dwDeviceSN`:存储GD10设备的序列号(Device ID
- `m_dwPLCID`:存储PLC控制器的ID
这两个标识符在任务上传过程中起着至关重要的作用,确保任务被正确路由到目标设备。
### 标识符的设置与使用
设备ID和PLC ID通过专门的setter方法进行设置:
```mermaid
classDiagram
class DialUploadLoopTask {
+SetDeviceID(DWORD dwDeviceID)
+SetPLCID(DWORD dwPLCID)
-m_dwDeviceSN DWORD
-m_dwPLCID DWORD
}
class UsageFlow {
direction LR
A[用户选择设备] --> B[调用SetDeviceID]
B --> C[保存m_dwDeviceSN]
D[用户选择PLC] --> E[调用SetPLCID]
E --> F[保存m_dwPLCID]
C --> G[上传时填充STLoopTaskInfo]
F --> G
G --> H[发送到GD10设备]
}
```
在上传过程中,这些ID被提取自界面控件(去除"SN"和"PLC"前缀),转换为整数后填充到`STLoopTaskInfo`结构体的`uiGD10Id``uiPlcId`字段中,确保设备能够正确识别和处理上传的任务。
**图表来源**
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L22-L30)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L232-L238)
**本节来源**
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L22-L30)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L232-L238)
## 消息响应处理
### 预处理与响应机制
`DialUploadLoopTask`类实现了`CNetRequestDialog`定义的`PreNetResponse`纯虚函数,用于处理来自GD10设备的响应消息。这种设计模式遵循了模板方法模式,基类`CNetRequestDialog`定义了算法骨架,子类实现具体步骤。
```mermaid
sequenceDiagram
participant GD10 as GD10设备
participant Network as 网络模块
participant CNetRequestDialog as CNetRequestDialog
participant DialUploadLoopTask as DialUploadLoopTask
GD10->>Network : 发送响应数据包
Network->>CNetRequestDialog : OnNetResponse消息
CNetRequestDialog->>CNetRequestDialog : 调用PreNetResponse
CNetRequestDialog->>DialUploadLoopTask : 虚函数调用
DialUploadLoopTask->>DialUploadLoopTask : 处理具体响应
DialUploadLoopTask->>DialUploadLoopTask : 显示结果或错误信息
```
### 响应处理逻辑
`PreNetResponse`方法根据响应命令类型和状态码进行相应的处理:
```mermaid
flowchart TD
Start([收到响应]) --> CheckCommand["检查命令类型 EN_REQ_LOOP_TASK_TRUST"]
CheckCommand --> IsMatch{"命令匹配?"}
IsMatch --> |否| Exit[忽略响应]
IsMatch --> |是| CheckStatus["检查状态码"]
CheckStatus --> Success{"状态码=0?"}
Success --> |是| ShowSuccess["显示成功消息"]
Success --> |否| CheckConflict["检查是否为时间冲突"]
CheckConflict --> IsConflict{"状态码=2?"}
IsConflict --> |是| ShowConflict["显示时间冲突消息"]
IsConflict --> |否| ShowUnknownError["显示未知错误"]
ShowSuccess --> CloseDialog["关闭对话框"]
ShowConflict --> Exit
ShowUnknownError --> Exit
CloseDialog --> Exit
```
成功的响应会显示"循环任务创建完成"的消息并关闭对话框,而错误响应则会根据具体错误码显示相应的错误信息,如"此时段已创建其他任务"。
**图表来源**
- [NetRequestDialog.cpp](file://cpp/socket/NetRequestDialog.cpp#L37-L41)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L387-L447)
**本节来源**
- [NetRequestDialog.cpp](file://cpp/socket/NetRequestDialog.cpp#L37-L41)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L387-L447)
@@ -0,0 +1,265 @@
# 循环任务查询
<cite>
**本文档引用的文件**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp)
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [TaskDataOper.h](file://h/TaskDataOper.h)
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h)
</cite>
## 目录
1. [引言](#引言)
2. [核心组件](#核心组件)
3. [架构概述](#架构概述)
4. [详细组件分析](#详细组件分析)
5. [依赖分析](#依赖分析)
6. [性能考虑](#性能考虑)
7. [故障排除指南](#故障排除指南)
8. [结论](#结论)
## 引言
本文档系统化地描述了Geomative Studio软件中循环任务查询功能的实现机制。重点分析了DialLoopTaskQuery对话框作为CDialog派生类的生命周期管理,包括其初始化流程、数据交换机制以及消息映射处理。文档详细阐述了CListCtrl控件在任务列表展示中的应用,以及STLoopTaskTable结构体在内存中的数据组织方式。同时,深入探讨了查询功能与数据库的交互逻辑,特别是如何通过CTaskDataOper组件访问tdTaskPacket和tdTaskPacketInfo表来获取循环任务数据。
## 核心组件
循环任务查询功能的核心组件是DialLoopTaskQuery对话框类,该类继承自MFC的CDialog类,负责提供用户界面以查询和选择循环任务。该对话框通过m_LoopTablelist成员变量管理内存中的循环任务数据,并使用m_ListLoopDisplay控件在界面上展示任务列表。当用户选择任务并点击查询按钮时,系统会将选中的任务ID存储在m_szArrayLoopTaskID数组中,并关闭对话框以返回主程序进行后续处理。
**本节来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L1-L145)
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h)
## 架构概述
循环任务查询功能的架构基于MFC对话框框架,采用经典的模型-视图-控制器(MVC)模式。DialLoopTaskQuery类作为视图和控制器,负责用户交互和界面展示;STLoopTaskTable结构体作为数据模型,定义了循环任务的数据结构;CTaskDataOper类作为数据访问层,负责与数据库进行交互。整个架构通过消息映射机制实现用户操作的响应,通过DoDataExchange实现控件与成员变量的数据绑定。
```mermaid
graph TB
subgraph "用户界面层"
DialLoopTaskQuery["DialLoopTaskQuery<br/>对话框类"]
end
subgraph "数据访问层"
TaskDataOper["CTaskDataOper<br/>数据操作类"]
end
subgraph "数据存储层"
Database["数据库<br/>tdTaskPacket表"]
end
DialLoopTaskQuery --> TaskDataOper
TaskDataOper --> Database
Database --> TaskDataOper
TaskDataOper --> DialLoopTaskQuery
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L1-L145)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L1-L1450)
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h#L700-L706)
## 详细组件分析
### DialLoopTaskQuery类分析
DialLoopTaskQuery类是循环任务查询功能的核心实现,作为CDialog的派生类,它遵循MFC对话框的标准生命周期。
#### 类生命周期管理
DialLoopTaskQuery类的生命周期由MFC框架管理,遵循标准的构造、初始化、运行和析构流程。类的构造函数负责初始化成员变量,析构函数则负责清理资源。
```mermaid
classDiagram
class DialLoopTaskQuery {
+CStatic m_StaticLoopNum
+CListCtrl m_ListLoopDisplay
+CList<STLoopTaskTable> m_LoopTablelist
+CStringArray m_szArrayLoopTaskID
+DialLoopTaskQuery(CWnd* pParent)
+~DialLoopTaskQuery()
+OnInitDialog() bool
+DoDataExchange(CDataExchange* pDX)
+OnBnClickedQuerySubLoop()
+OnBnClickedCancel()
}
DialLoopTaskQuery --|> CDialog : "继承"
```
**图表来源**
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h)
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L1-L145)
#### OnInitDialog初始化流程
OnInitDialog方法是对话框初始化的核心,负责设置界面控件的初始状态和加载数据。该方法首先调用基类的OnInitDialog进行基本初始化,然后配置CListCtrl控件的扩展样式,设置列标题,并根据m_LoopTablelist中的数据填充列表控件。
```mermaid
flowchart TD
Start([OnInitDialog入口]) --> SetExtendedStyle["设置CListCtrl扩展样式<br/>LVS_EX_FULLROWSELECT等"]
SetExtendedStyle --> SetStaticText["设置静态文本控件<br/>m_StaticLoopNum初始值为0"]
SetStaticText --> AddColumns["添加列表控件列<br/>任务名称、任务ID等"]
AddColumns --> CheckData["检查m_LoopTablelist<br/>是否有数据"]
CheckData --> |是| LoopData["遍历m_LoopTablelist<br/>填充列表控件"]
CheckData --> |否| SetTaskNum["设置任务数量为0"]
LoopData --> FormatTime["格式化时间显示<br/>使用Tm2LocalStr函数"]
FormatTime --> InsertItem["插入列表项<br/>SetItemText设置各列值"]
InsertItem --> UpdateTaskNum["更新任务数量显示"]
UpdateTaskNum --> End([返回TRUE])
SetTaskNum --> End
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L82-L144)
#### DoDataExchange数据交换机制
DoDataExchange方法实现了对话框控件与类成员变量之间的数据交换,这是MFC数据绑定的核心机制。该方法使用DDX_Control宏将界面控件与类的成员变量关联起来,确保界面状态与程序数据的一致性。
```mermaid
sequenceDiagram
participant Framework as "MFC框架"
participant Dialog as "DialLoopTaskQuery"
Framework->>Dialog : OnInitDialog()
Dialog->>Dialog : CDialog : : OnInitDialog()
Dialog->>Dialog : DoDataExchange(pDX)
Dialog->>Dialog : DDX_Control(pDX, IDC_STATIC_LOOP_Q_NUM, m_StaticLoopNum)
Dialog->>Dialog : DDX_Control(pDX, IDC_LIST_QUERY, m_ListLoopDisplay)
Dialog->>Framework : 控件与成员变量绑定完成
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L29-L34)
#### 消息映射处理
消息映射机制使DialLoopTaskQuery类能够响应用户的操作。通过BEGIN_MESSAGE_MAP宏定义,将特定的Windows消息映射到相应的处理函数。当用户点击"查询"或"取消"按钮时,框架会自动调用对应的处理函数。
```mermaid
flowchart LR
A["用户点击查询按钮"] --> B["WM_COMMAND消息"]
B --> C["MFC框架查找消息映射"]
C --> D["找到ON_BN_CLICKED(IDOK_QUERY_SUB_LOOP)"]
D --> E["调用OnBnClickedQuerySubLoop函数"]
E --> F["处理查询逻辑"]
F --> G["关闭对话框"]
H["用户点击取消按钮"] --> I["WM_COMMAND消息"]
I --> J["MFC框架查找消息映射"]
J --> K["找到ON_BN_CLICKED(IDCANCEL)"]
K --> L["调用OnBnClickedCancel函数"]
L --> M["清理资源"]
M --> N["关闭对话框"]
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L37-L40)
### CListCtrl控件应用分析
m_ListLoopDisplay是CListCtrl类型的控件,用于在界面上展示循环任务列表。该控件通过插入列和设置项文本的方式组织和显示数据。
#### 任务列表展示机制
CListCtrl控件通过多列列表的形式展示任务信息,每行代表一个循环任务,每列代表任务的一个属性。控件的初始化和数据填充在OnInitDialog方法中完成。
```mermaid
erDiagram
TASK ||--o{ COLUMN : "包含"
TASK {
string 任务名称
string 任务ID
string 任务类型
string 开始时间
string 结束时间
}
COLUMN {
string 列标题
int 列宽度
int 对齐方式
}
DISPLAY : "m_ListLoopDisplay"
DISPLAY --> TASK : "显示"
DISPLAY --> COLUMN : "管理"
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L90-L137)
### STLoopTaskTable结构体分析
STLoopTaskTable结构体定义了循环任务在内存中的数据组织方式,是连接界面展示和数据库存储的关键数据模型。
#### 内存数据组织
STLoopTaskTable结构体包含了循环任务的所有必要信息,通过CList模板类进行管理,形成一个任务列表。
```mermaid
classDiagram
class STLoopTaskTable {
+char ucTaskID[40]
+char ucTaskName[40]
+BYTE ucLoopType
+UINT32 uiStartTime
+UINT32 uiEndTime
}
class CList {
+AddHead()
+AddTail()
+RemoveAll()
+GetHeadPosition()
+GetNext()
}
CList<STLoopTaskTable> --|> CList : "模板实例化"
CList<STLoopTaskTable> --> STLoopTaskTable : "存储"
```
**图表来源**
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h#L700-L706)
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h#L28)
### 数据库交互逻辑分析
循环任务查询功能通过CTaskDataOper组件与数据库进行交互,获取循环任务的相关数据。
#### 查询功能与数据库交互
查询功能通过CTaskDataOper类的QueryTaskPacketInfo方法访问数据库,获取tdTaskPacketInfo表中的任务信息,并将其转换为STTdBrowseInfo结构体数组。
```mermaid
sequenceDiagram
participant Dialog as "DialLoopTaskQuery"
participant DataOper as "CTaskDataOper"
participant Database as "数据库"
Dialog->>DataOper : QueryTaskPacketInfo(vtTdBrowseInfo)
DataOper->>Database : SELECT * FROM tdTaskPacketInfo
Database-->>DataOper : 返回任务数据
DataOper->>DataOper : 转换为STTdBrowseInfo数组
DataOper-->>Dialog : 填充vtTdBrowseInfo
Dialog->>Dialog : 将数据加载到m_LoopTablelist
```
**图表来源**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L1112-L1139)
- [TaskDataOper.h](file://h/TaskDataOper.h#L308-L306)
## 依赖分析
循环任务查询功能依赖于多个核心组件和外部资源。主要依赖包括MFC框架提供的对话框和控件类、CTaskDataOper数据操作类、全局应用程序对象theApp以及数据库连接。这些依赖关系确保了功能的完整性和稳定性。
```mermaid
graph TD
DialLoopTaskQuery --> CDialog
DialLoopTaskQuery --> CListCtrl
DialLoopTaskQuery --> CStatic
DialLoopTaskQuery --> CTaskDataOper
DialLoopTaskQuery --> theApp
CTaskDataOper --> ADODB
CTaskDataOper --> Database
theApp --> NetworkOper
theApp --> Connection
```
**图表来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L10-L13)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L25-L38)
## 性能考虑
循环任务查询功能在性能方面主要考虑数据加载效率和界面响应速度。由于任务列表数据通常不会太大,因此采用一次性加载所有数据的方式。通过合理设置CListCtrl控件的扩展样式,如LVS_EX_GRIDLINES和LVS_EX_FULLROWSELECT,提升了用户体验。在数据交换过程中,使用_bstr_t类型转换确保了字符串处理的效率。
## 故障排除指南
当循环任务查询功能出现问题时,可以按照以下步骤进行排查:
1. 检查数据库连接是否正常
2. 验证tdTaskPacket和tdTaskPacketInfo表是否存在且有数据
3. 确认m_LoopTablelist是否正确填充了数据
4. 检查OnInitDialog方法中的列设置是否正确
5. 验证消息映射是否正确配置
**本节来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L55-L58)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L79-L81)
## 结论
循环任务查询功能通过DialLoopTaskQuery对话框实现了用户友好的任务选择界面。该功能充分利用了MFC框架的特性,通过标准的对话框生命周期管理、数据交换机制和消息映射,实现了稳定可靠的用户交互。内存中的STLoopTaskTable结构体和CList容器有效组织了任务数据,而CTaskDataOper组件则确保了与数据库的高效交互。整体设计遵循了良好的软件工程原则,具有良好的可维护性和扩展性。
@@ -0,0 +1,292 @@
# 循环任务管理
<cite>
**本文档引用的文件**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp)
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h)
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [DialManageLoopTask.h](file://h/DialManageLoopTask.h)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp)
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h)
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h)
</cite>
## 目录
1. [引言](#引言)
2. [循环任务查询](#循环任务查询)
3. [循环任务管理](#循环任务管理)
4. [循环任务上传](#循环任务上传)
5. [数据结构与协议](#数据结构与协议)
6. [生命周期与同步机制](#生命周期与同步机制)
7. [异常处理与数据完整性](#异常处理与数据完整性)
8. [与PLC状态监控的集成](#与plc状态监控的集成)
9. [结论](#结论)
## 引言
循环任务管理功能是Geomative Studio系统中的核心模块之一,负责实现定时任务的创建、查询、管理和批量上传。该功能通过三个主要界面组件实现:`DialLoopTaskQuery`(任务查询)、`DialManageLoopTask`(任务管理)和`DialUploadLoopTask`(任务上传)。这些组件共同构成了一个完整的循环任务生命周期管理系统,支持用户对设备端的定时测量任务进行精细化控制。
系统通过网络协议与设备端通信,实现任务信息的双向同步。任务数据结构设计考虑了时间控制、执行策略、子任务调度等多个维度,确保任务能够在指定时间窗口内按预定规则执行。同时,系统集成了PLC状态监控功能,确保任务执行环境的稳定性。
**本文档来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L1-L145)
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L1-L621)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L1-L532)
## 循环任务查询
`DialLoopTaskQuery`组件提供了循环任务的查询功能,允许用户从设备端获取已存在的循环任务列表。该组件通过`CListCtrl`控件展示任务信息,包括任务名称、任务ID、任务类型、开始时间和结束时间等关键字段。
在初始化过程中,组件通过`OnInitDialog`方法设置列表控件的列标题和显示样式。由于该组件仅用于查询和选择任务,其核心逻辑集中在`OnBnClickedQuerySubLoop`事件处理函数中。当用户选择一个或多个任务并点击确认按钮时,系统会将选中的任务ID存储在`m_szArrayLoopTaskID`数组中,并关闭对话框,将选择结果返回给调用方。
该组件的设计体现了单一职责原则,专注于任务查询功能,不涉及任务的创建或修改操作。通过与`STLoopTaskTable`数据结构的绑定,实现了任务信息的结构化展示。
**本文档来源**
- [DialLoopTaskQuery.cpp](file://cpp/Views/DialLoopTaskQuery.cpp#L82-L144)
- [DialLoopTaskQuery.h](file://h/DialLoopTaskQuery.h#L29)
## 循环任务管理
`DialManageLoopTask`组件提供了循环任务的管理功能,包括任务的删除和详细信息查看。该组件继承自`CNetRequestDialog`,具备网络请求处理能力,能够与设备端进行双向通信。
组件的核心功能包括:
- **任务列表初始化**:通过`InitLoopTaskList`方法向设备端发送`EN_REQ_DOWNLOAD_LOOP_TABLE`命令,获取指定时间范围内的循环任务列表。
- **任务删除**:用户选择一个或多个任务后,点击删除按钮,系统会向设备端发送`EN_CANCEL_LOOP_TASK_TRUST`命令,请求删除选中的循环任务。
- **子任务查看**:当用户点击某个循环任务时,系统会发送`EN_REQ_DOWNLOAD_LOOP_SUB_TABLE`命令,获取该循环任务包含的子任务列表。
该组件使用`std::map<CString, STLoopTaskTable>`数据结构`m_mapSaveLoopList`来缓存从设备端获取的任务列表,提高了数据访问效率。同时,通过`CRITICAL_SECTION`临界区对象`m_cs`确保多线程环境下的数据安全。
**本文档来源**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L230-L621)
- [DialManageLoopTask.h](file://h/DialManageLoopTask.h#L63)
## 循环任务上传
`DialUploadLoopTask`组件提供了新建循环任务的功能,允许用户配置任务参数并上传到设备端。该组件提供了丰富的用户界面元素,包括组合框、日期时间选择器和编辑框,用于收集任务配置信息。
任务创建流程包括以下关键步骤:
1. **参数收集**:从用户界面收集任务名称、循环类型(次数循环或定时循环)、循环次数、开始时间、结束时间、每日开始时间和任务间隔等参数。
2. **数据验证**:对用户输入进行验证,确保循环次数在1-60000范围内,结束时间不早于开始时间。
3. **数据结构填充**:将验证后的参数填充到`STLoopTaskInfo`数据结构中,并进行网络字节序转换。
4. **任务上传**:通过`PostNetRequest`方法发送`EN_REQ_LOOP_TASK_TRUST`命令,将任务信息上传到设备端。
该组件还支持子任务的拖拽排序功能,通过`DragMoveItem`消息处理函数实现。用户可以通过拖拽调整子任务的执行顺序,系统会按照调整后的顺序生成任务ID列表并上传。
**本文档来源**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L180-L378)
- [DialUploadLoopTask.h](file://h/DialUploadLoopTask.h#L42)
## 数据结构与协议
循环任务管理功能依赖于一系列精心设计的数据结构和通信协议。核心数据结构包括:
### STLoopTaskTable
该结构体用于表示循环任务的基本信息,包括:
- `ucTaskID`:任务ID
- `ucTaskName`:任务名称
- `ucLoopType`:循环类型(0:一次, 1:按天, 2:按月, 3:按周)
- `uiStartTime`:开始测试时间
- `uiEndTime`:结束测试时间
### STLoopTaskInfo
该结构体用于表示循环任务的详细配置信息,包含:
- `ucTaskID`:循环任务名
- `ucTaskName`:循环备用任务名
- `uiPlcId`PLC设备ID
- `uiGD10Id`GD10设备ID
- `ucContrlType`:控制类型(0:次数循环, 1:定时循环)
- `uiLoopNum`:循环次数
- `uiStartTime`:开始测试时间
- `uiEndTime`:结束测试时间
- `uiStartMin`:每天或每周相对0点开始的分钟数
- `uiTaskSpace`:任务间间隔(秒)
- `uiSubTaskNum`:子任务数
### 通信协议
系统定义了专门的网络命令用于循环任务管理:
- `EN_REQ_LOOP_TASK_TRUST` (0x58):请求创建循环任务
- `EN_CANCEL_LOOP_TASK_TRUST` (0x59):请求取消循环任务
- `EN_REQ_DOWNLOAD_TASK_ARG` (0x73):请求下载任务参数
- `EN_REQ_DOWNLOAD_LOOP_TABLE` (0x77):请求下载循环任务表
- `EN_REQ_DOWNLOAD_LOOP_SUB_TABLE` (0x78):请求下载循环子任务表
这些数据结构和协议共同构成了循环任务管理功能的基础,确保了任务信息在客户端和设备端之间的一致性和完整性。
```mermaid
classDiagram
class STLoopTaskTable {
+char ucTaskID[40]
+char ucTaskName[40]
+BYTE ucLoopType
+UINT32 uiStartTime
+UINT32 uiEndTime
}
class STLoopTaskInfo {
+char ucTaskID[40]
+char ucTaskName[60]
+UINT32 uiPlcId
+UINT32 uiGD10Id
+BYTE ucContrlType
+BYTE ucTimerType
+UINT16 uiLoopNum
+UINT16 uiRemainLoopNum
+BYTE ucLoopType
+BYTE ucTimerAgsNum
+BYTE ucTimerTimeAgs
+UINT32 uiStartTime
+UINT32 uiEndTime
+UINT32 uiStartMin
+UINT32 uiTaskSpace
+UINT32 uiSubTaskNum
}
class STTaskListItem {
+char szTaskID[40]
+char szTDName[60]
+BYTE byTestStatus
+EN_TASK_LOCAL_STATUSE eSynStatus
}
class EN_TASK_LOCAL_STATUSE {
<<enumeration>>
EN_TASK_NO_UPLOAD = 0
EN_TASK_NO_DOWNLOAD
EN_TASK_YES_SYN
}
class EN_TASK_SERVER_STATUSE {
<<enumeration>>
EN_TASK_STATE_NO_TRUST = 0
EN_TASK_STATE_TESTING
EN_TASK_STATE_STOP_TEST = 20
EN_TASK_STATE_TEST_FAILED = 30
EN_TASK_STATE_FINISH = 40
}
STLoopTaskInfo --> STTaskListItem : "包含"
STTaskListItem --> EN_TASK_LOCAL_STATUSE : "引用"
STLoopTaskInfo --> EN_TASK_SERVER_STATUSE : "引用"
```
**图表来源**
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h#L705-L729)
- [CtrlProtocolDef.h](file://h/CtrlProtocolDef.h#L698)
## 生命周期与同步机制
循环任务的生命周期管理涉及创建、查询、执行和删除四个阶段,每个阶段都有相应的同步机制确保数据一致性。
### 创建阶段
当用户通过`DialUploadLoopTask`创建新任务时,系统会生成唯一的任务ID,格式为"LOOPYYYYMMDDHHMMSS_任务名"。这个ID结合了时间戳和任务名,确保全局唯一性。创建请求通过`EN_REQ_LOOP_TASK_TRUST`命令发送到设备端,设备端验证参数合法性后返回响应。
### 查询阶段
`DialManageLoopTask`组件通过分页机制查询任务列表。初始查询时间范围为当前时间前30天到当前时间后1小时,如果查询结果跨越多天,则按5天为单位分批加载,避免单次请求数据量过大。
### 执行阶段
任务执行由设备端的PLC控制器负责调度。系统通过`STLoopTaskInfo`中的`uiStartMin``uiTaskSpace`参数精确控制任务的启动时间和间隔。任务执行状态通过`EN_TASK_SERVER_STATUSE`枚举值反映,包括测试中、测试停止、测试失败和完成等状态。
### 删除阶段
任务删除操作是不可逆的。当用户请求删除任务时,系统会向设备端发送`EN_CANCEL_LOOP_TASK_TRUST`命令,设备端验证后删除任务并释放相关资源。删除操作会同时清除任务的所有子任务和测量数据。
整个生命周期中,系统通过网络请求-响应模式确保操作的原子性。每个关键操作都有对应的日志记录,便于故障排查和审计。
```mermaid
sequenceDiagram
participant 用户 as 用户界面
participant 客户端 as 客户端应用
participant 设备端 as 设备端
用户->>客户端 : 创建循环任务
客户端->>设备端 : 发送EN_REQ_LOOP_TASK_TRUST
设备端-->>客户端 : 返回创建结果
客户端->>用户 : 显示创建结果
用户->>客户端 : 查询循环任务
客户端->>设备端 : 发送EN_REQ_DOWNLOAD_LOOP_TABLE
设备端-->>客户端 : 返回任务列表
客户端->>用户 : 显示任务列表
用户->>客户端 : 删除循环任务
客户端->>设备端 : 发送EN_CANCEL_LOOP_TASK_TRUST
设备端-->>客户端 : 返回删除结果
客户端->>用户 : 显示删除结果
设备端->>设备端 : 按计划执行任务
设备端->>客户端 : 推送任务状态更新
客户端->>用户 : 更新界面显示
```
**图表来源**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L376)
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L250)
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L172)
## 异常处理与数据完整性
系统在循环任务管理过程中实施了多层次的异常处理和数据完整性保障措施。
### 输入验证
在任务创建过程中,系统对所有用户输入进行严格验证:
- 任务名称不能为空
- 循环次数必须在1-60000范围内
- 结束时间不能早于开始时间
- 任务ID必须符合命名规范
### 网络通信保障
系统通过以下机制确保网络通信的可靠性:
- **请求重试**:关键操作支持重试机制,避免因网络抖动导致操作失败
- **超时控制**:设置合理的请求超时时间,防止长时间等待
- **错误码处理**:根据设备端返回的错误码进行针对性处理,如`FAILED_CREATE_LOOP_DURING_THIS_PERIOD`表示该时间段已存在其他任务
### 数据一致性
为确保数据一致性,系统采用以下策略:
- **事务性操作**:关键操作(如任务删除)设计为原子操作,要么全部成功,要么全部失败
- **状态同步**:通过`EN_TASK_LOCAL_STATUSE``EN_TASK_SERVER_STATUSE`两个状态枚举,分别维护本地和服务器端的任务状态,确保状态同步
- **日志记录**:所有关键操作都记录到日志文件中,便于问题追踪和审计
### 内存管理
系统在内存管理方面也做了精心设计:
- 使用`std::map``CList`等容器管理任务列表,提供高效的查找和遍历能力
- 通过`CRITICAL_SECTION`保护共享数据,避免多线程竞争
- 及时释放不再使用的资源,防止内存泄漏
这些措施共同确保了循环任务管理功能的稳定性和可靠性。
**本文档来源**
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L186-L271)
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L264-L268)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L409-L418)
## 与PLC状态监控的集成
循环任务管理功能与PLC状态监控系统深度集成,确保任务执行环境的稳定性和可靠性。
### 状态依赖
循环任务的执行依赖于PLC的运行状态。系统通过`OperPLC`模块获取PLC的实时状态,只有在PLC处于正常工作状态时才允许启动新的测量任务。这种依赖关系避免了在设备异常情况下执行任务导致的数据错误或设备损坏。
### 状态同步
系统实现了PLC状态与循环任务状态的双向同步:
- 当PLC状态发生变化时,系统会更新相关任务的状态
- 当循环任务状态发生变化时,系统会向PLC发送相应的控制指令
### 故障处理
在PLC出现故障时,系统会采取以下措施:
- 暂停正在执行的循环任务
- 记录故障信息和时间戳
- 向用户发出告警通知
- 在PLC恢复正常后,根据配置决定是否恢复任务执行
### 参数传递
循环任务的配置参数会通过特定的通信协议传递给PLC,包括:
- 任务ID和名称
- 执行时间计划
- 测量参数和阈值
- 异常处理策略
这种集成设计确保了上位机软件与下位机控制器之间的协调工作,提高了整个系统的自动化水平和可靠性。
**本文档来源**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L130-L133)
- [DialUploadLoopTask.cpp](file://cpp/Views/DialUploadLoopTask.cpp#L133-L136)
## 结论
循环任务管理功能通过`DialLoopTaskQuery``DialManageLoopTask``DialUploadLoopTask`三个核心组件,实现了完整的任务生命周期管理。系统采用分层架构设计,将用户界面、业务逻辑和数据访问分离,提高了代码的可维护性和可扩展性。
数据结构设计充分考虑了实际应用场景,`STLoopTaskInfo`等结构体包含了任务执行所需的所有参数。通信协议设计简洁高效,通过少量的命令码实现了复杂的功能需求。
异常处理机制完善,从输入验证到网络通信再到数据一致性,每个环节都有相应的保障措施。与PLC状态监控的深度集成,确保了任务执行的可靠性和安全性。
该功能模块的设计体现了工业控制系统对稳定性、可靠性和安全性的高要求,为地质勘探设备的自动化测量提供了坚实的基础。
@@ -0,0 +1,292 @@
# 循环任务管理界面
<cite>
**本文档引用的文件**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [DataMngStruct.h](file://h/DataMngStruct.h)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h)
</cite>
## 目录
1. [简介](#简介)
2. [项目结构](#项目结构)
3. [核心组件](#核心组件)
4. [架构概述](#架构概述)
5. [详细组件分析](#详细组件分析)
6. [依赖分析](#依赖分析)
7. [性能考虑](#性能考虑)
8. [故障排除指南](#故障排除指南)
9. [结论](#结论)
## 简介
本文档深入解析循环任务管理界面的UI架构与交互逻辑,基于DialManageLoopTask类的实现。该对话框是Geomative Studio软件中用于管理定时循环任务的核心组件,提供了任务创建、编辑、删除等核心操作功能。文档重点分析了界面与底层数据模型的绑定机制,用户操作事件(如按钮点击)的处理流程,以及如何通过消息映射与CTaskDataOper服务层进行通信。同时,文档化了界面状态管理策略,包括任务列表的动态刷新机制和用户输入验证逻辑。
## 项目结构
循环任务管理功能主要分布在Views和Operator两个模块中。Views模块包含用户界面相关的实现,而Operator模块则负责数据操作和业务逻辑处理。核心文件DialManageLoopTask.cpp位于cpp/Views目录下,实现了循环任务管理对话框的完整功能。
```mermaid
graph TB
subgraph "Views"
A[DialManageLoopTask.cpp]
B[DialLoopTaskQuery.cpp]
C[DialUploadLoopTask.cpp]
end
subgraph "Operator"
D[TaskDataOper.cpp]
end
subgraph "Socket"
E[NetRequestDialog.h]
end
A --> D
A --> E
B --> D
C --> D
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h)
**Section sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 核心组件
循环任务管理界面的核心组件是CDialManageLoopTask类,它继承自CNetRequestDialog,实现了循环任务的管理功能。该组件集成了任务列表显示、子任务管理、任务删除等核心操作。通过与CTaskDataOper服务层的通信,实现了与底层数据模型的绑定。组件使用了消息映射机制来处理用户操作事件,如按钮点击和列表项选择。
**Section sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
## 架构概述
循环任务管理界面采用典型的MVCModel-View-Controller)架构模式。视图层由CDialManageLoopTask类实现,负责用户界面的展示和用户交互。控制层通过消息映射处理用户操作,调用服务层进行数据操作。模型层由CTaskDataOper类提供,负责与数据库的交互和业务逻辑处理。
```mermaid
classDiagram
class CDialManageLoopTask {
+CListCtrl m_LoopTaskList
+CListCtrl m_subtaskList
+CEdit m_editLoopTaskName
+CEdit m_editPLCID
+CEdit m_editGDID
+OnInitDialog()
+OnBnClickedBtnDeleteLoopTask()
+OnBnClickedOk()
+OnNMClickListLoopTaskList()
+InitLoopTaskList()
+PreNetResponse()
}
class CTaskDataOper {
+Create1DTask()
+Create2DTask()
+Create3DTask()
+InsertTaskPacketInfo()
+InsertPlcStatusData()
+QueryARByTdID()
+QuerySptByAR()
}
class CNetRequestDialog {
+PostNetRequest()
+PreNetResponse()
+DoDataExchange()
}
CDialManageLoopTask --> CTaskDataOper : "uses"
CDialManageLoopTask --> CNetRequestDialog : "inherits"
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h)
## 详细组件分析
### CDialManageLoopTask类分析
CDialManageLoopTask类是循环任务管理界面的核心实现,负责管理用户界面和用户交互。该类通过继承CNetRequestDialog获得了网络请求处理能力,能够与服务器进行通信获取和更新任务数据。
#### 用户界面初始化
在OnInitDialog方法中,组件初始化了两个列表控件:m_LoopTaskList用于显示循环任务列表,m_subtaskList用于显示选中任务的子任务列表。根据当前语言设置,组件会动态设置界面文本,支持中文和英文两种语言。
```mermaid
flowchart TD
Start([OnInitDialog]) --> SetLanguage["设置界面语言"]
SetLanguage --> CreateList["创建任务列表控件"]
CreateList --> SetColumn["设置列表列"]
SetColumn --> InitData["初始化循环任务列表"]
InitData --> Return["返回TRUE"]
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L60-L136)
#### 任务删除功能
OnBnClickedBtnDeleteLoopTask方法处理删除按钮的点击事件。当用户选择一个或多个任务并点击删除按钮时,该方法会收集选中任务的ID,通过PostNetRequest发送删除请求到服务器,并在收到成功响应后从界面列表中移除相应任务。
```mermaid
sequenceDiagram
participant User as "用户"
participant UI as "CDialManageLoopTask"
participant Network as "CNetRequestDialog"
participant Server as "服务器"
User->>UI : 点击删除按钮
UI->>UI : 获取选中任务
UI->>Network : PostNetRequest(EN_CANCEL_LOOP_TASK_TRUST)
Network->>Server : 发送删除请求
Server-->>Network : 返回响应
Network->>UI : PreNetResponse
UI->>UI : 更新界面列表
UI-->>User : 显示操作结果
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L138-L193)
#### 任务选择与详情显示
OnNMClickListLoopTaskList方法处理任务列表项的点击事件。当用户点击某个任务时,该方法会更新右侧的详细信息显示,并通过PostNetRequest请求该任务的子任务列表数据。
```mermaid
flowchart TD
Click["点击任务列表项"] --> GetTaskID["获取任务ID"]
GetTaskID --> UpdateUI["更新界面显示"]
UpdateUI --> RequestSubTask["PostNetRequest(EN_REQ_DOWNLOAD_LOOP_SUB_TABLE)"]
RequestSubTask --> WaitResponse["等待服务器响应"]
WaitResponse --> ShowSubTask["显示子任务列表"]
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L202-L228)
**Section sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L1-L621)
### CTaskDataOper服务层分析
CTaskDataOper类是数据操作的核心服务层,负责与数据库的交互和业务逻辑处理。该类提供了创建不同类型任务、查询任务信息、插入任务包信息等方法。
#### 任务创建功能
Create1DTask、Create2DTask和Create3DTask方法分别用于创建一维、二维和三维任务。这些方法通过ADO数据库操作,将任务信息插入到相应的数据库表中。
```mermaid
classDiagram
class CTaskDataOper {
+Create1DTask(ST1DTaskParam)
+Create2DTask(ST2DTaskParam)
+Create3DTask(ST3DTaskParam)
+InsertTaskPacketInfo()
+InsertPlcStatusData()
+QueryARByTdID()
+QuerySptByAR()
}
class ST1DTaskParam {
+strTDName
+iSptID
+strTestPlace
+iStacking
+iTxWave
+iTxPeriod
+iSAInterval
}
class ST2DTaskParam {
+strTDName
+iSptID
+strTestPlace
+iStartElec
+iEndElec
+iEAmount
+iStacking
+iTxWave
+iTxPeriod
+iSAInterval
+iCableLayout
+iSkipCable
+iRollCnt
+fEspace
+fHoleSpace
+ucTestGRFlag
}
class ST3DTaskParam {
+strTDName
+iSptID
+strTestPlace
+iStacking
+iTxWave
+iTxPeriod
+iSAInterval
+iCableLayout
+iSkipCable
+ucTestGRFlag
}
CTaskDataOper --> ST1DTaskParam : "uses"
CTaskDataOper --> ST2DTaskParam : "uses"
CTaskDataOper --> ST3DTaskParam : "uses"
```
**Diagram sources**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L97-L667)
#### 任务包信息管理
InsertTaskPacketInfo方法用于插入任务包信息,包括循环次数、间隔时间和PLC ID等。该方法通过事务处理确保数据的一致性。
```mermaid
flowchart TD
Start["开始插入任务包信息"] --> BeginTrans["开始数据库事务"]
BeginTrans --> DeleteOld["删除旧的任务包信息"]
DeleteOld --> InsertMain["插入主任务包信息"]
InsertMain --> DeleteOldInfo["删除旧的任务包详情"]
DeleteOldInfo --> InsertDetails["插入任务包详情"]
InsertDetails --> Commit["提交事务"]
Commit --> End["完成"]
Commit --> Rollback["回滚事务"]
```
**Diagram sources**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L669-L715)
**Section sources**
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L1-L4455)
## 依赖分析
循环任务管理界面依赖于多个核心组件和服务。主要依赖关系包括:
```mermaid
graph TD
A[CDialManageLoopTask] --> B[CTaskDataOper]
A --> C[CNetRequestDialog]
A --> D[CFileOperTools]
B --> E[theApp.m_pConnection]
B --> F[theApp.m_NetWorkOper]
C --> G[theApp.m_NetWorkOper]
A --> H[g_iUILanguage]
A --> I[theApp]
style A fill:#f9f,stroke:#333
style B fill:#bbf,stroke:#333
style C fill:#f96,stroke:#333
```
**Diagram sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp)
- [NetRequestDialog.h](file://cpp/socket/NetRequestDialog.h)
**Section sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L1-L621)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L1-L4455)
## 性能考虑
循环任务管理界面在设计时考虑了多个性能因素。首先,任务列表的加载采用了分页机制,每次只加载指定时间范围内的任务,避免一次性加载过多数据导致界面卡顿。其次,网络请求采用了异步处理模式,通过消息映射机制在后台线程中处理网络通信,避免阻塞UI线程。此外,界面更新采用了增量更新策略,只更新发生变化的部分,减少不必要的重绘操作。
## 故障排除指南
在使用循环任务管理界面时,可能会遇到以下常见问题:
1. **任务列表无法加载**:检查网络连接是否正常,确保服务器正在运行。
2. **删除任务失败**:确认任务是否正在执行中,正在执行的任务无法删除。
3. **界面显示异常**:尝试重启应用程序,清除可能的界面状态错误。
4. **语言显示错误**:检查g_iUILanguage全局变量的设置是否正确。
**Section sources**
- [DialManageLoopTask.cpp](file://cpp/Views/DialManageLoopTask.cpp#L1-L621)
- [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L1-L4455)
## 结论
循环任务管理界面通过CDialManageLoopTask类的实现,提供了一个功能完整、交互友好的任务管理解决方案。该界面成功地将UI展示、用户交互和数据操作分离,遵循了良好的软件设计原则。通过与CTaskDataOper服务层的紧密协作,实现了对循环任务的全生命周期管理。未来可以考虑增加任务批量操作、更丰富的筛选条件和导出功能,进一步提升用户体验。