From be5908615aa5f61c478cf3fa3823dc07c9b1d70f Mon Sep 17 00:00:00 2001
From: LAPTOP-T815PCOQ\25526 <mr.liuyang@126.com>
Date: 星期四, 12 十二月 2024 18:08:34 +0800
Subject: [PATCH] 1. 添加报警表 2. 读取数据库中的报警表显示在界面上,或添加报警数据

---
 SourceCode/Bond/BondEq/DBManager/AlarmManager.cpp |  232 +++++++++++++++++++++++++++++
 SourceCode/Bond/BondEq/DBManager/AlarmManager.h   |  142 +++++++++++++++++
 SourceCode/Bond/BondEq/stdafx.h                   |    1 
 SourceCode/Bond/BondEq/BondEqDlg.cpp              |   16 ++
 SourceCode/Bond/BondEq/BondEq.vcxproj             |    2 
 SourceCode/Bond/BondEq/CPageAlarm.cpp             |   32 +++
 6 files changed, 424 insertions(+), 1 deletions(-)

diff --git a/SourceCode/Bond/BondEq/BondEq.vcxproj b/SourceCode/Bond/BondEq/BondEq.vcxproj
index c76af03..a43d4f8 100644
--- a/SourceCode/Bond/BondEq/BondEq.vcxproj
+++ b/SourceCode/Bond/BondEq/BondEq.vcxproj
@@ -220,6 +220,7 @@
     <ClInclude Include="Common.h" />
     <ClInclude Include="Configuration.h" />
     <ClInclude Include="CPanelProject.h" />
+    <ClInclude Include="DBManager\AlarmManager.h" />
     <ClInclude Include="DBManager\AxisManager.h" />
     <ClInclude Include="DBManager\SystemLogManager.h" />
     <ClInclude Include="DBManager\UserManager.h" />
@@ -294,6 +295,7 @@
     <ClCompile Include="CProjectPageRemoteEqs.cpp" />
     <ClCompile Include="Configuration.cpp" />
     <ClCompile Include="CPanelProject.cpp" />
+    <ClCompile Include="DBManager\AlarmManager.cpp" />
     <ClCompile Include="DBManager\AxisManager.cpp" />
     <ClCompile Include="DBManager\SystemLogManager.cpp" />
     <ClCompile Include="DBManager\UserManager.cpp" />
diff --git a/SourceCode/Bond/BondEq/BondEqDlg.cpp b/SourceCode/Bond/BondEq/BondEqDlg.cpp
index 9aa2398..f381744 100644
--- a/SourceCode/Bond/BondEq/BondEqDlg.cpp
+++ b/SourceCode/Bond/BondEq/BondEqDlg.cpp
@@ -229,6 +229,22 @@
 		return FALSE;
 	}
 
+	// 初始化报警模块
+	AlarmManager& alarmManager = AlarmManager::getInstance();
+	alarmManager.setDatabase(db.get());
+	try {
+		if (!alarmManager.initializeAlarmTable()) {
+			AfxMessageBox("初始化报警模块失败!");
+			return FALSE;
+		}
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("初始化报警模块失败:%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+		return FALSE;
+	}
+
 	// 设置配方文件夹路径
 	RecipeManager& recipeManager = RecipeManager::getInstance();
 	std::string strRecipePath =  CToolUnits::getCurrentExePath() + _T("\\Recipe");
diff --git a/SourceCode/Bond/BondEq/CPageAlarm.cpp b/SourceCode/Bond/BondEq/CPageAlarm.cpp
index 0d76752..d84faef 100644
--- a/SourceCode/Bond/BondEq/CPageAlarm.cpp
+++ b/SourceCode/Bond/BondEq/CPageAlarm.cpp
@@ -158,6 +158,8 @@
 	CAlarmMonitor* pMonitor = (CAlarmMonitor*)theApp.m_model.getBonder().GetComponent("警告信息");
 
 	pMonitor->Lock();
+
+#if 0
 	std::map<int, CAlarm*>& alarmings = pMonitor->getAlarmingMap();
 	std::list< CAlarm*>& alarms = pMonitor->getAlarmRecords();
 
@@ -167,6 +169,20 @@
 	for (auto item : alarms) {
 		AddAlarm(pMonitor, item);
 	}
+#else
+	// 获取报警数据
+	auto vecData = AlarmManager::getInstance().getAllAlarms();
+
+	// 填充数据
+	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
+	for (auto item : vecData) {
+		pListCtrl->InsertItem(0, _T(""));
+		pListCtrl->SetItemText(0, 1, item[0].c_str());
+		pListCtrl->SetItemText(0, 2, item[1].c_str());
+		pListCtrl->SetItemText(0, 3, item[2].c_str());
+		pListCtrl->SetItemText(0, 4, item[3].c_str());
+	}
+#endif // 0
 
 	pMonitor->Unlock();
 }
