From 700ca509ba853d1615ea3e5c470d2532006f0e1e Mon Sep 17 00:00:00 2001
From: darker <mr.darker@163.com>
Date: 星期五, 17 一月 2025 15:21:34 +0800
Subject: [PATCH] 1. 添加报警管理器,新增设备名称

---
 SourceCode/Bond/Servo/Servo.vcxproj         |    4 
 SourceCode/Bond/Servo/AlarmManager.cpp      |  289 ++++++++++++++++++++++++++++++++
 SourceCode/Bond/Servo/Servo.vcxproj.filters |    6 
 SourceCode/Bond/Servo/AlarmManager.h        |  163 ++++++++++++++++++
 SourceCode/Bond/Servo/Servo.cpp             |   19 ++
 SourceCode/Bond/Servo/stdafx.h              |   22 ++
 SourceCode/Bond/Servo/ServoDlg.cpp          |    1 
 7 files changed, 504 insertions(+), 0 deletions(-)

diff --git a/SourceCode/Bond/Servo/AlarmManager.cpp b/SourceCode/Bond/Servo/AlarmManager.cpp
new file mode 100644
index 0000000..7864235
--- /dev/null
+++ b/SourceCode/Bond/Servo/AlarmManager.cpp
@@ -0,0 +1,289 @@
+#include "stdafx.h"
+#include "AlarmManager.h"
+#include <sstream>
+#include <iostream>
+#include <stdexcept>
+#include <ctime>
+
+// 常量
+const std::string DATABASE_FILE = R"(AlarmManager.db)";
+
+// 静态成员初始化
+std::mutex AlarmManager::m_mutex;
+
+// 获取单例实例
+AlarmManager& AlarmManager::getInstance() {
+    static AlarmManager instance;
+    return instance;
+}
+
+// 构造函数
+AlarmManager::AlarmManager() {
+	m_pDB = new BL::SQLiteDatabase();
+}
+
+// 析构函数
+AlarmManager::~AlarmManager() {
+    if (m_pDB != nullptr) {
+        delete m_pDB;
+        m_pDB = nullptr;
+    }
+}
+
+// 设置数据库连接
+void AlarmManager::setDatabase(BL::Database* db) {
+    std::lock_guard<std::mutex> lock(m_mutex);
+    m_pDB = db;
+}
+
+// 初始化报警表
+bool AlarmManager::initAlarmTable() {
+    char path[MAX_PATH];
+    GetModuleFileName(NULL, path, MAX_PATH);
+    std::string exePath(path);
+    std::string dbFileDir = exePath.substr(0, exePath.find_last_of("\\/")) + "\\DB";
+	if (!CreateDirectory(dbFileDir.c_str(), NULL) && ERROR_ALREADY_EXISTS != GetLastError()) {
+		throw std::runtime_error("Failed to create database directory.");
+	}
+
+    std::string dbFilePath = dbFileDir + "\\" + DATABASE_FILE;
+    if (!m_pDB->connect(dbFilePath, true)) {
+        throw std::runtime_error("Failed to connect to database.");
+    }
+
+    const std::string createTableQuery = R"(
+        CREATE TABLE IF NOT EXISTS alarms (
+            id TEXT NOT NULL,
+            device_name TEXT NOT NULL,
+            description TEXT NOT NULL,
+            start_time DATETIME NOT NULL,
+            end_time DATETIME NOT NULL
+        )
+    )";
+
+    return m_pDB->executeQuery(createTableQuery);
+}
+
+// 销毁报警表
+void AlarmManager::termAlarmTable() {
+    if (m_pDB != nullptr) {
+		m_pDB->disconnect();
+    }
+}
+
+// 销毁报警表
+bool AlarmManager::destroyAlarmTable() {
+	if (!m_pDB) {
+		throw std::runtime_error("Database connection is not set.");
+	}
+	const std::string dropTableQuery = "DROP TABLE IF EXISTS alarms";
+	return m_pDB->executeQuery(dropTableQuery);
+}
+
+// 添加报警
+bool AlarmManager::addAlarm(const std::string& id, const std::string& deviceName, 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, device_name, description, start_time, end_time) VALUES ("
+        << "'" << id << "', "
+		<< "'" << deviceName << "', "
+        << "'" << 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, device_name, 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, device_name, 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, device_name, 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, device_name, 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, device_name, 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, device_name, 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& id,
+    const std::string& deviceName,
+    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, device_name, description, start_time, end_time FROM alarms WHERE 1=1";
+
+	if (!id.empty()) {
+		query << " AND id = '" << id << "'";
+	}
+	if (!deviceName.empty()) {
+		query << " AND device_name LIKE '%" << deviceName << "%'";
+	}
+    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& id,
+    const std::string& deviceName,
+    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 (!id.empty()) {
+		query << " AND id = '" << id << "'";
+    }
+    if (!deviceName.empty()) {
+		query << " AND device_name LIKE '%" << deviceName << "%'";
+    }
+    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& deviceName, 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 device_name = '" << deviceName << "'"
+        << " AND description = '" << description << "'"
+        << " AND start_time = '" << startTime << "'";
+
+    return m_pDB->executeQuery(query.str());
+}
+
+// 清理旧报警数据
+void AlarmManager::cleanOldAlarms(int daysToKeep, const std::string& deviceName) {
+    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')";
+
+    if (!deviceName.empty()) {
+        query << " AND device_name = '" << deviceName << "'";
+    }
+    m_pDB->executeQuery(query.str());
+}
diff --git a/SourceCode/Bond/Servo/AlarmManager.h b/SourceCode/Bond/Servo/AlarmManager.h
new file mode 100644
index 0000000..28bea98
--- /dev/null
+++ b/SourceCode/Bond/Servo/AlarmManager.h
@@ -0,0 +1,163 @@
+#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 initAlarmTable();
+
+	/**
+	 * 销毁报警表
+	 */
+    void termAlarmTable();
+
+	/**
+	 * 销毁报警表
+	 * @return 成功返回true,失败返回false
+	 */
+    bool destroyAlarmTable();
+
+    /**
+     * 添加报警
+     * @param id 报警ID
+	 * @param deviceName 设备名称
+     * @param description 报警描述
+     * @param startTime 报警开始时间
+     * @param endTime 报警结束时间
+     * @return 成功返回true,失败返回false
+     */
+    bool addAlarm(const std::string& id, const std::string& deviceName, 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 id 报警ID的筛选条件
+	 * @param deviceName 设备名称的筛选条件
+     * @param description 报警描述的筛选条件
+     * @param startTime 起始时间筛选条件
+     * @param endTime 结束时间筛选条件
+     * @param pageNumber 页码
+     * @param pageSize 每页的记录数
+     * @return 包含筛选后报警数据的二维字符串向量
+     */
+    std::vector<std::vector<std::string>> getFilteredAlarms(
+        const std::string& id,
+        const std::string& deviceName,
+        const std::string& description,
+        const std::string& startTime,
+        const std::string& endTime,
+        int pageNumber,
+        int pageSize);
+
+    /**
+     * 获取符合条件的报警总数
+     * @param id 报警ID的筛选条件
+	 * @param deviceName 设备名称的筛选条件
+     * @param description 报警描述的筛选条件
+     * @param startTime 起始时间筛选条件
+     * @param endTime 结束时间筛选条件
+     * @return 符合条件的报警总数
+     */
+    int getTotalAlarmCount(
+        const std::string& id,
+        const std::string& deviceName,
+        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& deviceName, const std::string& description, const std::string& startTime, const std::string& newEndTime);
+
+    /**
+     * 清理旧报警
+     * @param daysToKeep 保留的天数
+	 * @param deviceName 设备名称
+     */
+    void cleanOldAlarms(int daysToKeep = 30, const std::string& deviceName = "");
+
+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/Servo/Servo.cpp b/SourceCode/Bond/Servo/Servo.cpp
index 550391a..495b5e7 100644
--- a/SourceCode/Bond/Servo/Servo.cpp
+++ b/SourceCode/Bond/Servo/Servo.cpp
@@ -6,6 +6,7 @@
 #include "Servo.h"
 #include "ServoDlg.h"
 #include "ServoGraph.h"
+#include "AlarmManager.h"
 
 // 声明全局变量,用于管理 GDI+ 初始化
 ULONG_PTR g_diplusToken;
@@ -101,6 +102,21 @@
 	InitGDIPlus();
 
 
+	// 初始化报警管理器
+	try {
+		if (!AlarmManager::getInstance().initAlarmTable()) {
+			AfxMessageBox("初始化报警管理器失败!");
+			return FALSE;
+		}
+	}
+	catch (const std::exception& ex) {
+		CString errorMsg;
+		errorMsg.Format(_T("初始化报警管理器失败:%s"), CString(ex.what()));
+		AfxMessageBox(errorMsg, MB_ICONERROR);
+		return FALSE;
+	}
+
+
 	CServoDlg dlg;
 	m_pMainWnd = &dlg;
 	INT_PTR nResponse = dlg.DoModal();
@@ -140,6 +156,9 @@
 	// 清理 GDI+
 	TermGDIPlus();
 
+	// 销毁报警表
+	AlarmManager::getInstance().termAlarmTable();
+
 	return CWinApp::ExitInstance();
 }
 
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj b/SourceCode/Bond/Servo/Servo.vcxproj
index d0153cb..695b5e7 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj
+++ b/SourceCode/Bond/Servo/Servo.vcxproj
@@ -115,6 +115,7 @@
       <Optimization>Disabled</Optimization>
       <PreprocessorDefinitions>_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -168,6 +169,7 @@
       <IntrinsicFunctions>true</IntrinsicFunctions>
       <PreprocessorDefinitions>_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
       <SDLCheck>true</SDLCheck>
