chenluhua1980
8 天以前 b25ce186da97a1a774ddf89504f97d8c244fda66
SourceCode/Bond/Servo/AlarmManager.cpp
@@ -1,6 +1,7 @@
#include "stdafx.h"
#include "stdafx.h"
#include "Common.h"
#include "AlarmManager.h"
#include "Log.h"
#include <sstream>
#include <fstream>
#include <iostream>
@@ -8,25 +9,26 @@
#include <ctime>
#include <iomanip>
#include <random>
#include <chrono>
// 常量
// 常量
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;
@@ -34,7 +36,7 @@
    }
}
// 初始化报警表
// 初始化报警表
bool AlarmManager::initAlarmTable() {
    char path[MAX_PATH];
    GetModuleFileName(NULL, path, MAX_PATH);
@@ -49,7 +51,7 @@
        throw std::runtime_error("Failed to connect to database.");
    }
    // 创建设备表
    // 创建设备表
    const std::string createDevicesTableQuery = R"(
        CREATE TABLE IF NOT EXISTS devices (
            device_id TEXT PRIMARY KEY NOT NULL,
@@ -60,7 +62,7 @@
        return false;
    }
    // 创建单元表,设备ID和单元ID组合作为主键
    // 创建单元表,设备ID和单元ID组合作为主键
    const std::string createUnitsTableQuery = R"(
        CREATE TABLE IF NOT EXISTS units (
            device_id TEXT NOT NULL,
@@ -74,7 +76,7 @@
        return false;
    }
    // 创建报警表,报警记录的alarm_event_id是主键
    // 创建报警表,报警记录的alarm_event_id是主键
    const std::string createAlarmsTableQuery = R"(
        CREATE TABLE IF NOT EXISTS alarms (
            alarm_event_id INTEGER PRIMARY KEY AUTOINCREMENT,
@@ -93,8 +95,9 @@
        return false;
    }
    // 设备列表 (ID -> 名称)
    // 设备列表 (ID -> 名称)
    std::vector<std::pair<int, std::string>> devices = {
        {0, "Software"},
        {EQ_ID_LOADPORT1, EQ_NAME_LOADPORT1},
        {EQ_ID_LOADPORT2, EQ_NAME_LOADPORT2},
        {EQ_ID_LOADPORT3, EQ_NAME_LOADPORT3},
@@ -113,12 +116,12 @@
        {EQ_ID_OPERATOR_REMOVE, EQ_NAME_OPERATOR_REMOVE}
    };
    // 插入 devices 和对应的默认 unit
    // 插入 devices 和对应的默认 unit
    for (const auto& dev : devices) {
        int nDeviceId = dev.first;
        const std::string& strDeviceName = dev.second;
        // 插入设备
        // 插入设备
        std::ostringstream ossDev;
        ossDev << "INSERT OR IGNORE INTO devices (device_id, device_name) VALUES("
            << nDeviceId << ", '" << strDeviceName << "')";
@@ -126,7 +129,7 @@
            return false;
        }
        // 插入默认单元 (unit_id = 0, unit_name = device_name)
        // 插入默认单元 (unit_id = 0, unit_name = device_name)
        std::ostringstream ossUnit;
        ossUnit << "INSERT OR IGNORE INTO units (device_id, unit_id, unit_name) VALUES("
            << nDeviceId << ", 0, '" << strDeviceName << "')";