@@ -186,6 +202,12 @@
 	if (pAlarm->getOffTime() > 0) {
 		pListCtrl->SetItemText(0, 4, CToolUnits::timeToString2(pAlarm->getOffTime()).c_str());
 	}
+
+	AlarmManager::getInstance().addAlarm(
+		std::to_string(pAlarm->getId()).c_str(), 
+		pMonitor->getAlarmText(pAlarm->getId()),
+		CToolUnits::timeToString2(pAlarm->getOnTime()).c_str(),
+		CToolUnits::timeToString2(pAlarm->getOffTime()).c_str());
 }
 
 void CPageAlarm::UpdateAlarm(CAlarmMonitor* pMonitor, CAlarm* pAlarm)
@@ -198,6 +220,12 @@
 		if (pListCtrl->GetItemData(i) == (DWORD_PTR)pAlarm) {
 			if (pAlarm->getOffTime() > 0) {
 				pListCtrl->SetItemText(i, 4, CToolUnits::timeToString2(pAlarm->getOffTime()).c_str());
+
+				AlarmManager::getInstance().updateAlarmEndTime(
+					std::to_string(pAlarm->getId()).c_str(),
+					pMonitor->getAlarmText(pAlarm->getId()),
+					CToolUnits::timeToString2(pAlarm->getOnTime()).c_str(),
+					CToolUnits::timeToString2(pAlarm->getOffTime()).c_str());
 			}
 		}
 	}
@@ -208,7 +236,9 @@
 	CListCtrl* pListCtrl = (CListCtrl*)GetDlgItem(IDC_LIST_ALARM);
 	for (int i = 0; i < pListCtrl->GetItemCount(); i++) {
 		CAlarm* pAlarm = (CAlarm*)pListCtrl->GetItemData(i);
-		pAlarm->release();
+		if (pAlarm != nullptr) {
+			pAlarm->release();
+		}
 	}
 
 	return CDialogEx::DestroyWindow();