+      <AdditionalIncludeDirectories>.;..;..\DatabaseSDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -190,6 +192,7 @@
     <Text Include="ReadMe.txt" />
   </ItemGroup>
   <ItemGroup>
+    <ClInclude Include="AlarmManager.h" />
     <ClInclude Include="BlButton.h" />
     <ClInclude Include="Common.h" />
     <ClInclude Include="Configuration.h" />
@@ -209,6 +212,7 @@
     <ClInclude Include="targetver.h" />
   </ItemGroup>
   <ItemGroup>
+    <ClCompile Include="AlarmManager.cpp" />
     <ClCompile Include="BlButton.cpp" />
     <ClCompile Include="Configuration.cpp" />
     <ClCompile Include="Context.cpp" />
diff --git a/SourceCode/Bond/Servo/Servo.vcxproj.filters b/SourceCode/Bond/Servo/Servo.vcxproj.filters
index 1f263f5..5bc0cc3 100644
--- a/SourceCode/Bond/Servo/Servo.vcxproj.filters
+++ b/SourceCode/Bond/Servo/Servo.vcxproj.filters
@@ -69,6 +69,9 @@
     <ClInclude Include="SecsTestDlg.h">
       <Filter>澶存枃浠�</Filter>
     </ClInclude>
+    <ClInclude Include="AlarmManager.h">
+      <Filter>澶存枃浠�</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Servo.cpp">
@@ -113,6 +116,9 @@
     <ClCompile Include="SecsTestDlg.cpp">
       <Filter>婧愭枃浠�</Filter>
     </ClCompile>
