# 数据管理界面 **本文档引用的文件** - [datamngframe.cpp](file://cpp/Views/datamngframe.cpp) - [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp) - [DialListMeasuGR.cpp](file://cpp/Views/DialListMeasuGR.cpp) - [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp) - [DialListRealTimeMeasuGR.cpp](file://cpp/Views/DialListRealTimeMeasuGR.cpp) - [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp) - [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp) - [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp) - [TdManager.h](file://h/TdManager.h) - [TdManager.cpp](file://cpp/Managers/TdManager.cpp) - [DataOperator.h](file://h/DataOperator.h) - [TaskDataOper.h](file://h/TaskDataOper.h) - [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp) ## 目录 1. [数据管理框架](#数据管理框架) 2. [测量数据列表展示](#测量数据列表展示) 3. [实时数据刷新机制](#实时数据刷新机制) 4. [测量详情查看功能](#测量详情查看功能) 5. [实时监控界面行为](#实时监控界面行为) 6. [数据查询、过滤与导出](#数据查询过滤与导出) 7. [大数据量列表优化](#大数据量列表优化) 8. [操作指南](#操作指南) 9. [高级开发者指南](#高级开发者指南) ## 数据管理框架 数据管理框架的核心是`CDataMngFrame`类,它负责组织和管理数据管理界面的整体结构。该框架采用MDI(多文档界面)设计,通过分割窗口(Splitter Window)将界面分为左右两个视图:左侧为导航数据视图(`CNavDataView`),右侧为应用数据视图(`CAppDataView`)。 框架通过消息映射(`BEGIN_MESSAGE_MAP`)处理各种数据管理操作,如创建、删除、导出和刷新数据。当用户在导航树中选择一个数据项时,框架会根据数据类型(如2D电阻率、3D激电等)动态创建相应的应用视图,并加载和显示数据。 ```mermaid classDiagram class CDataMngFrame { +m_pNavDataView : CView* +m_pAppDataView : CView* +m_pDataOperator : CDataOperator* +OnCreateClient() bool +OnSchedule() LRESULT +ShowAppView() bool +ShowContentListByPageView() bool } class CDataOperator { +ShowRsp2DTdInfo() void +ShowIps2DpTdInfo() void +ShowSP2DTdInfo() void +LoadRsp2dRecordbyPage() void +LoadIpsp2dRecordbyPage() void +LoadSP2dRecordbyPage() void } CDataMngFrame --> CDataOperator : "使用" CDataMngFrame --> CView : "包含 m_pNavDataView" CDataMngFrame --> CView : "包含 m_pAppDataView" ``` **Diagram sources** - [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L49-L602) **Section sources** - [datamngframe.cpp](file://cpp/Views/datamngframe.cpp#L1-L800) ## 测量数据列表展示 测量数据列表的展示逻辑主要由`CDialListMeasuData`和`CDialListMeasuGR`两个类实现。`CDialListMeasuData`负责显示测量数据,而`CDialListMeasuGR`负责显示接地电阻信息。 `CDialListMeasuData`在`OnInitDialog`方法中初始化列表控件,设置列标题(如ID、A、B、M、N、Stack、K、V(mV)、I(mA)、R0(Ohm*m)等),并从数据库查询数据填充列表。它支持分页显示,通过“上一页”和“下一页”按钮进行导航。 ```mermaid flowchart TD A[初始化对话框] --> B[设置列表控件样式] B --> C[插入列标题] C --> D[查询数据库获取数据] D --> E{数据是否为空?} E --> |否| F[调用OnShowTdData显示数据] E --> |是| G[返回] F --> H[遍历数据向量] H --> I[格式化并插入列表项] I --> J[设置列表项文本] J --> K{是否遍历完成?} K --> |否| H K --> |是| L[结束] ``` **Diagram sources** - [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp#L52-L120) **Section sources** - [DialListMeasuData.cpp](file://cpp/Views/DialListMeasuData.cpp#L1-L333) - [DialListMeasuGR.cpp](file://cpp/Views/DialListMeasuGR.cpp#L1-L113) ## 实时数据刷新机制 实时数据的刷新机制由`CDialListRealTimeMeasureData`和`CDialListRealTimeMeasuGR`类实现。与静态数据列表不同,实时数据需要在测量过程中动态更新。 `CDialListRealTimeMeasureData`提供了三种数据更新方法: 1. `OnShowTdData`: 一次性清空并重新填充整个列表。 2. `OnShowTdDataAppend`: 在列表末尾追加新数据。 3. `OnShowTdDataUpdate`: 智能更新,先查找是否存在该数据,存在则更新,不存在则追加。 这种设计确保了在高频率数据更新场景下的流畅性和准确性。 ```mermaid sequenceDiagram participant Device as "测量设备" participant App as "应用程序" participant List as "实时数据列表" Device->>App : 发送测量数据包 App->>App : 解析数据包 App->>List : 调用OnShowTdDataUpdate List->>List : 查找ID匹配的列表项 alt 找到匹配项 List->>List : 更新现有项的数据 else 未找到匹配项 List->>List : 在末尾追加新项 end List->>List : 确保新项可见(EnsureVisible) List->>List : 更新界面 ``` **Diagram sources** - [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L171-L332) - [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L251-L332) **Section sources** - [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L1-L486) - [DialListRealTimeMeasuGR.cpp](file://cpp/Views/DialListRealTimeMeasuGR.cpp#L1-L244) ## 测量详情查看功能 测量详情的查看功能由`CDialMeasureDetailInfo`类实现。该类提供了一个包含“数据”和“接地电阻”两个标签页的对话框,允许用户在一个界面中查看任务的详细信息。 其核心逻辑在`OnInitDialog`方法中: 1. 根据传入的任务参数(`STRemTaskArg`),创建并初始化`CDialListMeasuTask`和`CDialListMeasuGR`两个子控件。 2. 分别调用`ShowPage(1)`和`GetGRRequest(m_stTaskArg)`从云端获取任务数据和接地电阻信息。 3. 通过标签页的切换事件(`OnSelchangeTabChg`)来显示或隐藏相应的子控件。 ```mermaid classDiagram class CDialMeasureDetailInfo { +m_dialListMeasuTask : CDialListMeasuTask +m_dialListMeasuGR : CDialListMeasuGR +OnInitDialog() bool +OnSelchangeTabChg() void } class CDialListMeasuTask { +ShowPage() void } class CDialListMeasuGR { +GetGRRequest() void } CDialMeasureDetailInfo --> CDialListMeasuTask CDialMeasureDetailInfo --> CDialListMeasuGR ``` **Diagram sources** - [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp#L56-L104) **Section sources** - [DialMeasureData.cpp](file://cpp/Views/DialMeasureData.cpp#L1-L2262) - [DialMeasureDetailInfo.cpp](file://cpp/Views/DialMeasureDetailInfo.cpp#L1-L186) ## 实时监控界面行为 实时监控界面由`CDialRealTimeMeasureData`类控制。该类不仅管理数据列表,还处理用户与测量过程的交互,如开始测量、暂停测量、单点测量等。 其行为逻辑如下: - **按钮状态管理**: 通过`SetBtnStatus`方法根据当前测量状态(如`EN_MEASU_BTN_MEASU_ALL`)启用或禁用按钮,防止用户进行无效操作。 - **测量命令发送**: 当用户点击“开始测量”时,`OnMeasureAll`方法会构造一个`STTrusteeTaskTable`结构体,并通过`PostNetRequest`发送到设备,启动测量任务。 - **数据接收与处理**: 重写`ProcRcvMeasuData`等方法来处理从设备接收的实时数据,并更新UI。 **Section sources** - [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp#L1-L1879) ## 数据查询、过滤与导出 数据查询、过滤和导出功能主要由`CTdManager`和`CDataOperator`两个核心类实现。 `CTdManager`作为数据管理器,提供了与数据库交互的底层接口: - **查询**: `ShowTdListByTz`、`ShowTdListByProject`等方法用于从数据库查询任务列表。 - **删除**: `DeleteRsp2DTd`、`DeleteIpsp2DTd`等方法用于删除不同类型的数据。 - **导入/导出**: `Import2DTdConToDB`、`ExportRsp2DTdToDAT`等方法用于数据的导入和导出。 `CDataOperator`则作为`CTdManager`的上层封装,为UI提供更便捷的调用接口。例如,`ExportRsp2DTdToExcel`方法会调用`CTdManager`的底层功能,将2D电阻率数据导出为Excel文件。 ```mermaid classDiagram class CDataOperator { +ExportRsp2DTdToExcel() UINT +ExportRsp2DTdToDAT() UINT +ExportRsp2DTdToCSV() UINT +ShowRsp2DTdInfo() void +LoadRsp2dRecordbyPage() void } class CTdManager { +ShowTdListByTz() bool +DeleteRsp2DTd() void +Import2DTdConToDB() bool +ExportRsp2DTdToDAT() UINT } CDataOperator --> CTdManager : "使用" ``` **Diagram sources** - [DataOperator.h](file://h/DataOperator.h#L29-L87) - [TdManager.h](file://h/TdManager.h#L33-L87) **Section sources** - [TdManager.h](file://h/TdManager.h#L1-L109) - [TdManager.cpp](file://cpp/Managers/TdManager.cpp#L1-L6839) - [DataOperator.h](file://h/DataOperator.h#L1-L174) ## 大数据量列表优化 在处理大数据量时,直接加载所有数据会导致界面卡顿。项目通过以下两种技术进行优化: 1. **分页加载**: `CDataOperator`类中的`LoadRsp2dRecordbyPage`等方法实现了分页查询。它接收一个起始ID和页大小,只从数据库加载指定范围的数据,显著减少了内存占用和加载时间。 2. **虚拟列表**: 虽然代码中未直接体现,但`CListCtrl`控件支持虚拟列表(Virtual List)模式。在这种模式下,控件不会存储所有数据,而是通过`LVN_GETDISPINFO`消息在需要显示某一行时,由程序动态提供该行的数据。这是一种处理海量数据的高效方式。 **Section sources** - [DataOperator.h](file://h/DataOperator.h#L76-L83) - [TaskDataOper.h](file://h/TaskDataOper.h#L378-L382) - [TaskDataOper.cpp](file://cpp/Operator/TaskDataOper.cpp#L418-L513) ## 操作指南 ### 初学者:数据查看与导出 1. **查看数据**: * 打开“数据管理”界面。 * 在左侧导航树中选择一个任务。 * 右侧会自动显示该任务的测量数据列表。 * 使用“上一页”和“下一页”按钮浏览不同页面的数据。 2. **导出数据**: * 在导航树中右键点击要导出的任务。 * 选择“导出”菜单下的格式,如“导出为Excel”或“导出为DAT文件”。 * 在弹出的对话框中选择保存路径,点击“保存”即可。 ## 高级开发者指南 ### 高频率数据更新场景下的UI线程安全处理 在实时监控等高频率数据更新场景下,数据接收通常在后台线程中进行,而UI更新必须在主线程(UI线程)中完成。为确保线程安全,项目采用了以下方案: 1. **消息传递机制**: 后台线程不直接操作UI控件,而是通过`PostMessage`或`PostNetRequest`向UI线程发送自定义消息(如`WM_MSG_UPDATE_TASK_LIST`)。 2. **UI线程处理**: UI线程的消息循环接收到消息后,调用相应的消息处理函数(如`OnShowTdDataUpdate`)来安全地更新列表控件。 这种“生产者-消费者”模式有效地隔离了数据处理和UI更新,避免了多线程访问共享资源导致的竞态条件和崩溃。 ```mermaid sequenceDiagram participant WorkerThread as "工作线程" participant UIThread as "UI线程" participant ListCtrl as "列表控件" WorkerThread->>WorkerThread : 接收测量数据 WorkerThread->>UIThread : PostMessage(WM_SHOW_TD_DATA_UPDATE, 数据指针) UIThread->>UIThread : 消息循环接收到消息 UIThread->>UIThread : 调用OnShowTdDataUpdate UIThread->>ListCtrl : 安全地更新列表项 ListCtrl->>UIThread : 更新完成 ``` **Section sources** - [DialListRealTimeMeasuData.cpp](file://cpp/Views/DialListRealTimeMeasuData.cpp#L344-L343) - [DialRealTimeMeasureData.cpp](file://cpp/Views/DialRealTimeMeasureData.cpp#L593-L594)