diff --git a/SourceCode/Bond/BondEq/DBManager/AlarmManager.cpp b/SourceCode/Bond/BondEq/DBManager/AlarmManager.cpp
new file mode 100644
index 0000000..042dce9
--- /dev/null
+++ b/SourceCode/Bond/BondEq/DBManager/AlarmManager.cpp
@@ -0,0 +1,232 @@
+#include "stdafx.h"
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+#include <ctime>
+
+// 静态成员初始化
+std::mutex AlarmManager::m_mutex;
+
+// 获取单例实例
+AlarmManager& AlarmManager::getInstance() {
+    static AlarmManager instance;
+    return instance;
+}
+
+// 构造函数
+AlarmManager::AlarmManager() : m_pDB(nullptr) {}
+
+// 析构函数
+AlarmManager::~AlarmManager() {
+    m_pDB = nullptr;
+}
+
+// 设置数据库连接
+void AlarmManager::setDatabase(BL::Database* db) {
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_pDB = db;
+}
+
+// 初始化报警表
+bool AlarmManager::initializeAlarmTable() {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    const std::string createTableQuery = R"(
+        CREATE TABLE IF NOT EXISTS alarms (
+            id TEXT NOT NULL,
+            description TEXT NOT NULL,
+            start_time DATETIME NOT NULL,
+            end_time DATETIME NOT NULL
+        )
+    )";
+
+    return m_pDB->executeQuery(createTableQuery);
+}
+
+// 添加报警
+bool AlarmManager::addAlarm(const std::string& id, const std::string& description, const std::string& startTime, const std::string& endTime) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "INSERT INTO alarms (id, description, start_time, end_time) VALUES ("
+        << "'" << id << "', "
+        << "'" << description << "', "
+        << "'" << startTime << "', "
+        << "'" << endTime << "')";
+
+    std::lock_guard<std::mutex> lock(m_mutex);
+    return m_pDB->executeQuery(query.str());
+}
+
+// 查询所有报警数据
+std::vector<std::vector<std::string>> AlarmManager::getAllAlarms() {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    const std::string query = "SELECT id, description, start_time, end_time FROM alarms";
+    return m_pDB->fetchResults(query);
+}
+
+// 根据报警ID查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsById(const std::string& id) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms WHERE id = '" << id << "'";
+    return m_pDB->fetchResults(query.str());
+}
+
+// 根据描述查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByDescription(const std::string& description) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms WHERE description LIKE '%" << description << "%'";
+    return m_pDB->fetchResults(query.str());
+}
+
+// 根据时间范围查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByTimeRange(
+    const std::string& startTime, const std::string& endTime) {
+
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms WHERE 1=1";
+
+    if (!startTime.empty()) {
+        query << " AND start_time >= '" << startTime << "'";
+    }
+    if (!endTime.empty()) {
+        query << " AND end_time <= '" << endTime << "'";
+    }
+
+    return m_pDB->fetchResults(query.str());
+}
+
+// 根据ID、开始时间和结束时间查询报警
+std::vector<std::vector<std::string>> AlarmManager::getAlarmsByIdAndTimeRange(
+    const std::string& id, const std::string& startTime, const std::string& endTime) {
+
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms WHERE id = '" << id << "'";
+
+    if (!startTime.empty()) {
+        query << " AND start_time >= '" << startTime << "'";
+    }
+    if (!endTime.empty()) {
+        query << " AND end_time <= '" << endTime << "'";
+    }
+
+    return m_pDB->fetchResults(query.str());
+}
+
+// 分页查询报警数据
+std::vector<std::vector<std::string>> AlarmManager::getAlarms(int startPosition, int count) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms LIMIT " << count << " OFFSET " << startPosition;
+    return m_pDB->fetchResults(query.str());
+}
+
+// 筛选报警数据
+std::vector<std::vector<std::string>> AlarmManager::getFilteredAlarms(
+    const std::string& description,
+    const std::string& startTime,
+    const std::string& endTime,
+    int pageNumber,
+    int pageSize) {
+
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT id, description, start_time, end_time FROM alarms WHERE 1=1";
+
+    if (!description.empty()) {
+        query << " AND description LIKE '%" << description << "%'";
+    }
+    if (!startTime.empty()) {
+        query << " AND start_time >= '" << startTime << "'";
+    }
+    if (!endTime.empty()) {
+        query << " AND end_time <= '" << endTime << "'";
+    }
+
+    int offset = (pageNumber - 1) * pageSize;
+    query << " ORDER BY start_time DESC LIMIT " << pageSize << " OFFSET " << offset;
+
+    return m_pDB->fetchResults(query.str());
+}
+
+// 获取符合条件的报警总数
+int AlarmManager::getTotalAlarmCount(
+    const std::string& description,
+    const std::string& startTime,
+    const std::string& endTime) {
+
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "SELECT COUNT(*) FROM alarms WHERE 1=1";
+
+    if (!description.empty()) {
+        query << " AND description LIKE '%" << description << "%'";
+    }
+    if (!startTime.empty()) {
+        query << " AND start_time >= '" << startTime << "'";
+    }
+    if (!endTime.empty()) {
+        query << " AND end_time <= '" << endTime << "'";
+    }
+
+    auto results = m_pDB->fetchResults(query.str());
+    return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0;
+}
+
+// 更新报警的结束时间
+bool AlarmManager::updateAlarmEndTime(const std::string& id, const std::string& description, const std::string& startTime, const std::string& newEndTime) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "UPDATE alarms SET end_time = '" << newEndTime << "'"
+        << " WHERE id = '" << id << "'"
+        << " AND description = '" << description << "'"
+        << " AND start_time = '" << startTime << "'";
+
+    return m_pDB->executeQuery(query.str());
+}
+
+// 清理旧报警数据
+void AlarmManager::cleanOldAlarms(int daysToKeep) {
+    if (!m_pDB) {
+        throw std::runtime_error("Database connection is not set.");
+    }
+
+    std::ostringstream query;
+    query << "DELETE FROM alarms WHERE end_time < datetime('now', '-" << daysToKeep << " days')";
+    m_pDB->executeQuery(query.str());
+}
diff --git a/SourceCode/Bond/BondEq/DBManager/AlarmManager.h b/SourceCode/Bond/BondEq/DBManager/AlarmManager.h
new file mode 100644
index 0000000..bbe3e3a
--- /dev/null
+++ b/SourceCode/Bond/BondEq/DBManager/AlarmManager.h
@@ -0,0 +1,142 @@
+#ifndef ALARM_MANAGER_H
+#define ALARM_MANAGER_H
+
+#include <string>
+#include <vector>
+#include <mutex>
+#include "Database.h"
+
+class AlarmManager {
+public:
+    /**
+     * 获取单例实例
+     * @return AlarmManager实例的引用
+     */
+    static AlarmManager& getInstance();
+
+    /**
+     * 设置数据库连接
+     * @param db 数据库连接的指针
+     */
+    void setDatabase(BL::Database* db);
+
+    /**
+     * 初始化报警表
+     * @return 成功返回true,失败返回false
+     */
+    bool initializeAlarmTable();
+
+    /**
+     * 添加报警
+     * @param id 报警ID
+     * @param description 报警描述
+     * @param startTime 报警开始时间
+     * @param endTime 报警结束时间
+     * @return 成功返回true,失败返回false
+     */
+    bool addAlarm(const std::string& id, const std::string& description, const std::string& startTime, const std::string& endTime);
+
+    /**
+     * 查询所有报警数据
+     * @return 包含所有报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getAllAlarms();
+
+    /**
+     * 根据报警ID查询报警
+     * @param id 报警ID
+     * @return 包含筛选后报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getAlarmsById(const std::string& id);
+
+    /**
+     * 根据描述查询报警
+     * @param description 报警描述的筛选条件
+     * @return 包含筛选后报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getAlarmsByDescription(const std::string& description);
+
+    /**
+     * 根据时间范围查询报警
+     * @param startTime 起始时间
+     * @param endTime 结束时间
+     * @return 包含查询结果的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getAlarmsByTimeRange(
+        const std::string& startTime, const std::string& endTime);
+
+	/**
+	* 根据ID和时间范围查询报警
+	 * @param id 报警ID
+	 * @param startTime 起始时间
+	 * @param endTime 结束时间
+	 * @return 包含查询结果的二维字符串向量
+	 */
+    std::vector<std::vector<std::string>> getAlarmsByIdAndTimeRange(
+        const std::string& id, const std::string& startTime, const std::string& endTime);
+
+    /**
+     * 获取报警数据
+     * @param startPosition 起始位置
+     * @param count 获取的记录数量
+     * @return 包含报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getAlarms(int startPosition, int count);
+
+    /**
+     * 获取筛选后的报警数据
+     * @param description 报警描述的筛选条件
+     * @param startTime 起始时间筛选条件
+     * @param endTime 结束时间筛选条件
+     * @param pageNumber 页码
+     * @param pageSize 每页的记录数
+     * @return 包含筛选后报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getFilteredAlarms(
+        const std::string& description,
+        const std::string& startTime,
+        const std::string& endTime,
+        int pageNumber,
+        int pageSize);
+
+    /**
+     * 获取符合条件的报警总数
+     * @param description 报警描述的筛选条件
+     * @param startTime 起始时间筛选条件
+     * @param endTime 结束时间筛选条件
+     * @return 符合条件的报警总数
+     */
+    int getTotalAlarmCount(
+        const std::string& description,
+        const std::string& startTime,
+        const std::string& endTime);
+
+	/**
+	 * 更新报警结束时间
+	 * @param id 报警ID
+	 * @param description 报警描述
+	 * @param startTime 报警开始时间
+	 * @param newEndTime 新的报警结束时间
+	 * @return 成功返回true,失败返回false
+	 */
+    bool updateAlarmEndTime(const std::string& id, const std::string& description, const std::string& startTime, const std::string& newEndTime);
+
+    /**
+     * 清理旧报警
+     * @param daysToKeep 保留的天数
+     */
+    void cleanOldAlarms(int daysToKeep = 30);
+
+private:
+    AlarmManager();
+    ~AlarmManager();
+
+    // 禁止拷贝和赋值
+    AlarmManager(const AlarmManager&) = delete;
+    AlarmManager& operator=(const AlarmManager&) = delete;
+
+    BL::Database* m_pDB;
+    static std::mutex m_mutex;
+};
+
+#endif // ALARM_MANAGER_H
\ No newline at end of file
diff --git a/SourceCode/Bond/BondEq/stdafx.h b/SourceCode/Bond/BondEq/stdafx.h
index ed3a40f..95c78f8 100644
--- a/SourceCode/Bond/BondEq/stdafx.h
+++ b/SourceCode/Bond/BondEq/stdafx.h
@@ -51,6 +51,7 @@
 #include "UserManager.h"
 #include "RecipeManager.h"
 #include "SystemLogManager.h"
+#include "AlarmManager.h"
 
 // 控件样式
 static UINT g_nGridFixCellColor = RGB(144, 200, 246);

--
Gitblit v1.9.3