+    <ClCompile Include="AlarmManager.cpp">
+      <Filter>婧愭枃浠�</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Servo.rc">
diff --git a/SourceCode/Bond/Servo/ServoDlg.cpp b/SourceCode/Bond/Servo/ServoDlg.cpp
index 07cb989..f349071 100644
--- a/SourceCode/Bond/Servo/ServoDlg.cpp
+++ b/SourceCode/Bond/Servo/ServoDlg.cpp
@@ -9,6 +9,7 @@
 #include "Common.h"
 #include "Log.h"
 #include "SecsTestDlg.h"
+#include "AlarmManager.h"
 #include <chrono>
 #include <thread>
 #include <cmath>
diff --git a/SourceCode/Bond/Servo/stdafx.h b/SourceCode/Bond/Servo/stdafx.h
index 9b9a811..4768d25 100644
--- a/SourceCode/Bond/Servo/stdafx.h
+++ b/SourceCode/Bond/Servo/stdafx.h
@@ -33,10 +33,32 @@
 
 #include <afxcontrolbars.h>     // 功能区和控件条的 MFC 支持
 
+
 // GDI+
 #include <gdiplus.h>
 using namespace Gdiplus;
 
+
+// 数据库模块
+#include "..\DatabaseSDK\include\Database.h"
+#include "..\DatabaseSDK\include\MySQLDatabase.h"
+#include "..\DatabaseSDK\include\SQLiteDatabase.h"
+
+#if defined(_WIN64)
+#if defined(_DEBUG)
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Debug\\DatabaseEx.lib")
+#else
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\x64\\Release\\DatabaseEx.lib")
+#endif
+#else
+#if defined(_DEBUG)
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Debug\\DatabaseEx.lib")
+#else
+#pragma comment(lib, "..\\DatabaseSDK\\lib\\Win32\\Release\\DatabaseEx.lib")
+#endif
+#endif
+
+
 #include "..\RxWindows1.0\include\RxWindowsLib.h"
 #include "..\HSMSSDK\Include\HSMSSDK.h"
 

--
Gitblit v1.9.3