@@ -138,14 +141,14 @@
    return true;
}
// 销毁报警表
// 销毁报警表
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.");
@@ -154,9 +157,9 @@
   return m_pDB->executeQuery(dropTableQuery);
}
// 插入模拟数据
// 插入模拟数据
void AlarmManager::insertMockData() {
    // 插入设备数据
    // 插入设备数据
    for (int i = 1; i <= 3; ++i) {
        std::string deviceName = "Device" + std::to_string(i);
        std::stringstream query;
@@ -166,7 +169,7 @@
        }
    }
    // 插入单元数据
    // 插入单元数据
    for (int i = 1; i <= 3; ++i) {
        for (int j = 0; j <= 3; ++j) {
            int unitId = j;
@@ -175,8 +178,8 @@
            std::stringstream query;
            query << "INSERT INTO units (device_id, unit_id, unit_name) VALUES ('"
                << deviceId << "', '"   // 插入设备ID,确保是字符串
                << unitId << "', '"     // 插入单元ID,确保是字符串
                << deviceId << "', '"   // 插入设备ID,确保是字符串
                << unitId << "', '"     // 插入单元ID,确保是字符串
                << unitName << "');";
            if (!m_pDB->executeQuery(query.str())) {
@@ -186,7 +189,7 @@
    }
    /*
    // 初始化随机数生成器
    // 初始化随机数生成器
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_int_distribution<> deviceDis(1, 3);
@@ -195,7 +198,7 @@
    std::uniform_int_distribution<> severityDis(0, 3);
    std::vector<std::string> descriptions = { "Overheat", "Sensor failure", "Power outage" };
    // 时间相关
    // 时间相关
    auto now = std::chrono::system_clock::now();
    auto start_time = std::chrono::system_clock::to_time_t(now);
    auto end_time = std::chrono::system_clock::to_time_t(now + std::chrono::minutes(10));
@@ -205,13 +208,13 @@
    localtime_s(&start_tm, &start_time);
    localtime_s(&end_tm, &end_time);
    // 插入模拟数据
    // 插入模拟数据
    for (int i = 0; i < 10; ++i) {
        int deviceId = deviceDis(gen);          // 随机设备ID
        int unitId = unitDis(gen);              // 随机单元ID
        int errorCode = errorCodeDis(gen);      // 随机错误码
        int severityLevel = severityDis(gen);   // 随机生成报警等级
        std::string description = descriptions[errorCodeDis(gen) % descriptions.size()];  // 随机报警描述
        int deviceId = deviceDis(gen);          // 随机设备ID
        int unitId = unitDis(gen);              // 随机单元ID
        int errorCode = errorCodeDis(gen);      // 随机错误码
        int severityLevel = severityDis(gen);   // 随机生成报警等级
        std::string description = descriptions[errorCodeDis(gen) % descriptions.size()];  // 随机报警描述
        std::stringstream query;
        query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) "
@@ -226,38 +229,38 @@
    */
}
// 添加报警信息
// 添加报警信息
bool AlarmManager::addAlarm(const AlarmData& alarmData, int& alarmEventId) {
    if (!m_pDB) {
        return false;
    }
    #if 0
        // 开始事务
        // 开始事务
        m_pDB->executeQuery("BEGIN TRANSACTION;");
    
        // 构建插入查询
        // 构建插入查询
        std::ostringstream query;
        query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) VALUES ("
            << alarmData.nId << ", "              // 错误码
            << alarmData.nSeverityLevel << ", "   // 报警等级
            << alarmData.nDeviceId << ", "        // 设备ID
            << alarmData.nUnitId << ", '"         // 单元ID
            << alarmData.strDescription << "', '" // 描述
            << alarmData.strStartTime << "', '"   // 开始时间
            << alarmData.strEndTime << "')";      // 结束时间
            << alarmData.nId << ", "              // 错误码
            << alarmData.nSeverityLevel << ", "   // 报警等级
            << alarmData.nDeviceId << ", "        // 设备ID
            << alarmData.nUnitId << ", '"         // 单元ID
            << alarmData.strDescription << "', '" // 描述
            << alarmData.strStartTime << "', '"   // 开始时间
            << alarmData.strEndTime << "')";      // 结束时间
    
        // 使用锁保护多线程安全
        // 使用锁保护多线程安全
        std::lock_guard<std::mutex> lock(m_mutex);
    
        // 执行插入查询
        // 执行插入查询
        bool result = m_pDB->executeQuery(query.str());
        if (result) {
            alarmEventId = getLastInsertId();
            m_alarmCache[alarmEventId] = alarmData;
        }
    
        // 提交事务
        // 提交事务
        m_pDB->executeQuery("COMMIT;");
    
        return result;
@@ -273,23 +276,23 @@
            }
        }
        // 构建插入查询并使用 RETURNING 获取插入后的 alarm_event_id
        // 构建插入查询并使用 RETURNING 获取插入后的 alarm_event_id
        std::ostringstream query;
        query << "INSERT INTO alarms (id, severity_level, device_id, unit_id, description, start_time, end_time) "
            << "VALUES (" << alarmData.nId << ", " << alarmData.nSeverityLevel << ", " << alarmData.nDeviceId << ", "
            << alarmData.nUnitId << ", '" << alarmData.strDescription << "', '" << alarmData.strStartTime << "', '"
            << alarmData.strEndTime << "') RETURNING alarm_event_id;";
    
        // 使用锁保护多线程安全
        // 使用锁保护多线程安全
        std::lock_guard<std::mutex> lock(m_mutex);
    
        // 执行查询并获取结果
        // 执行查询并获取结果
        auto results = m_pDB->fetchResults(query.str());
        if (!results.empty() && !results[0].empty()) {
            try {
                // 提取并转换 alarm_event_id
                // 提取并转换 alarm_event_id
                alarmEventId = std::stoi(results[0][0]);
                // 将插入的报警数据添加到缓存
                // 将插入的报警数据添加到缓存
                m_mapCache[alarmEventId] = alarmData;
                return true;
            }
@@ -303,13 +306,13 @@
    #endif
}
// 查询所有报警数据
// 查询所有报警数据
std::vector<AlarmData> AlarmManager::getAllAlarms() {
    if (!m_pDB) {
        return {};
    }
    // 查询所有报警数据(包括设备名称和单元名称)
    // 查询所有报警数据(包括设备名称和单元名称)
    const std::string query = R"(
        SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time
        FROM alarms a
@@ -319,19 +322,19 @@
    auto results = m_pDB->fetchResults(query);
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -339,7 +342,7 @@
    return alarms;
}
// 根据报警ID查询报警
// 根据报警ID查询报警
std::vector<AlarmData> AlarmManager::getAlarmsById(const std::string& id) {
    if (!m_pDB) {
        return {};
@@ -355,19 +358,19 @@
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -375,7 +378,7 @@
    return alarms;
}
// 根据描述查询报警
// 根据描述查询报警
std::vector<AlarmData> AlarmManager::getAlarmsByDescription(const std::string& description) {
    if (!m_pDB) {
        return {};
@@ -391,19 +394,19 @@
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -411,7 +414,7 @@
    return alarms;
}
// 根据时间范围查询报警
// 根据时间范围查询报警
std::vector<AlarmData> AlarmManager::getAlarmsByTimeRange(const std::string& startTime, const std::string& endTime) {
    if (!m_pDB) {
        return {};
@@ -434,19 +437,19 @@
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -454,7 +457,7 @@
    return alarms;
}
// 根据ID、开始时间和结束时间查询报警
// 根据ID、开始时间和结束时间查询报警
std::vector<AlarmData> AlarmManager::getAlarmsByIdAndTimeRange(const std::string& id, const std::string& startTime, const std::string& endTime) {
    if (!m_pDB) {
        return {};
@@ -477,19 +480,19 @@
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -497,7 +500,7 @@
    return alarms;
}
// 分页查询报警数据
// 分页查询报警数据
std::vector<AlarmData> AlarmManager::getAlarms(int startPosition, int count) {
    if (!m_pDB) {
        return {};
@@ -513,19 +516,19 @@
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarmData.nId = std::stoi(row[0]);              // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);   // 报警等级
        alarmData.nDeviceId = std::stoi(row[2]);        // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);          // 单元ID
        alarmData.strDeviceName = row[4];               // 设备名称
        alarmData.strUnitName = row[5];                 // 单元名称
        alarmData.strDescription = row[6];              // 描述
        alarmData.strStartTime = row[7];                // 开始时间
        alarmData.strEndTime = row[8];                  // 结束时间
        alarms.push_back(alarmData);
    }
@@ -533,7 +536,86 @@
    return alarms;
}
// 筛选报警数据
// 获取当前未结束的报警(end_time 为空),并可按 start_time 最近 N 小时过滤
std::vector<AlarmData> AlarmManager::getActiveAlarms(int recentHours /*=12*/) {
    if (!m_pDB) {
        return {};
    }
    // 计算时间阈值:当前时间减 recentHours
    std::string cutoffTime;
    if (recentHours > 0) {
        using namespace std::chrono;
        auto cutoff = system_clock::now() - hours(recentHours);
        std::time_t t = system_clock::to_time_t(cutoff);
        std::tm tm {};
        localtime_s(&tm, &t);
        char buf[32] = { 0 };
        std::strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", &tm);
        cutoffTime = buf;
    }
    std::ostringstream query;
    query << R"(
        SELECT a.id, a.severity_level, a.device_id, a.unit_id, d.device_name, u.unit_name, a.description, a.start_time, a.end_time
        FROM alarms a
        JOIN devices d ON a.device_id = d.device_id
        JOIN units u ON a.device_id = u.device_id AND a.unit_id = u.unit_id
        WHERE a.end_time IS NULL OR a.end_time = ''
    )";
    if (!cutoffTime.empty()) {
        query << " AND a.start_time >= '" << cutoffTime << "'";
    }
    query << " ORDER BY a.start_time DESC";
    auto lastErrStr = []() -> std::string {
        DWORD gle = GetLastError();
        if (gle == 0) return {};
        LPSTR buf = nullptr;
        size_t len = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
            nullptr, gle, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&buf, 0, nullptr);
        std::string s = (buf && len > 0) ? std::string(buf, len) : "";
        if (buf) LocalFree(buf);
        return s;
    };
    std::vector<std::vector<std::string>> results;
    try {
        results = m_pDB->fetchResults(query.str());
    }
    catch (const std::exception& ex) {
        DWORD gle = GetLastError();
        auto errStr = lastErrStr();
        LOGE("<AlarmManager>getActiveAlarms failed: %s, GLE=%lu (%s)", ex.what(), gle, errStr.c_str());
        return {};
    }
    std::vector<AlarmData> alarms;
    auto toInt = [](const std::string& s) -> int {
        try {
            return std::stoi(s);
        }
        catch (...) {
            return 0;
        }
    };
    for (const auto& row : results) {
        if (row.size() < 9) continue;
        AlarmData alarmData;
        alarmData.nId = toInt(row[0]);
        alarmData.nSeverityLevel = toInt(row[1]);
        alarmData.nDeviceId = toInt(row[2]);
        alarmData.nUnitId = toInt(row[3]);
        alarmData.strDeviceName = row[4];
        alarmData.strUnitName = row[5];
        alarmData.strDescription = row[6];
        alarmData.strStartTime = row[7];
        alarmData.strEndTime = row[8];
        alarms.push_back(alarmData);
    }
    return alarms;
}
// 筛选报警数据
std::vector<AlarmData> AlarmManager::getFilteredAlarms(const std::string& keyword, const std::string& startTime, const std::string& endTime, int pageNumber, int pageSize) {
    if (!m_pDB) {
        return {};
@@ -547,7 +629,7 @@
        JOIN units u   ON a.device_id = u.device_id AND a.unit_id = u.unit_id
        WHERE 1=1)";
    // 统一关键字模糊查询
    // 统一关键字模糊查询
    if (!keyword.empty()) {
        query << " AND ("
            << "a.id LIKE '%" << keyword << "%' OR "
@@ -557,7 +639,7 @@
            << "a.description LIKE '%" << keyword << "%')";
    }
    // 时间条件
    // 时间条件
    if (!startTime.empty()) {
        query << " AND a.start_time >= '" << startTime << "'";
    }
@@ -565,26 +647,26 @@
        query << " AND a.end_time <= '" << endTime << "'";
    }
    // 分页设置
    // 分页设置
    int nOffset = (pageNumber - 1) * pageSize;
    query << " ORDER BY a.start_time DESC LIMIT " << pageSize << " OFFSET " << nOffset;
    // 查询
    // 查询
    auto results = m_pDB->fetchResults(query.str());
    // 遍历查询结果,填充 AlarmData 结构体
    // 遍历查询结果,填充 AlarmData 结构体
    std::vector<AlarmData> alarms;
    for (const auto& row : results) {
        AlarmData alarmData;
        alarmData.nId = std::stoi(row[0]);             // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);  // 报警等级 (字符串)
        alarmData.nDeviceId = std::stoi(row[2]);       // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);         // 单元ID
        alarmData.strDeviceName = row[4];              // 设备名称
        alarmData.strUnitName = row[5];                // 单元名称
        alarmData.strDescription = row[6];             // 描述
        alarmData.strStartTime = row[7];               // 开始时间
        alarmData.strEndTime = row[8];                 // 结束时间
        alarmData.nId = std::stoi(row[0]);             // 错误码
        alarmData.nSeverityLevel = std::stoi(row[1]);  // 报警等级 (字符串)
        alarmData.nDeviceId = std::stoi(row[2]);       // 设备ID
        alarmData.nUnitId = std::stoi(row[3]);         // 单元ID
        alarmData.strDeviceName = row[4];              // 设备名称
        alarmData.strUnitName = row[5];                // 单元名称
        alarmData.strDescription = row[6];             // 描述
        alarmData.strStartTime = row[7];               // 开始时间
        alarmData.strEndTime = row[8];                 // 结束时间
        alarms.push_back(alarmData);
    }
@@ -592,7 +674,7 @@
    return alarms;
}
// 获取符合条件的报警总数
// 获取符合条件的报警总数
int AlarmManager::getTotalAlarmCount(const std::string& keyword, const std::string& startTime, const std::string& endTime) {
    if (!m_pDB) {
        return 0;
@@ -606,7 +688,7 @@
        JOIN units u   ON a.device_id = u.device_id AND a.unit_id = u.unit_id
        WHERE 1=1)";
    // 统一关键字模糊查询
    // 统一关键字模糊查询
    if (!keyword.empty()) {
        query << " AND ("
            << "a.id LIKE '%" << keyword << "%' OR "
@@ -616,7 +698,7 @@
            << "a.description LIKE '%" << keyword << "%')";
    }
    // 时间条件
    // 时间条件
    if (!startTime.empty()) {
        query << " AND a.start_time >= '" << startTime << "'";
    }
@@ -628,7 +710,7 @@
    return (!results.empty() && !results[0].empty()) ? std::stoi(results[0][0]) : 0;
}
// 更新报警的结束时间
// 更新报警的结束时间
bool AlarmManager::updateAlarmEndTime(
    const std::string& id,
    const std::string& severityLevel,
@@ -642,7 +724,7 @@
        return false;
    }
    // 更新报警结束时间
    // 更新报警结束时间
    std::ostringstream updateQuery;
    updateQuery << "UPDATE alarms SET end_time = '" << newEndTime << "'"
        << " WHERE id = '" << id << "'"
@@ -655,7 +737,7 @@
    return m_pDB->executeQuery(updateQuery.str());
}
// 清理旧报警数据
// 清理旧报警数据
void AlarmManager::cleanOldAlarms(int daysToKeep, const std::string& deviceId, const std::string& unitId) {
    if (!m_pDB) {
        return;
@@ -674,7 +756,7 @@
    m_pDB->executeQuery(query.str());
}
// 通过设备ID获取设备名称
// 通过设备ID获取设备名称
std::string AlarmManager::getDeviceNameById(int deviceId) {
    if (!m_pDB) {
        return "";
@@ -688,10 +770,10 @@
        return "";
    }
    return result[0][0];  // 返回查询到的设备名称
    return result[0][0];  // 返回查询到的设备名称
}
// 通过设备ID和单元ID获取单元名称
// 通过设备ID和单元ID获取单元名称
std::string AlarmManager::getUnitNameById(int deviceId, int unitId) {
    if (!m_pDB) {
        return "";
@@ -706,10 +788,10 @@
        return "";
    }
    return result[0][0];  // 返回查询到的单元名称
    return result[0][0];  // 返回查询到的单元名称
}
// 获取最近插入的 alarm_event_id
// 获取最近插入的 alarm_event_id
int AlarmManager::getLastInsertId() {
    std::string query = "SELECT last_insert_rowid();";
    auto results = m_pDB->fetchResults(query);
@@ -718,12 +800,12 @@
        return -1;
    }
    // 从查询结果中获取最后插入的 ID
    // 从查询结果中获取最后插入的 ID
    int lastInsertId = std::stoi(results[0][0]);
    return lastInsertId;
}
// 通过 alarm_event_id 解除报警(更新结束时间)
// 通过 alarm_event_id 解除报警(更新结束时间)
bool AlarmManager::clearAlarmByEventId(int alarmEventId, const std::string& endTime) {
    if (!m_pDB) {
        return false;
@@ -745,7 +827,7 @@
    return result;
}
// 通过多个属性查找并解除报警(更新结束时间)
// 通过多个属性查找并解除报警(更新结束时间)
bool AlarmManager::clearAlarmByAttributes(int nId, int nDeviceId, int nUnitId, const std::string& endTime) {
    if (!m_pDB) {
        return false;
@@ -753,7 +835,7 @@
    std::lock_guard<std::mutex> lock(m_mutex);
    // 先在缓存中查找匹配的 alarm_event_id
    // 先在缓存中查找匹配的 alarm_event_id
    int alarmEventId = -1;
    for (AlarmDataMap::const_iterator it = m_mapCache.begin(); it != m_mapCache.end(); ++it) {
        const AlarmData& alarm = it->second;
@@ -766,12 +848,32 @@
        }
    }
    // 如果没找到匹配的记录,则直接返回 false
    if (alarmEventId == -1) {
        return false;
    }
   // 缓存未命中时,从数据库查找仍未结束的记录(取最新一条)
   if (alarmEventId == -1) {
      std::ostringstream querySel;
      querySel << "SELECT alarm_event_id FROM alarms WHERE "
         << "id = " << nId
         << " AND device_id = " << nDeviceId
         << " AND unit_id = " << nUnitId
         << " AND (end_time IS NULL OR end_time = '') "
         << "ORDER BY start_time DESC LIMIT 1;";
      auto results = m_pDB->fetchResults(querySel.str());
      if (!results.empty() && !results[0].empty()) {
         try {
            alarmEventId = std::stoi(results[0][0]);
         }
         catch (...) {
            alarmEventId = -1;
         }
      }
   }
    // 构建 SQL 语句,使用找到的 alarm_event_id 来更新结束时间
   // 如果没找到匹配的记录,则直接返回 false
   if (alarmEventId == -1) {
      return false;
   }
    // 构建 SQL 语句,使用找到的 alarm_event_id 来更新结束时间
    std::ostringstream query;
    query << "UPDATE alarms SET end_time = '" << endTime << "' WHERE alarm_event_id = " << alarmEventId << ";";
    bool result = m_pDB->executeQuery(query.str());
@@ -782,7 +884,7 @@
    return result;
}
// 读取报警文件
// 读取报警文件
bool AlarmManager::readAlarmFile(const std::string& filename) {
    std::ifstream file(filename, std::ios::binary);
    if (!file.is_open()) {
@@ -795,7 +897,7 @@
        char ch;
        while (f.get(ch)) {
            if (ch == '\r') {
                // 处理 \r\n 或 单独 \r
                // 处理 \r\n 或 单独 \r
                if (f.peek() == '\n') f.get();
                break;
            }
@@ -850,19 +952,19 @@
    return true;
}
// 将报警数据保存到文件
// 将报警数据保存到文件
bool AlarmManager::saveAlarmFile(const std::string& filename) {
    std::ofstream file(filename);
    if (!file.is_open()) {
        std::cerr << "打开文件写入失败!" << std::endl;
        std::cerr << "打开文件写入失败!" << std::endl;
        return false;
    }
    // 写入标题行
    // 写入标题行
    file << "No,UNIT ID,UNIT NO,Alarm Level,Alarm Code,AlarmID,Alarm Text,Description\n";
    // 写入报警数据
    // 写入报警数据
    int nIndex = 1;
    for (const auto& pair : m_mapAlarm) {
        const AlarmInfo& alarm = pair.second;
@@ -880,19 +982,19 @@
    return true;
}
// 通过 AlarmID 查询对应的报警信息
// 通过 AlarmID 查询对应的报警信息
const AlarmInfo* AlarmManager::getAlarmInfoByID(int nAlarmID) const {
    auto it = m_mapAlarm.find(nAlarmID);
    if (it != m_mapAlarm.end()) {
        return &(it->second);
    }
    else {
        std::cerr << "未找到 AlarmID: " << nAlarmID << std::endl;
        std::cerr << "未找到 AlarmID: " << nAlarmID << std::endl;
        return nullptr;
    }
}
// 通过多个 AlarmID 查询对应的报警信息
// 通过多个 AlarmID 查询对应的报警信息
std::vector<AlarmInfo> AlarmManager::getAlarmsInfoByIDs(const std::vector<int>& alarmIDs) const {
    std::vector<AlarmInfo> alarms;
@@ -902,7 +1004,7 @@
            alarms.push_back(it->second);
        } 
        else {
            std::cerr << "未找到 AlarmID: " << alarmID << std::endl;
            std::cerr << "未找到 AlarmID: " << alarmID << std::endl;
        }
    }